From: Michael D. Lowis Date: Mon, 12 Jul 2021 16:40:17 +0000 (-0400) Subject: got basic expression parsing back up and running. Verified using constant evaluation... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2d50a45fcc671012c3712fda5146d0aec90f2461;p=proto%2Fobnc.git got basic expression parsing back up and running. Verified using constant evaluation logic --- diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index 44c7bc7..1d02883 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -157,7 +157,7 @@ void lexprintpos(Parser* p, FILE* file, Tok* tok); Tok* peek(Parser* p); void error(Parser* p, const char* fmt, ...); bool matches(Parser* p, TokType type); -bool matches_oneof(Parser* p, TokType types[]); +bool matches_oneof(Parser* p, const TokType types[]); bool accept(Parser* p, TokType type); void expect(Parser* p, TokType type); Tok* expect_val(Parser* p, TokType type); diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index a0eaaba..70c97cc 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -229,30 +229,29 @@ static AstNode* term(Parser* p) AstNode* expr = factor(p); -// while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0})) -// { -// Item right = { 0 }; -// int op = consume(p); -// factor(p, &right); -// switch(op) -// { -// case '*': -// case '/': -// case '%': -// check_nums(p, item, &right); -// codegen_binop(p, op, item, &right); -// break; -// -// case AND: -// check_bools(p, item, &right); -// codegen_binop(p, op, item, &right); -// break; -// -// default: -// assert(!"not supported"); -// break; -// } -// } + while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0})) + { + int op = consume(p); + AstNode* right = factor(p); + switch(op) + { + case '*': + case '/': + case '%': + check_nums(p, expr, right); + expr = ast_binop(op, expr, right); + break; + + case AND: + check_bools(p, expr, right); + expr = ast_binop(op, expr, right); + break; + + default: + assert(!"not supported"); + break; + } + } EXIT_RULE(); assert(expr != NULL); @@ -265,12 +264,12 @@ static AstNode* simple_expr(Parser* p) AstNode* expr; - /* first term and +/- */ + /* first term and +/- unary ops */ if (matches_oneof(p, (int[]){'+', '-', 0})) { - int op = consume(p); // OP + int op = consume(p); AstNode* operand = term(p); -// check_num(p, operand); + check_num(p, operand); expr = ast_unop(op, operand); } else @@ -278,22 +277,21 @@ static AstNode* simple_expr(Parser* p) expr = term(p); } -// /* optional second term and op */ -// while (matches_oneof(p, (int[]){'+', '-', OR, 0})) -// { -// Item right = { 0 }; -// int op = consume(p); -// term(p, &right); -// if (op == OR) -// { -// check_bools(p, item, &right); -// } -// else -// { -// check_nums(p, item, &right); -// } -// codegen_binop(p, op, item, &right); -// } + /* optional second term and binary ops */ + while (matches_oneof(p, (int[]){'+', '-', OR, 0})) + { + int op = consume(p); + AstNode* right = term(p); + if (op == OR) + { + check_bools(p, expr, right); + } + else + { + check_nums(p, expr, right); + } + expr = ast_binop(op, expr, right); + } EXIT_RULE(); assert(expr != NULL); @@ -302,20 +300,18 @@ static AstNode* simple_expr(Parser* p) static AstNode* expression(Parser* p) { + const int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, 0 }; ENTER_RULE(); -// int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 }; - AstNode* expr = simple_expr(p); -// if (matches_oneof(p, ops)) -// { -// Item right = { 0 }; -// int op = consume(p); -// simple_expr(p, &right); -// check_nums(p, item, &right); -// codegen_binop(p, op, item, &right); -// } + if (matches_oneof(p, ops)) + { + int op = consume(p); + AstNode* right = simple_expr(p); + check_nums(p, expr, right); + expr = ast_binop(op, expr, right); + } EXIT_RULE(); assert(expr != NULL); @@ -486,7 +482,7 @@ static AstNode* expression(Parser* p) static void const_decl(Parser* p) { -// ENTER_RULE(); + ENTER_RULE(); char* name = NULL; bool export = false; Symbol* sym = NULL; @@ -500,13 +496,9 @@ static void const_decl(Parser* p) sym->value = expression(p); ast_print(sym->value); puts(""); - (void)sym; /* TODO: put const value into symbol table */ -// ir_getconst(p, sym); -// sym->imm = item->imm; -// sym->type = item->type; } while (matches(p, IDENT)); -// EXIT_RULE(); + EXIT_RULE(); } //RULE(proc_decl, Item* item) @@ -586,7 +578,7 @@ static void const_decl(Parser* p) static void import_list(Parser* p) { -// ENTER_RULE(); + ENTER_RULE(); expect(p, IMPORT); do { @@ -612,7 +604,7 @@ static void import_list(Parser* p) m->next = p->imports; p->imports = m; } -// EXIT_RULE(); + EXIT_RULE(); } static void module(Parser* p) diff --git a/cerise/src/parse.c b/cerise/src/parse.c index c4e5d06..098986d 100644 --- a/cerise/src/parse.c +++ b/cerise/src/parse.c @@ -28,7 +28,7 @@ bool matches(Parser* p, TokType type) return (peek(p)->type == type); } -bool matches_oneof(Parser* p, TokType types[]) +bool matches_oneof(Parser* p, const TokType types[]) { for (int i = 0; types[i] != NONE; i++) { diff --git a/cerise/src/type_checks.c b/cerise/src/type_checks.c index 60d54ac..ff98dda 100644 --- a/cerise/src/type_checks.c +++ b/cerise/src/type_checks.c @@ -34,10 +34,14 @@ void check_num(Parser* p, AstNode* a) { check_real(p, a); } - else + else if (a->hdr.type->form == FORM_INT) { check_int(p, a); } + else + { + error(p, "numeric operation on non-numeric value"); + } } void check_nums(Parser* p, AstNode* a, AstNode* b) diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 192d9da..e41d143 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -8,9 +8,11 @@ const A = true B = 42 C = 42.0 - D = -42 - E = not A -# F = B + 1 - 1 + D = -B + E = -C + F = not A + G = B + 2 - 2 * 2 + H = false or A #type # TypeA = Int