Author | Jakob Wakeling <[email protected]> |
Date | 2022-04-19 08:03:53 |
Commit | 38468186153fa035ab9a2fcafaa533175e3f9a33 |
Parent | c2c12178e8195a0c613d25d12c276bd9dc385557 |
Handle unary operators with op_lookup
Diffstat
M | src/parse.c | | | 63 | ++++++++++++++++++++++++++++++++++++++++----------------------- |
M | src/parse.h | | | 1 | + |
2 files changed, 41 insertions, 23 deletions
diff --git a/src/parse.c b/src/parse.c index 903d5e2..383844b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -15,11 +15,14 @@ #include <stdlib.h> #include <string.h> +typedef struct { tok_k tk; ast_k ak; s32 o; bool as; } op; + char *ast_ks[] = { "AK_NULL", "AK_PROG", "AK_PROC", "AK_TYPE", "AK_STMT", "AK_COMP", "AK_DECL", "AK_RETURN", "AK_IF", "AK_FOR", + "AK_OP_POS", "AK_OP_NEG", "AK_OP_ADD", "AK_OP_SUB", "AK_OP_MUL", "AK_OP_DIV", "AK_OP_MOD", "AK_VAR", "AK_INT", @@ -38,6 +41,8 @@ static ast *parse_expr_proc(lex *l, syt *st); static ast *parse_int(lex *l, syt *st); +static op op_lookup(tok_k tk, bool unary); + /* Initialise an AST node. */ ast *ast_init(void) { ast *a = calloc(1, sizeof (ast)); @@ -183,22 +188,6 @@ static ast *parse_stmt_for(lex *l, syt *st) { ast_push(a, parse_stmt(l, st)); return a; } -typedef struct { tok_k tk; ast_k ak; s32 o; bool as; } op; - -static const op ops[] = { - { TK_OP_MUL, AK_OP_MUL, 2, false }, - { TK_OP_DIV, AK_OP_DIV, 2, false }, - { TK_OP_MOD, AK_OP_MOD, 2, false }, - { TK_OP_ADD, AK_OP_ADD, 1, false }, - { TK_OP_SUB, AK_OP_SUB, 1, false }, -}; - -static inline op ops_lookup(tok_k k) { - for (UINT i = 0; i < (sizeof (ops) / sizeof (*ops)); i += 1) { - if (k == ops[i].tk) { return ops[i]; } - } return (op){ 0 }; -} - static inline void shunt(ast_a *aa, tok t, op o) { ast *r = ast_a_pop(aa); ast *l = ast_a_pop(aa); @@ -232,7 +221,7 @@ static ast *parse_expr(lex *l, syt *st) { if (t.k == TK_NULL) { error(1, "todo: error: expected left parenthesis"); } if (t.k == TK_LPAREN) { break; } - shunt(&as, t, ops_lookup(t.k)); + shunt(&as, t, op_lookup(t.k, false)); } /* TODO handle procedure calls */ @@ -240,10 +229,10 @@ static ast *parse_expr(lex *l, syt *st) { lex_next(l); } break; default: /* Handle operators */ { - op o1; if ((o1 = ops_lookup(T.k)).tk == TK_NULL) { goto eox; } + op o1, o2; if ((o1 = op_lookup(T.k, false)).tk == TK_NULL) { goto eox; } - for (op o2 = ops_lookup(tok_a_peek(&ts).k);; o2 = ops_lookup(tok_a_peek(&ts).k)) { - if (o2.tk == TK_LPAREN || (o1.o > o2.o && (o1.o != o2.o || o1.as == true))) { break; } + for (o2 = op_lookup(tok_a_peek(&ts).k, false);; o2 = op_lookup(tok_a_peek(&ts).k, false)) { + if (o2.tk == TK_LPAREN || (o1.o < o2.o && (o1.o != o2.o || o1.as == true))) { break; } shunt(&as, tok_a_pop(&ts), o2); } @@ -257,7 +246,7 @@ static ast *parse_expr(lex *l, syt *st) { if (t.k == TK_LPAREN) { error(1, "LPAREN: TODO"); } if (t.k == TK_RPAREN) { error(1, "RPAREN: TODO"); } - shunt(&as, t, ops_lookup(t.k)); + shunt(&as, t, op_lookup(t.k, false)); } return ast_a_pop(&as); @@ -297,14 +286,37 @@ static ast *parse_int(lex *l, syt *st) { ast *a = ast_init(); tok t = lex_kind(l, TK_INT); a->k = AK_INT; a->ln = t.ln; a->cl = t.cl; - a->t = &TYPE(TY_S64); /* TODO properly determine type */ - if (!(a->s = strdup(t.s))) { error(1, "%s", SERR); } if (!(a->v = val_parse_int(t.s)).k) { error(1, "%s: %s", t.s, SERR); } + /* Determine integer type */ + // if (a->v.v_int <= U8_MAX) { a->t = &TYPE(TY_U8); } + // else if (a->v.v_int <= U16_MAX) { a->t = &TYPE(TY_U16); } + // else if (a->v.v_int <= U32_MAX) { a->t = &TYPE(TY_U32); } + // else if (a->v.v_int <= U64_MAX) { a->t = &TYPE(TY_U64); } + + a->t = &TYPE(TY_S64); // TODO remove temporary hack + return a; } +/* Lookup the operator associated with a particular token. */ +static op op_lookup(tok_k tk, bool unary) { + if (unary) switch (tk) { + case TK_OP_ADD: { return (op){ TK_OP_ADD, AK_OP_POS, 2, true }; } + case TK_OP_SUB: { return (op){ TK_OP_SUB, AK_OP_NEG, 2, true }; } + default: { return (op){ 0 }; } break; + } + else switch (tk) { + case TK_OP_ADD: { return (op){ TK_OP_ADD, AK_OP_ADD, 4, false }; } break; + case TK_OP_SUB: { return (op){ TK_OP_SUB, AK_OP_SUB, 4, false }; } break; + case TK_OP_MUL: { return (op){ TK_OP_MUL, AK_OP_MUL, 3, false }; } break; + case TK_OP_DIV: { return (op){ TK_OP_DIV, AK_OP_DIV, 3, false }; } break; + case TK_OP_MOD: { return (op){ TK_OP_MOD, AK_OP_MOD, 3, false }; } break; + default: { return (op){ 0 }; } break; + }; +} + /* Recursively print an AST. */ void ast_print(ast *a, UINT i) { for (UINT j = 0; j != i; ++j) { printf(" "); } diff --git a/src/parse.h b/src/parse.h index f051e2c..9174273 100644 --- a/src/parse.h +++ b/src/parse.h @@ -19,6 +19,7 @@ typedef enum { AK_STMT, AK_COMP, AK_DECL, AK_RETURN, AK_IF, AK_FOR, + AK_OP_POS, AK_OP_NEG, AK_OP_ADD, AK_OP_SUB, AK_OP_MUL, AK_OP_DIV, AK_OP_MOD, AK_VAR, AK_INT,