c->parse_error = 1;
}
+ static void tok_err(struct parse_context *c, char *fmt, struct token *t)
+ {
+ fprintf(stderr, "%s:%d:%d: %s\n", c->file_name, t->line, t->col, fmt);
+ c->parse_error = 1;
+ }
+
## Data Structures
One last introductory step before detailing the language elements and
struct variable *previous;
struct value val;
struct binding *name;
+ struct exec *where_decl;// where name was declared
struct exec *where_set; // where type was set
## variable fields
};
switch (v ? v->scope : OutScope) {
case InScope:
- /* Signal error ... once I build error signalling support */
+ /* Caller will report the error */
return NULL;
case CondScope:
for (;
$0->val.vtype = Vnum;
if (number_parse($0->val.num, $0->val.tail, $1.txt) == 0)
mpq_init($0->val.num);
+ if ($0->val.tail[0])
+ tok_err(config2context(config), "error: unsupported number suffix.",
+ &$1);
}$
| STRING ${
$0 = new_pos(val, $1);
$0->val.vtype = Vstr;
string_parse(&$1, '\\', &$0->val.str, $0->val.tail);
+ if ($0->val.tail[0])
+ tok_err(config2context(config), "error: unsupported string suffix.",
+ &$1);
}$
| MULTI_STRING ${
$0 = new_pos(val, $1);
$0->val.vtype = Vstr;
string_parse(&$1, '\\', &$0->val.str, $0->val.tail);
+ if ($0->val.tail[0])
+ tok_err(config2context(config), "error: unsupported string suffix.",
+ &$1);
}$
###### print exec cases
struct variable *v = var_decl(config2context(config), $1.txt);
$0 = new_pos(var, $1);
$0->var = v;
+ if (v)
+ v->where_decl = $0;
+ else {
+ v = var_ref(config2context(config), $1.txt);
+ $0->var = v;
+ type_err(config2context(config), "error: variable '%v' redeclared",
+ $0, Vnone, Vnone);
+ type_err(config2context(config), "info: this is where '%v' was first declared",
+ v->where_decl, Vnone, Vnone);
+ }
} }$
| IDENTIFIER ::= ${ {
struct variable *v = var_decl(config2context(config), $1.txt);
- v->constant = 1;
$0 = new_pos(var, $1);
$0->var = v;
+ if (v) {
+ v->where_decl = $0;
+ v->constant = 1;
+ } else {
+ v = var_ref(config2context(config), $1.txt);
+ $0->var = v;
+ type_err(config2context(config), "error: variable '%v' redeclared",
+ $0, Vnone, Vnone);
+ type_err(config2context(config), "info: this is where '%v' was first declared",
+ v->where_decl, Vnone, Vnone);
+ }
} }$
Variable -> IDENTIFIER ${ {
return type;
}
if (!vtype_compat(type, v->val.vtype, bool_permitted)) {
- type_err(c, "error: expected %1 but variable %v is %2", prog,
+ type_err(c, "error: expected %1 but variable '%v' is %2", prog,
type, v->val.vtype);
- type_err(c, "info: this is where %v was set to %1", v->where_set,
+ type_err(c, "info: this is where '%v' was set to %1", v->where_set,
v->val.vtype, Vnone);
*ok = 0;
}
if (t > Vunknown) {
if (propagate_types(b->right, c, ok, t, 0) != t)
if (b->left->type == Xvar)
- type_err(c, "info: variable %v was set as %1 here.",
+ type_err(c, "info: variable '%v' was set as %1 here.",
cast(var, b->left)->var->where_set, t, Vnone);
} else {
t = propagate_types(b->right, c, ok, Vnolabel, 0);
if (config2context(config)->scope_stack) abort();
}$
| ERROR ${
- fprintf(stderr, "%s:%d:%d: error: unhandled parse error.\n",
- config2context(config)->file_name, $1.line, $1.col);
- config2context(config)->parse_error = 1;
+ tok_err(config2context(config),
+ "error: unhandled parse error.", &$1);
}$
Varlist -> Varlist ArgDecl ${