typedef struct Symbol {
struct Symbol* next;
enum{
- SYM_CONST, SYM_VAR, SYM_TYPE, SYM_PROC
+ SYM_SCOPE, SYM_CONST, SYM_VAR, SYM_TYPE, SYM_PROC
} class;
char* name;
Type* type;
// src/sym.c
Symbol* symbol_new(Parser* p, char* name, int class, bool export);
Symbol* symbol_get(Parser* p, int class, char* name);
+void symbol_openscope(Parser* p);
+void symbol_closescope(Parser* p);
// src/type_checks.c
void check_int(Parser* p, Item* item);
W: Texts.Writer;\r
\r
PROCEDURE NewObj(VAR obj: OSG.Object; class: INTEGER);\r
- VAR new, x: OSG.Object;\r
- BEGIN x := topScope;\r
- WHILE (x.next # NIL) & (x.next.name # OSS.id) DO x := x.next END ;\r
+ VAR\r
+ new, x: OSG.Object;\r
+ BEGIN\r
+ x := topScope;\r
+ WHILE (x.next # NIL) & (x.next.name # OSS.id) DO\r
+ x := x.next\r
+ END ;\r
+\r
IF x.next = NIL THEN\r
- NEW(new); new.name := OSS.id; new.class := class; new.next := NIL;\r
- x.next := new; obj := new\r
- ELSE obj := x.next; OSS.Mark("mult def")\r
+ NEW(new);\r
+ new.name := OSS.id;\r
+ new.class := class;\r
+ new.next := NIL;\r
+ x.next := new;\r
+ obj := new\r
+ ELSE\r
+ obj := x.next;\r
+ OSS.Mark("mult def")\r
END\r
END NewObj;\r
\r
PROCEDURE find(VAR obj: OSG.Object);\r
- VAR s, x: OSG.Object;\r
- BEGIN s := topScope;\r
- REPEAT x := s.next;\r
- WHILE (x # NIL) & (x.name # OSS.id) DO x := x.next END ;\r
- s := s.dsc\r
+ VAR\r
+ s, x: OSG.Object;\r
+ BEGIN\r
+ s := topScope;\r
+ REPEAT\r
+ x := s.next;\r
+ WHILE (x # NIL) & (x.name # OSS.id) DO\r
+ x := x.next\r
+ END ;\r
+ s := s.dsc\r
UNTIL (x # NIL) OR (s = NIL);\r
- IF x = NIL THEN x := dummy; OSS.Mark("undef") END ;\r
+\r
+ IF x = NIL THEN\r
+ x := dummy;\r
+ OSS.Mark("undef")\r
+ END ;\r
+\r
obj := x\r
END find;\r
\r
PROCEDURE FindField(VAR obj: OSG.Object; list: OSG.Object);\r
BEGIN\r
- WHILE (list # NIL) & (list.name # OSS.id) DO list := list.next END ;\r
- IF list # NIL THEN obj := list ELSE OSS.Mark("undef"); obj := dummy END\r
+ WHILE (list # NIL) & (list.name # OSS.id) DO\r
+ list := list.next\r
+ END ;\r
+\r
+ IF list # NIL THEN\r
+ obj := list\r
+ ELSE\r
+ OSS.Mark("undef");\r
+ obj := dummy\r
+ END\r
END FindField;\r
\r
PROCEDURE Check(s: INTEGER; msg: ARRAY OF CHAR);\r
BEGIN\r
- IF sym = s THEN OSS.Get(sym) ELSE OSS.Mark(msg) END\r
+ IF sym = s THEN\r
+ OSS.Get(sym)\r
+ ELSE\r
+ OSS.Mark(msg)\r
+ END\r
END Check;\r
\r
PROCEDURE CheckInt(VAR x: OSG.Item);\r
BEGIN\r
- IF x.type.form # OSG.Integer THEN OSS.Mark("not integer") END\r
+ IF x.type.form # OSG.Integer THEN\r
+ OSS.Mark("not integer")\r
+ END\r
END CheckInt;\r
\r
PROCEDURE CheckBool(VAR x: OSG.Item);\r
BEGIN\r
- IF x.type.form # OSG.Boolean THEN OSS.Mark("not Boolean") END\r
+ IF x.type.form # OSG.Boolean THEN\r
+ OSS.Mark("not Boolean")\r
+ END\r
END CheckBool;\r
\r
PROCEDURE OpenScope;\r
VAR obj: OSG.Object;\r
BEGIN\r
IF sym = OSS.ident THEN\r
- NewObj(first, class); OSS.Get(sym);\r
+ NewObj(first, class);\r
+ OSS.Get(sym);\r
WHILE sym = OSS.comma DO\r
OSS.Get(sym);\r
- IF sym = OSS.ident THEN NewObj(obj, class); OSS.Get(sym)\r
- ELSE OSS.Mark("ident?")\r
+ IF sym = OSS.ident THEN\r
+ NewObj(obj, class);\r
+ OSS.Get(sym)\r
+ ELSE\r
+ OSS.Mark("ident?")\r
END\r
END;\r
Check(OSS.colon, "no :")\r
IF sym = OSS.const THEN\r
OSS.Get(sym);\r
WHILE sym = OSS.ident DO\r
- NewObj(obj, OSG.Const); OSS.Get(sym);\r
- IF sym = OSS.eql THEN OSS.Get(sym) ELSE OSS.Mark("=?") END;\r
+ NewObj(obj, OSG.Const);\r
+ OSS.Get(sym);\r
+ IF sym = OSS.eql THEN\r
+ OSS.Get(sym)\r
+ ELSE\r
+ OSS.Mark("=?")\r
+ END;\r
expression(x);\r
IF x.mode = OSG.Const THEN\r
- obj.val := x.a; obj.type := x.type\r
+ obj.val := x.a; obj.type := x.type\r
ELSE\r
- OSS.Mark("expression not constant")\r
+ OSS.Mark("expression not constant")\r
END ;\r
Check(OSS.semicolon, "; expected")\r
END\r
END ;\r
Check(OSS.semicolon, "; expected");\r
Declarations(dc);\r
- WHILE sym = OSS.procedure DO ProcedureDecl; Check(OSS.semicolon, "; expected") END ;\r
+ WHILE sym = OSS.procedure DO\r
+ ProcedureDecl;\r
+ Check(OSS.semicolon, "; expected")\r
+ END ;\r
\r
OSG.Header(dc);\r
IF sym = OSS.begin THEN OSS.Get(sym); StatSequence END ;\r
bool export = accept(p, '*');
Symbol* sym = symbol_new(p, name, SYM_PROC, export);
Symbol** args = &(sym->desc);
+ symbol_openscope(p);
/* construct the proc type */
expect(p, '(');
expect(p, ';');
}
expect(p, END);
+ symbol_closescope(p);
}
RULE(module)
{
+ symbol_openscope(p);
+
expect(p, MODULE);
p->name = expect_text(p, IDENT);
/* TODO: Check that it matches filename here */
{
error(p, "expected end of file");
}
+
+ symbol_closescope(p);
}
static inline char* file_load(char* path)
Parser Ctx = {0};
+static Symbol InitialScope = {
+ .next = &IntSym,
+ .class = SYM_SCOPE,
+};
+
+
static void parse_init(char* fname, char* string)
{
memset(&Ctx, 0, sizeof(Ctx));
- Ctx.scope = &RealSym;
+ Ctx.scope = &InitialScope;
LexFile* file = calloc(sizeof(LexFile), 1u);
file->path = strdup(fname);
file->fbeg = file->fpos = strdup(string);
#include "cerise.h"
+static int sym_matches(Parser* p, int class, char* name, Symbol* sym)
+{
+// printf(" %s == %s\n", name, sym->name);
+
+ if (sym->name && !strcmp(sym->name, name))
+ {
+ if (class >= 0 && (int)sym->class != class)
+ {
+ switch(class)
+ {
+ case SYM_CONST:
+ error(p, "'%s' is not a constant", name);
+ break;
+
+ case SYM_VAR:
+ error(p, "'%s' is not a variable", name);
+ break;
+
+ case SYM_TYPE:
+ error(p, "'%s' is not a type", name);
+ break;
+
+ default:
+ assert(!"unknown identifier type");
+ break;
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
Symbol* symbol_new(Parser* p, char* name, int class, bool export)
{
+// Symbol* scope = p->scope;
+// while ()
+// {
+// }
+
Symbol* sym = calloc(1, sizeof(Symbol));
sym->name = name;
sym->class = class;
Symbol* symbol_get(Parser* p, int class, char* name)
{
- Symbol* sym = p->scope;
- for (; sym; sym = sym->next)
+ Symbol* scope = p->scope;
+ Symbol* sym = NULL;
+
+ for (Symbol* scope = p->scope; scope; scope = scope->next)
{
- if (!strcmp(sym->name, name))
+ if (scope)
{
- if (class >= 0 && (int)sym->class != class)
+ printf("SCOPE:\n");
+ }
+
+ if (sym_matches(p, class, name, scope))
+ {
+ return scope;
+ }
+
+ for (Symbol* sym = scope->desc; sym; sym = sym->next)
+ {
+ printf(" %s == %s %d\n", name, sym->name, sym_matches(p, class, name, scope));
+
+ if (sym_matches(p, class, name, sym))
{
- switch(class)
- {
- case SYM_CONST: error(p, "'%s' is not a constant", name); break;
- case SYM_VAR: error(p, "'%s' is not a variable", name); break;
- case SYM_TYPE: error(p, "'%s' is not a type", name); break;
- default: assert(!"unknown identifier type"); break;
- }
+ return sym;
}
- return sym;
}
}
+
error(p, "unknown identifier '%s'", name);
return NULL;
}
+
+void symbol_openscope(Parser* p)
+{
+ Symbol* scope = calloc(1, sizeof(Symbol));
+ scope->class = SYM_SCOPE;
+ scope->desc = p->scope;
+ scope->next = NULL;
+ p->scope = scope;
+}
+
+void symbol_closescope(Parser* p)
+{
+ p->scope = p->scope->desc;
+}