From 7e294076240eefb4df5a045581f96def7da6ae8e Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Thu, 29 Apr 2021 13:59:24 -0400 Subject: [PATCH] added parsing rules for array types --- cerise/oberon0/OSP.Mod | 80 ++++++++++++++++++++++++++++--------- cerise/src/grammar.c | 61 +++++++++++++++++++++++++--- cerise/tests/Module.m | 91 +++++++++++++++++++++++------------------- 3 files changed, 167 insertions(+), 65 deletions(-) diff --git a/cerise/oberon0/OSP.Mod b/cerise/oberon0/OSP.Mod index 7b0fb37..ef157dc 100644 --- a/cerise/oberon0/OSP.Mod +++ b/cerise/oberon0/OSP.Mod @@ -372,6 +372,7 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) ELSE OSS.Mark("END?") END + ELSIF sym = OSS.while THEN OSS.Get(sym); L := OSG.pc; @@ -383,6 +384,7 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) OSG.BJump(L); OSG.FixLink(x.a); Check(OSS.end, "no END") + ELSIF sym = OSS.repeat THEN OSS.Get(sym); L := OSG.pc; @@ -392,6 +394,7 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) expression(x); CheckBool(x); OSG.CBJump(x, L) + ELSE OSS.Mark("missing UNTIL"); OSS.Get(sym) @@ -424,33 +427,68 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) PROCEDURE Type(VAR type: OSG.Type); VAR obj, first: OSG.Object; x: OSG.Item; tp: OSG.Type; BEGIN type := OSG.intType; (*sync*) - IF (sym # OSS.ident) & (sym < OSS.array) THEN OSS.Mark("type?"); + IF (sym # OSS.ident) & (sym < OSS.array) THEN + OSS.Mark("type?"); REPEAT OSS.Get(sym) UNTIL (sym = OSS.ident) OR (sym >= OSS.array) END ; + IF sym = OSS.ident THEN - find(obj); OSS.Get(sym); - IF obj.class = OSG.Typ THEN type := obj.type ELSE OSS.Mark("type?") END + find(obj); + OSS.Get(sym); + IF obj.class = OSG.Typ THEN + type := obj.type + ELSE + OSS.Mark("type?") + END + ELSIF sym = OSS.array THEN - OSS.Get(sym); expression(x); - IF (x.mode # OSG.Const) OR (x.a < 0) THEN OSS.Mark("bad index") END ; - IF sym = OSS.of THEN OSS.Get(sym) ELSE OSS.Mark("OF?") END ; - Type(tp); NEW(type); type.form := OSG.Array; type.base := tp; - type.len := x.a; type.size := type.len * tp.size + OSS.Get(sym); + expression(x); + IF (x.mode # OSG.Const) OR (x.a < 0) THEN + OSS.Mark("bad index") + END ; + IF sym = OSS.of THEN + OSS.Get(sym) + ELSE + OSS.Mark("OF?") + END ; + Type(tp); + NEW(type); + type.form := OSG.Array; + type.base := tp; + type.len := x.a; + type.size := type.len * tp.size + ELSIF sym = OSS.record THEN - OSS.Get(sym); NEW(type); type.form := OSG.Record; type.size := 0; OpenScope; + OSS.Get(sym); + NEW(type); + type.form := OSG.Record; + type.size := 0; + OpenScope; REPEAT IF sym = OSS.ident THEN - IdentList(OSG.Fld, first); Type(tp); obj := first; + IdentList(OSG.Fld, first); + Type(tp); + obj := first; WHILE obj # NIL DO - obj.type := tp; obj.val := type.size; type.size := type.size + obj.type.size; obj := obj.next + obj.type := tp; + obj.val := type.size; + type.size := type.size + obj.type.size; + obj := obj.next END END ; - IF sym = OSS.semicolon THEN OSS.Get(sym) - ELSIF sym = OSS.ident THEN OSS.Mark("; ?") + IF sym = OSS.semicolon THEN + OSS.Get(sym) + ELSIF sym = OSS.ident THEN + OSS.Mark("; ?") END UNTIL sym # OSS.ident; - type.dsc := topScope.next; CloseScope; Check(OSS.end, "no END") - ELSE OSS.Mark("ident?") + type.dsc := topScope.next; + CloseScope; + Check(OSS.end, "no END") + + ELSE + OSS.Mark("ident?") END END Type; @@ -482,9 +520,15 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) IF sym = OSS.type THEN OSS.Get(sym); WHILE sym = OSS.ident DO - NewObj(obj, OSG.Typ); OSS.Get(sym); - IF sym = OSS.eql THEN OSS.Get(sym) ELSE OSS.Mark("=?") END ; - Type(obj.type); Check(OSS.semicolon, "; expected") + NewObj(obj, OSG.Typ); + OSS.Get(sym); + IF sym = OSS.eql THEN + OSS.Get(sym) + ELSE + OSS.Mark("=?") + END ; + Type(obj.type); + Check(OSS.semicolon, "; expected") END END ; diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index 58e9411..d0f8187 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -253,6 +253,32 @@ RULE(expression) } } +RULE(type) +{ + (void)item; + if (matches(p, IDENT)) + { + expect(p, IDENT); + } + else if (accept(p, ARRAY)) + { + expression(p, item); + if (item->mode != ITEM_CONST) + { + error(p, "non-constant array size"); + } + expect(p, OF); + type(p, item); + } + else if (accept(p, RECORD)) + { + } + else + { + error(p, "expected a type"); + } +} + RULE(var_decl) { (void)item; @@ -299,7 +325,26 @@ RULE(var_decl) RULE(type_decl) { - (void)p, (void)item; + char* name = NULL; + bool export = false; + Symbol* sym = NULL; + + while (1) + { + name = expect_text(p, IDENT); + export = accept(p, '*'); + sym = symbol_new(p, name, SYM_TYPE, export); + expect(p, '='); + type(p, item); +// expression(p, item); +// sym->imm = item->imm; +// sym->type = item->type; + + if (!matches(p, IDENT)) + { + break; + } + } } RULE(const_decl) @@ -313,6 +358,7 @@ RULE(const_decl) name = expect_text(p, IDENT); export = accept(p, '*'); sym = symbol_new(p, name, SYM_CONST, export); + expect(p, '='); expression(p, item); sym->imm = item->imm; @@ -450,6 +496,11 @@ RULE(module) expect(p, END); } codegen_endproc(p); + + if (!matches(p, END_FILE)) + { + error(p, "expected end of file"); + } } static inline char* file_load(char* path) @@ -523,10 +574,10 @@ TEST_SUITE(Grammar) { TEST(Should parse basic module syntax) { - 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;"); + parse_module("Empty", "module Empty"); + parse_module("ModA", "module ModA import ModB"); + parse_module("ModA", "module ModA const FOO = 42"); + parse_module("ModA", "module ModA var foo : Int"); } TEST(Should parse imports) diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 57fcc05..d73b8e4 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -1,58 +1,65 @@ module Module #import -# A = Foo -# B = Bar +# A = Foo +# B = Bar const - A = true - B = 42 + A = true + B = 42 + +type + TypeA = Int + TypeB = array 5 of Int + TypeC = array 5 of + array 10 of Int + TypeD = record var - a : Bool - b : Int - c : Int + a : Bool + b : Int + c : Int begin -# a = true; -# a = A; -# b = 24; -# b = B; +# a = true; +# a = A; +# b = 24; +# b = B; # -# # Unary ops -# b = +b; -# b = -b; +# # Unary ops +# b = +b; +# b = -b; # -# # Arithmetic ops -# c = b + 1; -# c = b - 1; -# c = b * 1; -# c = b / 1; -# c = b % 1; +# # Arithmetic ops +# c = b + 1; +# c = b - 1; +# c = b * 1; +# c = b / 1; +# c = b % 1; # -# # Comparison ops -# c = b == 1; -# c = b != 1; -# c = b < 1; -# c = b > 1; -# c = b <= 1; -# c = b >= 1; +# # Comparison ops +# c = b == 1; +# c = b != 1; +# c = b < 1; +# c = b > 1; +# c = b <= 1; +# c = b >= 1; # -# # Register ops -# c = 1 + b; -# c = 1 - b; -# c = 1 * b; +# # Register ops +# c = 1 + b; +# c = 1 - b; +# c = 1 * b; # -# c = b + b; +# c = b + b; # -# # Complex arithmetic -# c = b + b * b + b; - - if 1 == 1 then - c = 1; - elsif 2 == 2 then - c = 2; - else - c = 3; - end +# # Complex arithmetic +# c = b + b * b + b; +# + if 1 == 1 then + c = 1; + elsif 2 == 2 then + c = 2; + else + c = 3; + end end -- 2.49.0