static AST* if_expression(Parser* p);
static AST* identifier(Parser* p);
static AST* expr_list(Parser* p, int firstc, int endc);
+static AST* prefix_expr(Parser* p);
+static AST* binary_expr(Parser* p, AST* left);
//#define TRACE
#ifdef TRACE
#define parse_exit()
#endif
-typedef struct {
- int precedence;
- int token;
- AST* (*parse)(Parser* p, AST* expr);
-} OpDef_T;
-
-AST* if_expr(Parser* p, AST* expr);
-AST* block_expr(Parser* p, AST* expr);
-AST* paren_expr(Parser* p, AST* expr);
-AST* binop_expr(Parser* p, AST* expr);
-AST* fncall_expr(Parser* p, AST* expr);
-
-OpDef_T PrefixOps[] = {
- { 0, T_IF, if_expr }, /* If expression */
- { 0, '{', block_expr }, /* Expression block */
- { 0, '(', paren_expr }, /* Parenthese grouping */
+uint8_t PrefixOps[T_COUNT] = {
+ [T_IF] = 1,
+ ['{'] = 1,
+ ['('] = 1,
};
-OpDef_T InfixOps[] = {
- { 0, '.', binop_expr }, /* If expression */
- { 0, '(', fncall_expr }, /* Parenthese grouping */
+uint8_t BinaryOps[T_COUNT] = {
+ ['.'] = 1,
+ ['('] = 1,
};
-/* Operator Parsing Routines
- *****************************************************************************/
-AST* if_expr(Parser* p, AST* expr) {
- return NULL;
-}
-
-AST* block_expr(Parser* p, AST* expr) {
- return NULL;
-}
-
-AST* paren_expr(Parser* p, AST* expr) {
- return NULL;
-}
-
-AST* binop_expr(Parser* p, AST* expr) {
- return NULL;
-}
-
-AST* fncall_expr(Parser* p, AST* expr) {
- return NULL;
-}
-
/* Parsing Routines
*****************************************************************************/
static Tok* peek(Parser* p) {
return Var(name, func, type, SF_CONSTANT);
}
-static AST* member_access(Parser* p);
-static AST* parenthesized(Parser* p);
-static AST* literal(Parser* p);
-
static AST* expression(Parser* p) {
parse_enter();
- AST* exp;
- if (matches(p, '{')) {
- exp = expression_block(p);
- } else if (matches(p, T_IF)) {
- exp = if_expression(p);
- } else {
- exp = member_access(p);
- /* check for function call syntax */
- if (matches(p, '('))
- exp = Apply(exp, expr_list(p, '(', ')'));
- }
- parse_exit();
- return exp;
-}
-
-static AST* member_access(Parser* p) {
- parse_enter();
- AST* exp = parenthesized(p);
- if (accept(p, '.')) {
- AST* field = identifier(p);
- // TODO: convert access to an apply or dedicated AST type
- }
- parse_exit();
- return exp;
-}
-
-static AST* parenthesized(Parser* p) {
- parse_enter();
- AST* exp;
- if (matches(p, '(')) {
- expect(p, '(');
- exp = expression(p);
- expect(p, ')');
- } else {
- exp = literal(p);
+ int precedence = PrefixOps[peek(p)->type];
+ AST* left = prefix_expr(p);
+ int next = peek(p)->type;
+ while (BinaryOps[next] && BinaryOps[next] >= precedence) {
+ left = binary_expr(p, left);
+ next = peek(p)->type;
}
parse_exit();
- return exp;
+ return left;
}
-static AST* literal(Parser* p) {
- parse_enter();
- AST* exp;
- if (matches(p, '[')) {
- exp = expr_list(p, '[', ']');
- } else if (matches(p, T_ID)) {
- exp = identifier(p);
- // TODO: Struct init here?
- } else {
- exp = constant(p);
+static AST* prefix_expr(Parser* p) {
+ AST* tree = NULL;
+ Tok* tok = peek(p);
+ switch ((int)tok->type) {
+ case '(':
+ expect(p, '(');
+ tree = expression(p);
+ expect(p, ')');
+ break;
+ case '[':
+ tree = expr_list(p, '[', ']');
+ break;
+ case '{':
+ tree = expression_block(p);
+ break;
+ case T_IF:
+ tree = if_expression(p);
+ break;
+ case T_BOOL:
+ tree = Bool(tok->value.integer);
+ accept(p, tok->type);
+ break;
+ case T_CHAR:
+ tree = Char(tok->value.integer);
+ accept(p, tok->type);
+ break;
+ case T_STRING:
+ tree = String(tok->text);
+ accept(p, tok->type); break;
+ case T_INT:
+ tree = Integer(tok->value.integer);
+ accept(p, tok->type);
+ break;
+ case T_FLOAT:
+ tree = Float(tok->value.floating);
+ accept(p, tok->type);
+ break;
+ case T_ID:
+ tree = Ident(tok->text);
+ accept(p, tok->type);
+ break;
+ default:
+ error(p, "expected an expression");
}
- parse_exit();
- return exp;
+ return tree;
}
-static AST* constant(Parser* p) {
- parse_enter();
- AST* tree = NULL;
+static AST* binary_expr(Parser* p, AST* left) {
+ AST* exp = NULL;
Tok* tok = peek(p);
- switch (tok->type) {
- case T_BOOL: tree = Bool(tok->value.integer); break;
- case T_CHAR: tree = Char(tok->value.integer); break;
- case T_STRING: tree = String(tok->text); break;
- case T_INT: tree = Integer(tok->value.integer); break;
- case T_FLOAT: tree = Float(tok->value.floating); break;
- case T_ID: tree = Ident(tok->text); break;
- default: error(p, "expected an expression");
+ switch ((int)tok->type) {
+ case '(':
+ exp = Apply(left, expr_list(p, '(', ')'));
+ break;
+ case '.':
+ expect(p, '.');
+ AST* field = identifier(p);
+ exp = left;
+ break;
}
- accept(p, tok->type);
- parse_exit();
- return tree;
+ return exp;
}
/* Type Expressions