]> git.mdlowis.com Git - proto/obnc.git/commitdiff
added module-level variable declarations
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 21 Apr 2021 19:46:00 +0000 (15:46 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 21 Apr 2021 19:46:00 +0000 (15:46 -0400)
cerise/parser.c

index 16609c4eb276235860373539bd8f3760f4705493..e166ccbe6dc70ec03cab3b700f1b1f57ad17c9db 100644 (file)
@@ -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