return sym;
}
-static Symbol* symbol_get(Parser* p, char* name)
+static Symbol* symbol_get(Parser* p, int class, char* name)
{
Symbol* sym = p->scope;
for (; sym; sym = sym->next)
{
if (!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 sym;
}
}
return NULL;
}
+/* Item Handling
+ *****************************************************************************/
+static void init_item(Item* item, Symbol* sym)
+{
+ item->mode = sym->class;
+ item->imm = sym->imm;
+ item->type = sym->type;
+}
+
/* Type Checking
*****************************************************************************/
static void check_int(Parser* p, Item* item)
}
}
-static void check_int2(Parser* p, Item* a, Item* b)
+static void check_ints(Parser* p, Item* a, Item* b)
{
check_int(p, a);
check_int(p, b);
}
}
-static void check_real2(Parser* p, Item* a, Item* b)
+static void check_reals(Parser* p, Item* a, Item* b)
{
check_real(p, a);
check_real(p, b);
}
}
-static void check_num2(Parser* p, Item* a, Item* b)
+static void check_nums(Parser* p, Item* a, Item* b)
{
if (a->type->form == FORM_REAL)
{
- check_real2(p, a, b);
+ check_reals(p, a, b);
}
else
{
- check_int2(p, a, b);
+ check_ints(p, a, b);
}
}
}
}
-static void check_bool2(Parser* p, Item* a, Item* b)
+static void check_bools(Parser* p, Item* a, Item* b)
{
check_bool(p, a);
check_bool(p, b);
}
+static void check_types(Parser* p, Item* a, Item* b)
+{
+ if (a->type->form == FORM_REAL)
+ {
+ check_reals(p, a, b);
+ }
+ else if (a->type->form == FORM_INT)
+ {
+ check_ints(p, a, b);
+ }
+ else
+ {
+ error(p, "type mismatch");
+ }
+}
+
/* Grammar Definition
*****************************************************************************/
RULE(qualident)
{
char* name = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, name);
+ Symbol* sym = symbol_get(p, -1, name);
+ init_item(item, sym);
+
+// item->mode = sym->class;
+// item->type = sym->type;
+// item->imm = sym->imm;
+
+// if (sym->class == SYM_CONST)
+// {
+// item->mode = ITEM_CONST;
+// item->imm = sym->imm;
+// }
- if (sym->class == SYM_CONST)
- {
- item->mode = ITEM_CONST;
- item->imm = sym->imm;
- }
// if (accept(p, '.'))
// {
// expect(p, IDENT);
case '*':
case '/':
case '%':
- check_num2(p, item, &right);
+ check_nums(p, item, &right);
codegen_binop(op, item, &right);
break;
case AND:
- check_bool2(p, item, &right);
+ check_bools(p, item, &right);
codegen_binop(op, item, &right);
break;
term(p, &right);
if (op == OR)
{
- check_bool2(p, item, &right);
+ check_bools(p, item, &right);
}
else
{
- check_num2(p, item, &right);
+ check_nums(p, item, &right);
}
codegen_binop(op, item, &right);
}
Item right = { 0 };
int op = consume(p);
simple_expr(p, &right);
- check_num2(p, item, &right);
+ check_nums(p, item, &right);
codegen_binop(op, item, &right);
}
}
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);
- }
+ type = symbol_get(p, SYM_TYPE, name);
/* apply the type to the newly created symbols */
for (int i = 0; i < nsyms; i++)
expect(p, '=');
expression(p, item);
sym->imm = item->imm;
+ sym->type = item->type;
if (!accept(p, ','))
{
}
}
+/* Code generation for
+find(obj);
+OSS.Get(sym);
+IF obj.class = OSG.SProc THEN
+ StandProc(obj.val)
+ELSE
+ OSG.MakeItem(x, obj, level);
+ selector(x);
+
+ IF sym = OSS.becomes THEN (*assignment*)
+
+ OSS.Get(sym);
+ expression(y);
+ IF (x.type.form IN {OSG.Boolean, OSG.Integer}) & (x.type.form = y.type.form) THEN
+ OSG.Store(x, y)
+ ELSE
+ OSS.Mark("incompatible assignment")
+ END
+
+// ELSIF sym = OSS.eql THEN
+// OSS.Mark("should be :=");
+// OSS.Get(sym);
+// expression(y)
+// ELSIF sym = OSS.lparen THEN (*procedure call*)
+// OSS.Get(sym);
+// IF (obj.class = OSG.Proc) & (obj.type = NIL) THEN
+// ParamList(obj);
+// OSG.Call(obj);
+// ELSE
+// OSS.Mark("not a procedure")
+// END
+// ELSIF obj.class = OSG.Proc THEN (*procedure call without parameters*)
+// IF obj.nofpar > 0 THEN
+// OSS.Mark("missing parameters")
+// END ;
+// IF obj.type = NIL THEN
+// OSG.Call(obj) ELSE
+// OSS.Mark("not a procedure")
+// END
+// ELSIF (obj.class = OSG.SProc) & (obj.val = 3) THEN
+// OSG.WriteLn
+// ELSIF obj.class = OSG.Typ THEN
+// OSS.Mark("illegal assignment")
+// ELSE
+// OSS.Mark("not a procedure")
+// END
+END
+
+*/
+
RULE(statement_seq)
{
if (matches(p, IDENT))
{
+ Item right = { 0 };
char* text = expect_text(p, IDENT);
if (accept(p, '='))
{
- Symbol* sym = symbol_get(p, text);
- if (!sym)
- {
- error(p, "undefined variable '%s'", text);
- }
- else if (sym->class != SYM_VAR)
- {
- error(p, "assignment to non-variable '%s'", text);
- }
- expression(p, item);
+ Symbol* sym = symbol_get(p, SYM_VAR, text);
+ init_item(item, sym);
+ expression(p, &right);
+ check_types(p, item, &right);
+ codegen_store(item, &right);
}
else
{
+ /* TODO: add function calls and other complex stuff */
error(p, "expected assignment");
}
}
expect(p, ';');
}
-static inline char* file_load(char* path)
+static inline char* file_load(char* path)
{
int fd = -1, nread = 0, length = 0;
struct stat sb = {0};
char* contents = NULL;
- if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0))
+ if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0))
{
contents = calloc(sb.st_size + 1u, 1u);
while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0)
length += nread, sb.st_size -= nread;
}
}
- if (fd > 0)
+ if (fd > 0)
{
close(fd);
}
.fbeg = fcontents,
.fpos = fcontents,
}
- },
+ },
&(Item){0}
);