#define config2context(_conf) container_of(_conf, struct parse_context, \
config)
+###### Parser: reduce
+ struct parse_context *c = config2context(config);
+
###### Parser: code
#include <unistd.h>
struct parse_context context = {
.config = {
.ignored = (1 << TK_line_comment)
- | (1 << TK_block_comment),
- .number_chars = ".,_+-",
+ | (1 << TK_block_comment)
+ | (1 << TK_mark),
+ .number_chars = ".,_+- ",
.word_start = "_",
.word_cont = "_",
},
###### 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);
###### core functions
static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
- struct type *type, int rules)
+ struct type *type, int rules);
+ static struct type *__propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+ struct type *type, int rules)
{
struct type *t;
return Tnone;
}
+ static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+ struct type *type, int rules)
+ {
+ struct type *ret = __propagate_types(prog, c, ok, type, rules);
+
+ if (c->parse_error)
+ *ok = 0;
+ return ret;
+ }
+
#### Interpreting
Interpreting an `exec` doesn't require anything but the `exec`. State
$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;
t = propagate_types(b->left, c, ok, NULL, rules & Rnoconstant);
if (!t || t->compat != array_compat) {
type_err(c, "error: %1 cannot be indexed", prog, t, 0, NULL);
- *ok = 0;
return NULL;
} else {
if (!type_compat(type, t->array.member, rules)) {
type_err(c, "error: have %1 but need %2", prog,
t->array.member, rules, type);
- *ok = 0;
}
return t->array.member;
}
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;
}
f->left, st, 0, NULL);
else if (f->index == -2) {
f->index = find_struct_index(st, f->name);
- if (f->index < 0) {
+ if (f->index < 0)
type_err(c, "error: cannot find requested field in %1",
f->left, st, 0, NULL);
- *ok = 0;
- }
}
if (f->index >= 0) {
struct type *ft = st->structure.fields[f->index].type;
- if (!type_compat(type, ft, rules)) {
+ if (!type_compat(type, ft, rules))
type_err(c, "error: have %1 but need %2", prog,
ft, rules, type);
- *ok = 0;
- }
return ft;
}
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;
}
} }$
+ $void
+ Open -> {
+ | NEWLINE Open
+ Close -> }
+ | NEWLINE Close
$*fieldlist
- FieldBlock -> Open SimpleFieldList Close ${ $0 = $<2; }$
- | Open Newlines SimpleFieldList Close ${ $0 = $<3; }$
+ FieldBlock -> Open FieldList Close ${ $0 = $<2; }$
+ | Open SimpleFieldList } ${ $0 = $<2; }$
| : FieldList ${ $0 = $<2; }$
- FieldList -> Field NEWLINE ${ $0 = $<1; }$
- | FieldList NEWLINE ${ $0 = $<1; }$
- | FieldList Field NEWLINE ${
+ FieldList -> SimpleFieldList NEWLINE ${ $0 = $<1; }$
+ | FieldList SimpleFieldList NEWLINE ${
$2->prev = $<1;
$0 = $<2;
}$
- SimpleFieldList -> Field ; ${ $0 = $<1; }$
- | SimpleFieldList Field ; ${
- $2->prev = $<1;
- $0 = $<2;
+ SimpleFieldList -> Field ${ $0 = $<1; }$
+ | SimpleFieldList ; Field ${
+ $3->prev = $<1;
+ $0 = $<3;
+ }$
+ | SimpleFieldList ; ${
+ $0 = $<1;
}$
Field -> IDENTIFIER : Type = Expression ${ {
$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);
}
}$
case Xval:
{
struct val *val = cast(val, prog);
- if (!type_compat(type, val->val.type, rules)) {
+ if (!type_compat(type, val->val.type, rules))
type_err(c, "error: expected %1%r found %2",
prog, type, rules, val->val.type);
- *ok = 0;
- }
return val->val.type;
}
$*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;
struct variable *v = var->var;
if (!v) {
type_err(c, "%d:BUG: no variable!!", prog, NULL, 0, NULL); // NOTEST
- *ok = 0; // NOTEST
return Tnone; // NOTEST
}
if (v->merged)
prog, NULL, 0, NULL);
type_err(c, "info: name was defined as a constant here",
v->where_decl, NULL, 0, NULL);
- *ok = 0;
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);
type, rules, v->val.type);
type_err(c, "info: this is where '%v' was set to %1", v->where_set,
v->val.type, rules, NULL);
- *ok = 0;
}
if (!type)
return v->val.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
/* both must be Tbool, result is Tbool */
propagate_types(b->left, c, ok, Tbool, 0);
propagate_types(b->right, c, ok, Tbool, 0);
- if (type && type != Tbool) {
+ if (type && type != Tbool)
type_err(c, "error: %1 operation found where %2 expected", prog,
Tbool, 0, type);
- *ok = 0;
- }
return Tbool;
###### interp 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
if (t)
t = propagate_types(b->left, c, ok, t, 0);
}
- if (!type_compat(type, Tbool, 0)) {
+ if (!type_compat(type, Tbool, 0))
type_err(c, "error: Comparison returns %1 but %2 expected", prog,
Tbool, rules, type);
- *ok = 0;
- }
return Tbool;
###### interp 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;
* unary ops fit here too */
propagate_types(b->left, c, ok, Tnum, 0);
propagate_types(b->right, c, ok, Tnum, 0);
- if (!type_compat(type, Tnum, 0)) {
+ if (!type_compat(type, Tnum, 0))
type_err(c, "error: Arithmetic returns %1 but %2 expected", prog,
Tnum, rules, type);
- *ok = 0;
- }
return Tnum;
case Concat:
/* both must be Tstr, result is Tstr */
propagate_types(b->left, c, ok, Tstr, 0);
propagate_types(b->right, c, ok, Tstr, 0);
- if (!type_compat(type, Tstr, 0)) {
+ if (!type_compat(type, Tstr, 0))
type_err(c, "error: Concat returns %1 but %2 expected", prog,
Tstr, rules, type);
- *ok = 0;
- }
return Tstr;
case Bracket:
###### Grammar
$void
- OptNL -> Newlines
- |
-
Newlines -> NEWLINE
| Newlines NEWLINE
$*binode
- Open -> {
- | NEWLINE {
- Close -> }
- | NEWLINE }
Block -> Open Statementlist Close ${ $0 = $<2; }$
- | Open Newlines Statementlist Close ${ $0 = $<3; }$
| Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$
- | Open Newlines SimpleStatements } ${ $0 = reorder_bilist($<3); }$
- | : Statementlist ${ $0 = $<2; }$
| : SimpleStatements ${ $0 = reorder_bilist($<2); }$
+ | : Statementlist ${ $0 = $<2; }$
Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$
ComplexStatements -> ComplexStatements ComplexStatement ${
- $0 = new(binode);
- $0->op = Block;
- $0->left = $<1;
- $0->right = $<2;
+ if ($2 == NULL) {
+ $0 = $<1;
+ } else {
+ $0 = new(binode);
+ $0->op = Block;
+ $0->left = $<1;
+ $0->right = $<2;
+ }
}$
- | ComplexStatements NEWLINE ${ $0 = $<1; }$
| ComplexStatement ${
- $0 = new(binode);
- $0->op = Block;
- $0->left = NULL;
- $0->right = $<1;
+ if ($1 == NULL) {
+ $0 = NULL;
+ } else {
+ $0 = new(binode);
+ $0->op = Block;
+ $0->left = NULL;
+ $0->right = $<1;
+ }
}$
$*exec
ComplexStatement -> SimpleStatements NEWLINE ${
$0 = reorder_bilist($<1);
}$
+ | Newlines ${ $0 = NULL; }$
## ComplexStatement Grammar
$*binode
| 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
if (t && t != Tnone && t != Tbool) {
if (!type)
type = t;
- else if (t != type) {
+ else if (t != type)
type_err(c, "error: expected %1%r, found %2",
e->left, type, rules, t);
- *ok = 0;
- }
}
}
return type;
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");
propagate_types(b->left, c, ok, t,
(b->op == Assign ? Rnoconstant : 0));
}
- if (t && t->dup == NULL) {
+ if (t && t->dup == NULL)
type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);
- *ok = 0;
- }
return Tnone;
break;
$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;
$*cond_statement
// both ForThen and Whilepart open scopes, and CondSuffix only
// closes one - so in the first branch here we have another to close.
- CondStatement -> ForThen WhilePart CondSuffix ${
+ CondStatement -> forPart ThenPart WhilePart CondSuffix ${
+ $0 = $<4;
+ $0->forpart = $<1;
+ $0->thenpart = $<2;
+ $0->condpart = $3.condpart; $3.condpart = NULL;
+ $0->dopart = $3.dopart; $3.dopart = NULL;
+ var_block_close(c, CloseSequential);
+ }$
+ | forPart WhilePart CondSuffix ${
$0 = $<3;
- $0->forpart = $1.forpart; $1.forpart = NULL;
- $0->thenpart = $1.thenpart; $1.thenpart = NULL;
+ $0->forpart = $<1;
+ $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 ${
+ | whilePart CondSuffix ${
$0 = $<2;
$0->condpart = $1.condpart; $1.condpart = NULL;
$0->dopart = $1.dopart; $1.dopart = NULL;
}$
- | SwitchPart CondSuffix ${
+ | switchPart CondSuffix ${
$0 = $<2;
$0->condpart = $<1;
}$
- | IfPart IfSuffix ${
+ | ifPart IfSuffix ${
$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->casepart = $<1;
}$
+ $void
+ Case -> case
+ | NEWLINE Case
$*casepart
- CasePart -> Newlines case Expression OpenScope Block ${
- $0 = calloc(1,sizeof(struct casepart));
- $0->value = $<3;
- $0->action = $<5;
- var_block_close(config2context(config), CloseParallel);
- }$
- | case Expression OpenScope Block ${
+ CasePart -> Case Expression OpenScope Block ${
$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
- IfSuffix -> Newlines ${ $0 = new(cond_statement); }$
- | Newlines else OpenScope Block ${
- $0 = new(cond_statement);
- $0->elsepart = $<4;
- var_block_close(config2context(config), CloseElse);
- }$
+ IfSuffix -> ${ $0 = new(cond_statement); }$
+ | NEWLINE IfSuffix ${ $0 = $<2; }$
| else OpenScope Block ${
$0 = new(cond_statement);
$0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
- }$
- | Newlines else OpenScope CondStatement ${
- $0 = new(cond_statement);
- $0->elsepart = $<4;
- 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
+ Then -> then
+ | NEWLINE Then
+ While -> while
+ | NEWLINE While
+ Do -> do
+ | NEWLINE Do
$*exec
// These scopes are closed in CondSuffix
- ForPart -> for OpenScope SimpleStatements ${
+ forPart -> for OpenScope SimpleStatements ${
$0 = reorder_bilist($<3);
}$
| for OpenScope Block ${
$0 = $<3;
}$
- ThenPart -> then OpenScope SimpleStatements ${
+ ThenPart -> Then OpenScope SimpleStatements ${
$0 = reorder_bilist($<3);
- var_block_close(config2context(config), CloseSequential);
+ var_block_close(c, CloseSequential);
}$
- | then OpenScope Block ${
+ | Then OpenScope Block ${
$0 = $<3;
- var_block_close(config2context(config), CloseSequential);
- }$
-
- ThenPartNL -> ThenPart OptNL ${
- $0 = $<1;
+ var_block_close(c, CloseSequential);
}$
// This scope is closed in CondSuffix
- WhileHead -> while OpenScope Block ${
+ WhileHead -> While OpenScope Block ${
$0 = $<3;
}$
-
- $cond_statement
- ForThen -> ForPart OptNL ThenPartNL ${
- $0.forpart = $<1;
- $0.thenpart = $<3;
- }$
- | ForPart OptNL ${
- $0.forpart = $<1;
+ whileHead -> while OpenScope Block ${
+ $0 = $<3;
}$
+ $cond_statement
// This scope is closed in CondSuffix
- WhilePart -> while OpenScope Expression Block ${
+ whilePart -> while OpenScope Expression Block ${
$0.type = Xcond_statement;
$0.condpart = $<3;
$0.dopart = $<4;
}$
- | WhileHead OptNL do Block ${
+ | whileHead Do Block ${
$0.type = Xcond_statement;
$0.condpart = $<1;
+ $0.dopart = $<3;
+ }$
+ WhilePart -> While OpenScope Expression Block ${
+ $0.type = Xcond_statement;
+ $0.condpart = $<3;
$0.dopart = $<4;
}$
+ | WhileHead Do Block ${
+ $0.type = Xcond_statement;
+ $0.condpart = $<1;
+ $0.dopart = $<3;
+ }$
- IfPart -> if OpenScope Expression OpenScope Block ${
+ ifPart -> if OpenScope Expression OpenScope Block ${
$0.type = Xcond_statement;
$0.condpart = $<3;
$0.thenpart = $<5;
- var_block_close(config2context(config), CloseParallel);
+ var_block_close(c, CloseParallel);
}$
- | if OpenScope Block OptNL then OpenScope Block ${
+ | if OpenScope Block Then OpenScope Block ${
$0.type = Xcond_statement;
$0.condpart = $<3;
- $0.thenpart = $<7;
- var_block_close(config2context(config), CloseParallel);
+ $0.thenpart = $<6;
+ var_block_close(c, CloseParallel);
}$
$*exec
// This scope is closed in CondSuffix
- SwitchPart -> switch OpenScope Expression ${
+ switchPart -> switch OpenScope Expression ${
$0 = $<3;
}$
| switch OpenScope Block ${
| DeclareProgram
| DeclareStruct
| NEWLINE
+ | ERROR NEWLINE ${
+ tok_err(c,
+ "error: unhandled parse error", &$1);
+ }$
## top level grammar
###### top level grammar
DeclareConstant -> const Open ConstList Close
- | const Open Newlines ConstList Close
| const Open SimpleConstList }
- | const Open Newlines SimpleConstList }
| const : ConstList
- | const SimpleConstList
+ | const SimpleConstList NEWLINE
ConstList -> ComplexConsts
+ | NEWLINE ConstList
ComplexConsts -> ComplexConst ComplexConsts
| ComplexConst
ComplexConst -> SimpleConstList NEWLINE
- SimpleConstList -> Const ; SimpleConstList
+ SimpleConstList -> SimpleConstList ; Const
| Const
- | Const ; SimpleConstList ;
+ | SimpleConstList ;
$*type
CType -> Type ${ $0 = $<1; }$
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);
} }$
$*binode
- Program -> program OpenScope Varlist Block OptNL ${
+ Program -> program OpenScope Varlist Block ${
$0 = new(binode);
$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;
} }$
###### demo: hello
const:
- pi ::= 3.1415926
+ pi ::= 3.141_592_6
four ::= 2 + 2 ; five ::= 10/2
const pie ::= "I like Pie";
cake ::= "The cake is"
// Dad taught me - the first one I ever heard of.
for i:=1; then i = i + 1; while i < size:
n := list[i-1] * list[i-1]
- list[i] = (n / 100) % 10000
+ list[i] = (n / 100) % 10 000
print "Before sort:",
for i:=0; then i = i + 1; while i < size: