// factor -> unary ( ( "/" | "*" ) unary )* ;
// unary -> ( "!" | "-" ) unary
// | primary ;
+// access -> IDENT "." ( access | IDENT )
// subscript -> IDENT "[" ast "]"
// funcalls -> IDENT "(" ( ast "," )* ")" | IDENT "(" ast ")"
// suffix -> IDENT ( "++" | "--" )
* --------------------+-------------------------------------+-----------+-----
* Struct/Union access | . | Left | NOTE: We use . to access through pointers as well
* --------------------+-------------------------------------+-----------+-----
- * Array Subscripting | [] | Left |
+ * Array Subscripting | [] | Left | X
* --------------------+-------------------------------------+-----------+-----
* Function Call | () | Left | X
* --------------------+-------------------------------------+-----------+-----
typedef struct Binary_expr Binary_expr;
typedef struct Funcall_AST Funcall_AST;
typedef struct Subscript_AST Subscript_AST;
+typedef struct Access_AST Access_AST;
typedef struct Unary_expr Unary_expr;
typedef struct Primary_expr Primary_expr;
typedef struct AST AST;
AST *index_ast;
};
+typedef enum {
+ ACC_RHS_ACCESS,
+ ACC_RHS_IDENT,
+ ACC_RHS_COUNT,
+} Access_AST_rhs_kind;
+
+struct Access_AST {
+ Token lhs; // Eg: foo.bar // here `foo` is lhs
+ union {
+ Access_AST *access;
+ String_view ident_key;
+ } rhs_as;
+ Access_AST_rhs_kind rhs_kind;
+};
+
struct Binary_expr {
Token operator;
AST *lhs;
AST_PRIMARY,
AST_FUNCALL,
AST_SUBSCRIPT,
+ AST_ACCESS,
AST_COUNT,
} AST_kind;
Unary_expr *unary_expr;
Funcall_AST *funcall;
Subscript_AST *subscript;
+ Access_AST *access;
Location loc;
};
case AST_PRIMARY: return "PRIMARY";
case AST_FUNCALL: return "FUNCALL";
case AST_SUBSCRIPT: return "SUBSCRIPT";
+ case AST_ACCESS: return "ACCESS";
case AST_COUNT:
default: ASSERT(false, "UNREACHABLE!");
}
// }
fprintf(f, "]");
} break;
+ case AST_ACCESS: {
+ fprintf(f, SV_FMT, SV_ARG(e.access->lhs.lexeme));
+ fprintf(f, ".");
+ switch (e.access->rhs_kind) {
+ case ACC_RHS_ACCESS: {
+
+ } break;
+ case ACC_RHS_IDENT: {
+ fprintf(f, SV_FMT, SV_ARG(e.access->rhs_as.ident_key));
+ } break;
+ case ACC_RHS_COUNT:
+ default:
+ ASSERT(false, "UNREACHABLE!");
+ }
+ } break;
+
case AST_COUNT:
default: ASSERT(false, "UNREACHABLE!");
}
AST *parse_suffix(Arena *arena, Parser *p);
AST *parse_funcall(Arena *arena, Parser *p);
AST *parse_subscript(Arena *arena, Parser *p);
+AST *parse_access(Arena *arena, Parser *p);
AST *parse_unary(Arena *arena, Parser *p);
AST *parse_factor(Arena *arena, Parser *p);
AST *parse_comparision(Arena *arena, Parser *p);
return parse_funcall(arena, p);
}
+AST *parse_access(Arena *arena, Parser *p) {
+ Token t = parser_peek(p);
+
+ if (t.type == TK_IDENT && parser_peek_by(p, 1).type == TK_DOT) {
+
+ AST *ast = (AST *)arena_alloc(arena, sizeof(AST));
+ ast->loc = t.loc;
+ ast->access = (Access_AST *)arena_alloc(arena, sizeof(Access_AST));
+ ast->kind = AST_ACCESS;
+ ast->access->lhs = parser_advance(p); // Eat IDENT
+
+ parser_advance(p); // Skip .
+
+ Token next = parser_peek(p);
+
+ if (next.type == TK_IDENT) {
+ ast->access->rhs_kind = ACC_RHS_IDENT;
+ ast->access->rhs_as.ident_key = next.lexeme;
+ parser_advance(p); // Eat IDENT
+ return ast;
+ } else {
+ }
+
+ ASSERT(false, "parse_access() is unimplemented!");
+ }
+
+ return parse_subscript(arena, p);
+}
+
AST *parse_unary(Arena *arena, Parser *p) {
Token t = parser_peek(p);
return ast;
}
- return parse_subscript(arena, p);
+ return parse_access(arena, p);
}
AST *parse_factor(Arena *arena, Parser *p) {
case ',': {
LEX_N_CHAR_TOKEN(TK_COMMA, 1);
} break;
+ case '.': {
+ LEX_N_CHAR_TOKEN(TK_DOT, 1);
+ } break;
// NOTE: Sanity check
case ' ': {
consume_char(l);