From: Michael D. Lowis Date: Wed, 21 Apr 2021 19:46:00 +0000 (-0400) Subject: added module-level variable declarations X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=fb581587aa68677c21837a147b5a367204ea57d3;p=proto%2Fobnc.git added module-level variable declarations --- diff --git a/cerise/parser.c b/cerise/parser.c index 16609c4..e166ccb 100644 --- a/cerise/parser.c +++ b/cerise/parser.c @@ -8,7 +8,7 @@ void name##_actual(Parser* p, Item* item); \ void name(Parser* p, Item* item) { \ printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \ - name##_actual(p); \ + name##_actual(p, item); \ Indent--; } \ void name##_actual(Parser* p, Item* item) #else @@ -402,7 +402,44 @@ RULE(expression) RULE(var_decl) { - (void)p, (void)item; + (void)item; + int nsyms = 0; + Symbol* sym = NULL; + Symbol* type = NULL; + char* name = NULL; + bool export = false; + + while (1) + { + name = expect_text(p, IDENT); + export = accept(p, '*'); + sym = symbol_new(p, name, SYM_CONST, export); + nsyms++; + + if (!accept(p, ',')) + { + break; + } + } + + expect(p, ':'); + name = expect_text(p, IDENT); + type = symbol_get(p, name); + if (!type) + { + error(p, "unknown type identifier '%'\n", name); + } + if (type->class != SYM_TYPE) + { + error(p, "'%' is not a type identifier\n", name); + } + + /* apply the type to the newly created symbols */ + for (int i = 0; i < nsyms; i++) + { + sym->type = type->type; + sym = sym->next; + } } RULE(type_decl) @@ -412,12 +449,12 @@ RULE(type_decl) RULE(const_decl) { + char* name = NULL; + bool export = false; + Symbol* sym = NULL; + while (1) { - char* name = NULL; - bool export = false; - Symbol* sym = NULL; - name = expect_text(p, IDENT); export = accept(p, '*'); sym = symbol_new(p, name, SYM_CONST, export); @@ -446,12 +483,12 @@ RULE(declaration_seq) } if (accept(p, TYPE)) { -// type_decl(p, item); + type_decl(p, item); expect(p, ';'); } if (accept(p, VAR)) { -// var_decl(p, item); + var_decl(p, item); expect(p, ';'); } } @@ -482,17 +519,21 @@ RULE(module) char* sname = expect_text(p, IDENT); /* TODO: Check that it matches filename here */ expect(p, ';'); + if (matches(p, IMPORT)) { import_list(p, item); } + declaration_seq(p, item); + if (accept(p, BEGIN)) { codegen_startproc(0); statement_seq(p, item); codegen_endproc(); } + expect(p, END); char* ename = expect_text(p, IDENT); if (strcmp(sname, ename)) @@ -538,6 +579,8 @@ TEST_SUITE(Grammar) { parse_module("Empty", "module Empty; end Empty;"); parse_module("ModA", "module ModA; import ModB; end ModA;"); + parse_module("ModA", "module ModA; const FOO = 42; end ModA;"); + parse_module("ModA", "module ModA; var foo : Int; end ModA;"); } TEST(Should parse imports) @@ -579,5 +622,13 @@ TEST_SUITE(Grammar) parse_rule(const_decl, 0, "FOO = 5 >= 3"); parse_rule(const_decl, 0, "FOO = 5, BAR = FOO - 3"); } + + TEST(Should module level variable declarations) + { + parse_rule(var_decl, 0, "i : Int"); + parse_rule(var_decl, 0, "i : Real"); + parse_rule(var_decl, 0, "i : Bool"); + parse_rule(var_decl, 0, "x,y,z : Int"); + } } #endif