This allow common variables to be declared and initialised
for all reduce fragments.
Use this in oceani to declare 'c' holding the parser context,
so we don't need to call config2context in so many places.
Signed-off-by: NeilBrown <neil@brown.name>
#define config2context(_conf) container_of(_conf, struct parse_context, \
config)
#define config2context(_conf) container_of(_conf, struct parse_context, \
config)
+###### Parser: reduce
+ struct parse_context *c = config2context(config);
+
###### Parser: code
#include <unistd.h>
###### Parser: code
#include <unistd.h>
- OpenScope -> ${ scope_push(config2context(config)); }$
+ OpenScope -> ${ scope_push(c); }$
Each variable records a scope depth and is in one of four states:
Each variable records a scope depth and is in one of four states:
$0->array.member = $<4;
$0->array.vsize = NULL;
{
$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)
char tail[3];
mpq_t num;
if (number_parse(num, tail, $2.txt) == 0)
}$
| [ IDENTIFIER ] Type ${ {
}$
| [ IDENTIFIER ] Type ${ {
- struct parse_context *c = config2context(config);
struct variable *v = var_ref(c, $2.txt);
if (!v)
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);
- 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;
$0 = calloc(1, sizeof(struct type));
*($0) = array_prototype;
###### top level grammar
DeclareStruct -> struct IDENTIFIER FieldBlock ${ {
struct type *t =
###### 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;
int cnt = 0;
struct fieldlist *f;
$0->f.init = val_prepare($0->f.type);
do {
ok = 1;
$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)
} while (ok == 2);
if (!ok)
- config2context(config)->parse_error = 1;
else
$0->f.init = interp_exec($5);
} }$
else
$0->f.init = interp_exec($5);
} }$
if (number_parse($0->val.num, tail, $1.txt) == 0)
mpq_init($0->val.num);
if (tail[0])
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",
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
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",
char tail[3];
string_parse(&$1, '\\', &$0->val.str, tail);
if (tail[0])
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",
$*var
VariableDecl -> IDENTIFIER : ${ {
$*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 {
$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);
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
- 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 :: ${ {
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 {
$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);
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
- 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 ${ {
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) {
$0 = new_pos(var, $1);
$0->var = v;
if (v) {
v->where_set = $0;
v->val = val_prepare($<3);
} else {
v->where_set = $0;
v->val = val_prepare($<3);
} else {
- v = var_ref(config2context(config), $1.txt);
+ v = var_ref(c, $1.txt);
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
- 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 ${ {
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) {
$0 = new_pos(var, $1);
$0->var = v;
if (v) {
v->val = val_prepare($<3);
v->constant = 1;
} else {
v->val = val_prepare($<3);
v->constant = 1;
} else {
- v = var_ref(config2context(config), $1.txt);
+ v = var_ref(c, $1.txt);
- type_err(config2context(config), "error: variable '%v' redeclared",
+ type_err(c, "error: variable '%v' redeclared",
- 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 ${ {
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 */
$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;
if (v) {
v->val = val_prepare(Tlabel);
v->val.label = &v->val;
$*type
Type -> IDENTIFIER ${
$*type
Type -> IDENTIFIER ${
- $0 = find_type(config2context(config), $1.txt);
+ $0 = find_type(c, $1.txt);
- tok_err(config2context(config),
"error: undefined type", &$1);
$0 = Tnone;
"error: undefined type", &$1);
$0 = Tnone;
| VariableDecl ${
if ($1->var->where_set == NULL) {
| VariableDecl ${
if ($1->var->where_set == NULL) {
- type_err(config2context(config),
"Variable declared with no type or value: %v",
$1, NULL, 0, NULL);
} else {
"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;
$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;
}$
| forPart WhilePart CondSuffix ${
$0 = $<3;
$0->thenpart = NULL;
$0->condpart = $2.condpart; $2.condpart = NULL;
$0->dopart = $2.dopart; $2.dopart = NULL;
$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;
}$
| 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
$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
}$
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;
}$
| CasePart CondSuffix ${
$0 = $<2;
$0 = calloc(1,sizeof(struct casepart));
$0->value = $<2;
$0->action = $<4;
$0 = calloc(1,sizeof(struct casepart));
$0->value = $<2;
$0->action = $<4;
- var_block_close(config2context(config), CloseParallel);
+ var_block_close(c, CloseParallel);
| else OpenScope Block ${
$0 = new(cond_statement);
$0->elsepart = $<3;
| 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;
}$
| else OpenScope CondStatement ${
$0 = new(cond_statement);
$0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
+ var_block_close(c, CloseElse);
ThenPart -> Then OpenScope SimpleStatements ${
$0 = reorder_bilist($<3);
ThenPart -> Then OpenScope SimpleStatements ${
$0 = reorder_bilist($<3);
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
| Then OpenScope Block ${
$0 = $<3;
}$
| Then OpenScope Block ${
$0 = $<3;
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
// This scope is closed in CondSuffix
}$
// This scope is closed in CondSuffix
$0.type = Xcond_statement;
$0.condpart = $<3;
$0.thenpart = $<5;
$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;
}$
| 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);
int ok;
struct variable *v;
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;
if (v) {
struct var *var = new_pos(var, $1);
v->where_decl = var;
var->var = v;
v->constant = 1;
} else {
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;
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)
} while (ok == 2);
if (!ok)
- config2context(config)->parse_error = 1;
else if (v) {
v->val = interp_exec($5);
}
else if (v) {
v->val = interp_exec($5);
}
###### top level grammar
DeclareProgram -> Program ${ {
###### 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);
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;
$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) abort();
- tok_err(config2context(config),
"error: unhandled parse error", &$1);
}$
"error: unhandled parse error", &$1);
}$
$*var
ArgDecl -> IDENTIFIER ${ {
$*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;
} }$
$0 = new(var);
$0->var = v;
} }$
- static void gen_parser(FILE *f, struct grammar *g, char *file, char *name)
+ static void gen_parser(FILE *f, struct grammar *g, char *file, char *name,
+ struct code_node *pre_reduce)
{
gen_known(f, g);
gen_non_term(f, g);
gen_goto(f, g);
gen_states(f, g);
{
gen_known(f, g);
gen_non_term(f, g);
gen_goto(f, g);
gen_states(f, g);
- gen_reduce(f, g, file);
+ gen_reduce(f, g, file, pre_reduce);
gen_free(f, g);
fprintf(f, "#line 0 \"gen_parser\"\n");
gen_free(f, g);
fprintf(f, "#line 0 \"gen_parser\"\n");
- static void gen_reduce(FILE *f, struct grammar *g, char *file)
+ static void gen_reduce(FILE *f, struct grammar *g, char *file,
+ struct code_node *code)
- fprintf(f, "#line 0 \"gen_reduce\"\n");
+ fprintf(f, "#line 1 \"gen_reduce\"\n");
fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
fprintf(f, "{\n");
fprintf(f, "\tint ret_size = 0;\n");
fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
fprintf(f, "{\n");
fprintf(f, "\tint ret_size = 0;\n");
+ if (code)
+ code_node_print(f, code, file);
+ fprintf(f, "#line 4 \"gen_reduce\"\n");
fprintf(f, "\tswitch(prod) {\n");
for (i = 0; i < g->production_count; i++) {
struct production *p = g->productions[i];
fprintf(f, "\tswitch(prod) {\n");
for (i = 0; i < g->production_count; i++) {
struct production *p = g->productions[i];
struct code_node *hdr = NULL;
struct code_node *code = NULL;
struct code_node *gram = NULL;
struct code_node *hdr = NULL;
struct code_node *code = NULL;
struct code_node *gram = NULL;
+ struct code_node *pre_reduce = NULL;
for (s = table; s; s = s->next) {
struct text sec = s->section;
if (tag && !strip_tag(&sec, tag))
for (s = table; s; s = s->next) {
struct text sec = s->section;
if (tag && !strip_tag(&sec, tag))
code = s->code;
else if (text_is(sec, "grammar"))
gram = s->code;
code = s->code;
else if (text_is(sec, "grammar"))
gram = s->code;
+ else if (text_is(sec, "reduce"))
+ pre_reduce = s->code;
else {
fprintf(stderr, "Unknown content section: %.*s\n",
s->section.len, s->section.txt);
else {
fprintf(stderr, "Unknown content section: %.*s\n",
s->section.len, s->section.txt);
if (f) {
if (code)
code_node_print(f, code, infile);
if (f) {
if (code)
code_node_print(f, code, infile);
- gen_parser(f, g, infile, name);
+ gen_parser(f, g, infile, name, pre_reduce);
fclose(f);
} else {
fprintf(stderr, "Cannot create %s.c\n",
fclose(f);
} else {
fprintf(stderr, "Cannot create %s.c\n",