#define config2context(_conf) container_of(_conf, struct parse_context, \
config)
+###### Parser: reduce
+ struct parse_context *c = config2context(config);
+
###### Parser: code
#include <unistd.h>
###### Grammar
$void
- OpenScope -> ${ scope_push(config2context(config)); }$
+ OpenScope -> ${ scope_push(c); }$
Each variable records a scope depth and is in one of four states:
v = t->previous;
free_value(t->val);
- if (t->min_depth == 0)
+ if (t->depth == 0)
// This is a global constant
free_exec(t->where_decl);
free(t);
$0->array.member = $<4;
$0->array.vsize = NULL;
{
- struct parse_context *c = config2context(config);
char tail[3];
mpq_t num;
if (number_parse(num, tail, $2.txt) == 0)
}$
| [ IDENTIFIER ] Type ${ {
- struct parse_context *c = config2context(config);
struct variable *v = var_ref(c, $2.txt);
if (!v)
- tok_err(config2context(config), "error: name undeclared", &$2);
+ tok_err(c, "error: name undeclared", &$2);
else if (!v->constant)
- tok_err(config2context(config), "error: array size must be a constant", &$2);
+ tok_err(c, "error: array size must be a constant", &$2);
$0 = calloc(1, sizeof(struct type));
*($0) = array_prototype;
###### print binode cases
case Index:
- print_exec(b->left, -1, 0);
+ print_exec(b->left, -1, bracket);
printf("[");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
printf("]");
break;
case Xfieldref:
{
struct fieldref *f = cast(fieldref, e);
- print_exec(f->left, -1, 0);
+ print_exec(f->left, -1, bracket);
printf(".%.*s", f->name.len, f->name.txt);
break;
}
###### top level grammar
DeclareStruct -> struct IDENTIFIER FieldBlock ${ {
struct type *t =
- add_type(config2context(config), $2.txt, &structure_prototype);
+ add_type(c, $2.txt, &structure_prototype);
int cnt = 0;
struct fieldlist *f;
$0->f.init = val_prepare($0->f.type);
do {
ok = 1;
- propagate_types($<5, config2context(config), &ok, $3, 0);
+ propagate_types($<5, c, &ok, $3, 0);
} while (ok == 2);
if (!ok)
- config2context(config)->parse_error = 1;
+ c->parse_error = 1;
else
$0->f.init = interp_exec($5);
} }$
$0->f.type = $<3;
$0->f.init = val_init($3);
}$
+ | ERROR ${ tok_err(c, "Syntax error in struct field", &$1); }$
###### forward decls
static void structure_print_type(struct type *t, FILE *f);
if (number_parse($0->val.num, tail, $1.txt) == 0)
mpq_init($0->val.num);
if (tail[0])
- tok_err(config2context(config), "error: unsupported number suffix",
+ tok_err(c, "error: unsupported number suffix",
&$1);
}
}$
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
- tok_err(config2context(config), "error: unsupported string suffix",
+ tok_err(c, "error: unsupported string suffix",
&$1);
}
}$
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
- tok_err(config2context(config), "error: unsupported string suffix",
+ tok_err(c, "error: unsupported string suffix",
&$1);
}
}$
$*var
VariableDecl -> IDENTIFIER : ${ {
- struct variable *v = var_decl(config2context(config), $1.txt);
+ struct variable *v = var_decl(c, $1.txt);
$0 = new_pos(var, $1);
$0->var = v;
if (v)
v->where_decl = $0;
else {
- v = var_ref(config2context(config), $1.txt);
+ v = var_ref(c, $1.txt);
$0->var = v;
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
$0, NULL, 0, NULL);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: ${ {
- struct variable *v = var_decl(config2context(config), $1.txt);
+ struct variable *v = var_decl(c, $1.txt);
$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);
+ v = var_ref(c, $1.txt);
$0->var = v;
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
$0, NULL, 0, NULL);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER : Type ${ {
- struct variable *v = var_decl(config2context(config), $1.txt);
+ struct variable *v = var_decl(c, $1.txt);
$0 = new_pos(var, $1);
$0->var = v;
if (v) {
v->where_set = $0;
v->val = val_prepare($<3);
} else {
- v = var_ref(config2context(config), $1.txt);
+ v = var_ref(c, $1.txt);
$0->var = v;
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
$0, NULL, 0, NULL);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
} }$
| IDENTIFIER :: Type ${ {
- struct variable *v = var_decl(config2context(config), $1.txt);
+ struct variable *v = var_decl(c, $1.txt);
$0 = new_pos(var, $1);
$0->var = v;
if (v) {
v->val = val_prepare($<3);
v->constant = 1;
} else {
- v = var_ref(config2context(config), $1.txt);
+ v = var_ref(c, $1.txt);
$0->var = v;
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
$0, NULL, 0, NULL);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
} }$
$*exec
Variable -> IDENTIFIER ${ {
- struct variable *v = var_ref(config2context(config), $1.txt);
+ struct variable *v = var_ref(c, $1.txt);
$0 = new_pos(var, $1);
if (v == NULL) {
/* This might be a label - allocate a var just in case */
- v = var_decl(config2context(config), $1.txt);
+ v = var_decl(c, $1.txt);
if (v) {
- v->val = val_prepare(Tlabel);
- v->val.label = &v->val;
+ v->val = val_prepare(Tnone);
+ v->where_decl = $0;
v->where_set = $0;
}
}
$*type
Type -> IDENTIFIER ${
- $0 = find_type(config2context(config), $1.txt);
+ $0 = find_type(c, $1.txt);
if (!$0) {
- tok_err(config2context(config),
+ tok_err(c,
"error: undefined type", &$1);
$0 = Tnone;
v->where_decl, NULL, 0, NULL);
return v->val.type;
}
+ if (v->val.type == Tnone && v->where_decl == prog)
+ type_err(c, "error: variable used but not declared: %v",
+ prog, NULL, 0, NULL);
if (v->val.type == NULL) {
if (type && *ok != 0) {
v->val = val_prepare(type);
case CondExpr:
b2 = cast(binode, b->right);
- print_exec(b2->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b2->left, -1, bracket);
printf(" if ");
- print_exec(b->left, -1, 0);
+ print_exec(b->left, -1, bracket);
printf(" else ");
- print_exec(b2->right, -1, 0);
+ print_exec(b2->right, -1, bracket);
+ if (bracket) printf(")");
break;
###### propagate binode cases
###### print binode cases
case And:
- print_exec(b->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, -1, bracket);
printf(" and ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
case AndThen:
- print_exec(b->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, -1, bracket);
printf(" and then ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
case Or:
- print_exec(b->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, -1, bracket);
printf(" or ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
case OrElse:
- print_exec(b->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, -1, bracket);
printf(" or else ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
case Not:
+ if (bracket) printf("(");
printf("not ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
###### propagate binode cases
case GtrEq:
case Eql:
case NEql:
- print_exec(b->left, -1, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, -1, bracket);
switch(b->op) {
case Less: printf(" < "); break;
case LessEq: printf(" <= "); break;
case NEql: printf(" != "); break;
default: abort(); // NOTEST
}
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
+ if (bracket) printf(")");
break;
###### propagate binode cases
case Divide:
case Concat:
case Rem:
- print_exec(b->left, indent, 0);
+ if (bracket) printf("(");
+ print_exec(b->left, indent, bracket);
switch(b->op) {
case Plus: fputs(" + ", stdout); break;
case Minus: fputs(" - ", stdout); break;
case Concat: fputs(" ++ ", stdout); break;
default: abort(); // NOTEST
} // NOTEST
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
+ if (bracket) printf(")");
break;
case Absolute:
+ if (bracket) printf("(");
printf("+");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
+ if (bracket) printf(")");
break;
case Negate:
+ if (bracket) printf("(");
printf("-");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
+ if (bracket) printf(")");
break;
case Bracket:
printf("(");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
printf(")");
break;
| SimpleStatements ; ${ $0 = $<1; }$
SimpleStatement -> pass ${ $0 = NULL; }$
+ | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
## SimpleStatement Grammar
###### print binode cases
if (b->left == NULL)
printf("pass");
else
- print_exec(b->left, indent, 0);
+ print_exec(b->left, indent, bracket);
if (b->right) {
printf("; ");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
}
} else {
// block, one per line
while (b) {
if (b->left) {
printf(" ");
- print_exec(b->left, -1, 0);
+ print_exec(b->left, -1, bracket);
if (b->right)
printf(",");
}
| VariableDecl ${
if ($1->var->where_set == NULL) {
- type_err(config2context(config),
+ type_err(c,
"Variable declared with no type or value: %v",
$1, NULL, 0, NULL);
} else {
case Assign:
do_indent(indent, "");
- print_exec(b->left, indent, 0);
+ print_exec(b->left, indent, bracket);
printf(" = ");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
if (indent >= 0)
printf("\n");
break;
{
struct variable *v = cast(var, b->left)->var;
do_indent(indent, "");
- print_exec(b->left, indent, 0);
+ print_exec(b->left, indent, bracket);
if (cast(var, b->left)->var->constant) {
if (v->where_decl == v->where_set) {
printf("::");
}
if (b->right) {
printf("= ");
- print_exec(b->right, indent, 0);
+ print_exec(b->right, indent, bracket);
}
if (indent >= 0)
printf("\n");
$0 = new_pos(binode, $1);
$0->op = Use;
$0->right = $<2;
+ if ($0->right->type == Xvar) {
+ struct var *v = cast(var, $0->right);
+ if (v->var->val.type == Tnone) {
+ /* Convert this to a label */
+ v->var->val = val_prepare(Tlabel);
+ v->var->val.label = &v->var->val;
+ }
+ }
}$
###### print binode cases
case Use:
do_indent(indent, "use ");
- print_exec(b->right, -1, 0);
+ print_exec(b->right, -1, bracket);
if (indent >= 0)
printf("\n");
break;
$0->thenpart = $<2;
$0->condpart = $3.condpart; $3.condpart = NULL;
$0->dopart = $3.dopart; $3.dopart = NULL;
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
| forPart WhilePart CondSuffix ${
$0 = $<3;
$0->thenpart = NULL;
$0->condpart = $2.condpart; $2.condpart = NULL;
$0->dopart = $2.dopart; $2.dopart = NULL;
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
| whilePart CondSuffix ${
$0 = $<2;
$0->condpart = $1.condpart; $1.condpart = NULL;
$0->thenpart = $1.thenpart; $1.thenpart = NULL;
// This is where we close an "if" statement
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
CondSuffix -> IfSuffix ${
$0 = $<1;
// This is where we close scope of the whole
// "for" or "while" statement
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
| CasePart CondSuffix ${
$0 = $<2;
$0 = calloc(1,sizeof(struct casepart));
$0->value = $<2;
$0->action = $<4;
- var_block_close(config2context(config), CloseParallel);
+ var_block_close(c, CloseParallel);
}$
$*cond_statement
| else OpenScope Block ${
$0 = new(cond_statement);
$0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
+ var_block_close(c, CloseElse);
}$
| else OpenScope CondStatement ${
$0 = new(cond_statement);
$0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
+ var_block_close(c, CloseElse);
}$
$void
ThenPart -> Then OpenScope SimpleStatements ${
$0 = reorder_bilist($<3);
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
| Then OpenScope Block ${
$0 = $<3;
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
// This scope is closed in CondSuffix
$0.type = Xcond_statement;
$0.condpart = $<3;
$0.thenpart = $<5;
- var_block_close(config2context(config), CloseParallel);
+ var_block_close(c, CloseParallel);
}$
| if OpenScope Block Then OpenScope Block ${
$0.type = Xcond_statement;
$0.condpart = $<3;
$0.thenpart = $<6;
- var_block_close(config2context(config), CloseParallel);
+ var_block_close(c, CloseParallel);
}$
$*exec
| DeclareProgram
| DeclareStruct
| NEWLINE
+ | ERROR NEWLINE ${
+ tok_err(c,
+ "error: unhandled parse error", &$1);
+ }$
## top level grammar
int ok;
struct variable *v;
- v = var_decl(config2context(config), $1.txt);
+ v = var_decl(c, $1.txt);
if (v) {
struct var *var = new_pos(var, $1);
v->where_decl = var;
var->var = v;
v->constant = 1;
} else {
- v = var_ref(config2context(config), $1.txt);
- tok_err(config2context(config), "error: name already declared", &$1);
- type_err(config2context(config), "info: this is where '%v' was first declared",
+ v = var_ref(c, $1.txt);
+ tok_err(c, "error: name already declared", &$1);
+ type_err(c, "info: this is where '%v' was first declared",
v->where_decl, NULL, 0, NULL);
}
do {
ok = 1;
- propagate_types($5, config2context(config), &ok, $3, 0);
+ propagate_types($5, c, &ok, $3, 0);
} while (ok == 2);
if (!ok)
- config2context(config)->parse_error = 1;
+ c->parse_error = 1;
else if (v) {
v->val = interp_exec($5);
}
} }$
+ | ERROR NEWLINE ${ tok_err(c, "Syntax error in constant", &$1); }$
###### print const decls
{
###### top level grammar
DeclareProgram -> Program ${ {
- struct parse_context *c = config2context(config);
if (c->prog)
type_err(c, "Program defined a second time",
$1, NULL, 0, NULL);
$0->op = Program;
$0->left = reorder_bilist($<3);
$0->right = $<4;
- var_block_close(config2context(config), CloseSequential);
- if (config2context(config)->scope_stack) abort();
+ var_block_close(c, CloseSequential);
+ if (c->scope_stack && !c->parse_error) abort();
}$
| ERROR ${
- tok_err(config2context(config),
+ tok_err(c,
"error: unhandled parse error", &$1);
}$
$*var
ArgDecl -> IDENTIFIER ${ {
- struct variable *v = var_decl(config2context(config), $1.txt);
+ struct variable *v = var_decl(c, $1.txt);
$0 = new(var);
$0->var = v;
} }$