struct parse_context {
struct token_config config;
char *file_name;
+ int parse_error;
## parse context
};
} else
prog = parse_oceani(s->code, &context.config,
dotrace ? stderr : NULL);
+ if (!prog) {
+ fprintf(stderr, "oceani: fatal parser error.\n");
+ context.parse_error = 1;
+ }
if (prog && doprint)
print_exec(*prog, 0, brackets);
- if (prog && doexec) {
+ if (prog && doexec && !context.parse_error) {
if (!analyse_prog(*prog, &context)) {
fprintf(stderr, "oceani: type error in program - not running.\n");
exit(1);
s = t;
}
## free context
- exit(0);
+ exit(context.parse_error ? 1 : 0);
}
### Analysis
}
}
fputs("\n", stderr);
+ 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
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 (;
static void print_exec(struct exec *e, int indent, int bracket)
{
+ if (!e)
+ return;
switch (e->type) {
case Xbinode:
print_binode(cast(binode, e), indent, bracket); break;
$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);
$0->right = $<4;
var_block_close(config2context(config), CloseSequential);
if (config2context(config)->scope_stack) abort();
- }$
+ }$
+ | ERROR ${
+ tok_err(config2context(config),
+ "error: unhandled parse error.", &$1);
+ }$
Varlist -> Varlist ArgDecl ${
$0 = new(binode);
struct binode *b = cast(binode, prog);
int ok = 1;
+ if (!b)
+ return 0;
do {
ok = 1;
propagate_types(b->right, c, &ok, Vnone, 0);
static void interp_prog(struct exec *prog, char **argv)
{
struct binode *p = cast(binode, prog);
- struct binode *al = cast(binode, p->left);
+ struct binode *al;
struct value v;
+ if (!prog)
+ return;
+ al = cast(binode, p->left);
while (al) {
struct var *v = cast(var, al->left);
struct value *vl = &v->var->val;