ELSE\r
OSS.Mark("END?")\r
END\r
+\r
ELSIF sym = OSS.while THEN\r
OSS.Get(sym);\r
L := OSG.pc;\r
OSG.BJump(L);\r
OSG.FixLink(x.a);\r
Check(OSS.end, "no END")\r
+\r
ELSIF sym = OSS.repeat THEN\r
OSS.Get(sym);\r
L := OSG.pc;\r
expression(x);\r
CheckBool(x);\r
OSG.CBJump(x, L)\r
+\r
ELSE\r
OSS.Mark("missing UNTIL");\r
OSS.Get(sym)\r
PROCEDURE Type(VAR type: OSG.Type);\r
VAR obj, first: OSG.Object; x: OSG.Item; tp: OSG.Type;\r
BEGIN type := OSG.intType; (*sync*)\r
- IF (sym # OSS.ident) & (sym < OSS.array) THEN OSS.Mark("type?");\r
+ IF (sym # OSS.ident) & (sym < OSS.array) THEN\r
+ OSS.Mark("type?");\r
REPEAT OSS.Get(sym) UNTIL (sym = OSS.ident) OR (sym >= OSS.array)\r
END ;\r
+\r
IF sym = OSS.ident THEN\r
- find(obj); OSS.Get(sym);\r
- IF obj.class = OSG.Typ THEN type := obj.type ELSE OSS.Mark("type?") END\r
+ find(obj);\r
+ OSS.Get(sym);\r
+ IF obj.class = OSG.Typ THEN\r
+ type := obj.type\r
+ ELSE\r
+ OSS.Mark("type?")\r
+ END\r
+\r
ELSIF sym = OSS.array THEN\r
- OSS.Get(sym); expression(x);\r
- IF (x.mode # OSG.Const) OR (x.a < 0) THEN OSS.Mark("bad index") END ;\r
- IF sym = OSS.of THEN OSS.Get(sym) ELSE OSS.Mark("OF?") END ;\r
- Type(tp); NEW(type); type.form := OSG.Array; type.base := tp;\r
- type.len := x.a; type.size := type.len * tp.size\r
+ OSS.Get(sym);\r
+ expression(x);\r
+ IF (x.mode # OSG.Const) OR (x.a < 0) THEN\r
+ OSS.Mark("bad index")\r
+ END ;\r
+ IF sym = OSS.of THEN\r
+ OSS.Get(sym)\r
+ ELSE\r
+ OSS.Mark("OF?")\r
+ END ;\r
+ Type(tp);\r
+ NEW(type);\r
+ type.form := OSG.Array;\r
+ type.base := tp;\r
+ type.len := x.a;\r
+ type.size := type.len * tp.size\r
+\r
ELSIF sym = OSS.record THEN\r
- OSS.Get(sym); NEW(type); type.form := OSG.Record; type.size := 0; OpenScope;\r
+ OSS.Get(sym);\r
+ NEW(type);\r
+ type.form := OSG.Record;\r
+ type.size := 0;\r
+ OpenScope;\r
REPEAT\r
IF sym = OSS.ident THEN\r
- IdentList(OSG.Fld, first); Type(tp); obj := first;\r
+ IdentList(OSG.Fld, first);\r
+ Type(tp);\r
+ obj := first;\r
WHILE obj # NIL DO\r
- obj.type := tp; obj.val := type.size; type.size := type.size + obj.type.size; obj := obj.next\r
+ obj.type := tp;\r
+ obj.val := type.size;\r
+ type.size := type.size + obj.type.size;\r
+ obj := obj.next\r
END\r
END ;\r
- IF sym = OSS.semicolon THEN OSS.Get(sym)\r
- ELSIF sym = OSS.ident THEN OSS.Mark("; ?")\r
+ IF sym = OSS.semicolon THEN\r
+ OSS.Get(sym)\r
+ ELSIF sym = OSS.ident THEN\r
+ OSS.Mark("; ?")\r
END\r
UNTIL sym # OSS.ident;\r
- type.dsc := topScope.next; CloseScope; Check(OSS.end, "no END")\r
- ELSE OSS.Mark("ident?")\r
+ type.dsc := topScope.next;\r
+ CloseScope;\r
+ Check(OSS.end, "no END")\r
+\r
+ ELSE\r
+ OSS.Mark("ident?")\r
END\r
END Type;\r
\r
IF sym = OSS.type THEN\r
OSS.Get(sym);\r
WHILE sym = OSS.ident DO\r
- NewObj(obj, OSG.Typ); OSS.Get(sym);\r
- IF sym = OSS.eql THEN OSS.Get(sym) ELSE OSS.Mark("=?") END ;\r
- Type(obj.type); Check(OSS.semicolon, "; expected")\r
+ NewObj(obj, OSG.Typ);\r
+ OSS.Get(sym);\r
+ IF sym = OSS.eql THEN\r
+ OSS.Get(sym)\r
+ ELSE\r
+ OSS.Mark("=?")\r
+ END ;\r
+ Type(obj.type);\r
+ Check(OSS.semicolon, "; expected")\r
END\r
END ;\r
\r
}
}
+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;
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)
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;
expect(p, END);
}
codegen_endproc(p);
+
+ if (!matches(p, END_FILE))
+ {
+ error(p, "expected end of file");
+ }
}
static inline char* file_load(char* path)
{
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)