#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:
$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;
###### 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;
$*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;
| SimpleStatements ; ${ $0 = $<1; }$
SimpleStatement -> pass ${ $0 = NULL; }$
+ | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
## SimpleStatement Grammar
###### print binode cases
| 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 {
$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;
} }$