#define config2context(_conf) container_of(_conf, struct parse_context, \
config)
+###### Parser: reduce
+ struct parse_context *c = config2context(config);
+
###### Parser: code
#include <unistd.h>
## core functions
#include <getopt.h>
- static char Usage[] = "Usage: oceani --trace --print --noexec --brackets"
- "--section=SectionName prog.ocn\n";
+ static char Usage[] =
+ "Usage: oceani --trace --print --noexec --brackets --section=SectionName prog.ocn\n";
static const struct option long_options[] = {
{"trace", 0, NULL, 't'},
{"print", 0, NULL, 'p'},
char *section = NULL;
struct parse_context context = {
.config = {
- .ignored = (1 << TK_line_comment)
- | (1 << TK_block_comment)
- | (1 << TK_mark),
+ .ignored = (1 << TK_mark),
.number_chars = ".,_+- ",
.word_start = "_",
.word_cont = "_",
###### includes
#include <gmp.h>
- #include "string.h"
- #include "number.h"
+ #include "parse_string.h"
+ #include "parse_number.h"
###### libs
myLDLIBS := libnumber.o libstring.o -lgmp
###### Grammar
$void
- OpenScope -> ${ scope_push(config2context(config)); }$
+ OpenScope -> ${ scope_push(c); }$
+ ClosePara -> ${ var_block_close(c, CloseParallel); }$
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);
- int cnt = 0;
- struct fieldlist *f;
-
- for (f = $3; f; f=f->prev)
- cnt += 1;
-
- t->structure.nfields = cnt;
- t->structure.fields = calloc(cnt, sizeof(struct field));
- f = $3;
- while (cnt > 0) {
- cnt -= 1;
- t->structure.fields[cnt] = f->f;
- f->f.init = val_prepare(Tnone);
- f = f->prev;
- }
- } }$
+ DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ {
+ struct type *t =
+ add_type(c, $2.txt, &structure_prototype);
+ int cnt = 0;
+ struct fieldlist *f;
+
+ for (f = $3; f; f=f->prev)
+ cnt += 1;
+
+ t->structure.nfields = cnt;
+ t->structure.fields = calloc(cnt, sizeof(struct field));
+ f = $3;
+ while (cnt > 0) {
+ cnt -= 1;
+ t->structure.fields[cnt] = f->f;
+ f->f.init = val_prepare(Tnone);
+ f = f->prev;
+ }
+ } }$
- $void
- Open -> {
- | NEWLINE Open
- Close -> }
- | NEWLINE Close
$*fieldlist
- FieldBlock -> Open FieldList Close ${ $0 = $<2; }$
- | Open SimpleFieldList } ${ $0 = $<2; }$
- | : FieldList ${ $0 = $<2; }$
-
- FieldList -> SimpleFieldList NEWLINE ${ $0 = $<1; }$
- | FieldList SimpleFieldList NEWLINE ${
- $2->prev = $<1;
- $0 = $<2;
+ FieldBlock -> { IN OptNL FieldLines OUT OptNL } ${ $0 = $<FL; }$
+ | { SimpleFieldList } ${ $0 = $<SFL; }$
+ | IN OptNL FieldLines OUT ${ $0 = $<FL; }$
+ | SimpleFieldList EOL ${ $0 = $<SFL; }$
+
+ FieldLines -> SimpleFieldList Newlines ${ $0 = $<SFL; }$
+ | FieldLines SimpleFieldList Newlines ${
+ $SFL->prev = $<FL;
+ $0 = $<SFL;
}$
- SimpleFieldList -> Field ${ $0 = $<1; }$
+ SimpleFieldList -> Field ${ $0 = $<F; }$
| SimpleFieldList ; Field ${
- $3->prev = $<1;
- $0 = $<3;
+ $F->prev = $<SFL;
+ $0 = $<F;
}$
| SimpleFieldList ; ${
- $0 = $<1;
+ $0 = $<SFL;
}$
+ | ERROR ${ tok_err(c, "Syntax error in struct field", &$1); }$
Field -> IDENTIFIER : Type = Expression ${ {
int ok;
$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);
} }$
{
int i;
- fprintf(f, "struct %.*s:\n", t->name.len, t->name.txt);
+ fprintf(f, "struct %.*s\n", t->name.len, t->name.txt);
for (i = 0; i < t->structure.nfields; i++) {
struct field *fl = t->structure.fields + i;
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);
###### Grammar
+ $LEFT if $$ifelse
+ ## expr precedence
+
$*exec
- Expression -> BoolExpr if Expression else Expression ${ {
+ Expression -> Expression if Expression else Expression $$ifelse ${ {
struct binode *b1 = new(binode);
struct binode *b2 = new(binode);
b1->op = CondExpr;
b2->right = $<5;
$0 = b1;
} }$
- | BoolExpr ${ $0 = $<1; }$
+ ## expression grammar
###### print binode cases
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
OrElse,
Not,
-###### Grammar
+###### expr precedence
+ $LEFT or
+ $LEFT and
+ $LEFT not
- $*exec
- BoolExpr -> BoolExpr or BTerm ${ {
+###### expression grammar
+ | Expression or Expression ${ {
struct binode *b = new(binode);
b->op = Or;
b->left = $<1;
b->right = $<3;
$0 = b;
} }$
- | BoolExpr or else BTerm ${ {
+ | Expression or else Expression ${ {
struct binode *b = new(binode);
b->op = OrElse;
b->left = $<1;
b->right = $<4;
$0 = b;
} }$
- | BTerm ${ $0 = $<1; }$
- BTerm -> BTerm and BFact ${ {
+ | Expression and Expression ${ {
struct binode *b = new(binode);
b->op = And;
b->left = $<1;
b->right = $<3;
$0 = b;
} }$
- | BTerm and then BFact ${ {
+ | Expression and then Expression ${ {
struct binode *b = new(binode);
b->op = AndThen;
b->left = $<1;
b->right = $<4;
$0 = b;
} }$
- | BFact ${ $0 = $<1; }$
- BFact -> not BFact ${ {
+ | not Expression ${ {
struct binode *b = new(binode);
b->op = Not;
b->right = $<2;
$0 = b;
} }$
- ## other BFact
###### 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
Eql,
NEql,
-###### other BFact
- | Expr CMPop Expr ${ {
+###### expr precedence
+ $LEFT < > <= >= == != CMPop
+
+###### expression grammar
+ | Expression CMPop Expression ${ {
struct binode *b = new(binode);
b->op = $2.op;
b->left = $<1;
b->right = $<3;
$0 = b;
} }$
- | Expr ${ $0 = $<1; }$
###### Grammar
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
Absolute, Negate,
Bracket,
-###### Grammar
+###### expr precedence
+ $LEFT + - Eop
+ $LEFT * / % ++ Top
+ $LEFT Uop
+ $TERM ( )
- $*exec
- Expr -> Expr Eop Term ${ {
+###### expression grammar
+ | Expression Eop Expression ${ {
struct binode *b = new(binode);
b->op = $2.op;
b->left = $<1;
b->right = $<3;
$0 = b;
} }$
- | Term ${ $0 = $<1; }$
- Term -> Term Top Factor ${ {
+ | Expression Top Expression ${ {
struct binode *b = new(binode);
b->op = $2.op;
b->left = $<1;
b->right = $<3;
$0 = b;
} }$
- | Factor ${ $0 = $<1; }$
- Factor -> ( Expression ) ${ {
+ | ( Expression ) ${ {
struct binode *b = new_pos(binode, $1);
b->op = Bracket;
b->right = $<2;
$0 = b;
} }$
- | Uop Factor ${ {
+ | Uop Expression ${ {
struct binode *b = new(binode);
b->op = $1.op;
b->right = $<2;
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;
###### Binode types
Block,
-###### Grammar
+###### expr precedence
+ $TERM pass
- $void
- Newlines -> NEWLINE
- | Newlines NEWLINE
+###### Grammar
$*binode
- Block -> Open Statementlist Close ${ $0 = $<2; }$
- | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$
- | : SimpleStatements ${ $0 = reorder_bilist($<2); }$
- | : Statementlist ${ $0 = $<2; }$
-
- Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$
+ Block -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
+ | { SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
+ | SimpleStatements ; ${ $0 = reorder_bilist($<SS); }$
+ | SimpleStatements EOL ${ $0 = reorder_bilist($<SS); }$
+ | IN OptNL Statementlist OUT ${ $0 = $<Sl; }$
+
+ OpenBlock -> OpenScope { IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
+ | OpenScope { SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
+ | OpenScope SimpleStatements ; ${ $0 = reorder_bilist($<SS); }$
+ | OpenScope SimpleStatements EOL ${ $0 = reorder_bilist($<SS); }$
+ | IN OpenScope OptNL Statementlist OUT ${ $0 = $<Sl; }$
+
+ UseBlock -> { OpenScope IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
+ | { OpenScope SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
+ | IN OpenScope OptNL Statementlist OUT ${ $0 = $<Sl; }$
+
+ ColonBlock -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $<Sl; }$
+ | { SimpleStatements } ${ $0 = reorder_bilist($<SS); }$
+ | : SimpleStatements ; ${ $0 = reorder_bilist($<SS); }$
+ | : SimpleStatements EOL ${ $0 = reorder_bilist($<SS); }$
+ | : IN OptNL Statementlist OUT ${ $0 = $<Sl; }$
+
+ Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<CS); }$
ComplexStatements -> ComplexStatements ComplexStatement ${
if ($2 == NULL) {
}$
$*exec
- ComplexStatement -> SimpleStatements NEWLINE ${
- $0 = reorder_bilist($<1);
+ ComplexStatement -> SimpleStatements Newlines ${
+ $0 = reorder_bilist($<SS);
+ }$
+ | SimpleStatements ; Newlines ${
+ $0 = reorder_bilist($<SS);
}$
- | Newlines ${ $0 = NULL; }$
## ComplexStatement Grammar
$*binode
$0->left = NULL;
$0->right = $<1;
}$
- | 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
###### Binode types
Print,
+##### expr precedence
+ $TERM print ,
+
###### SimpleStatement Grammar
| print ExpressionList ${
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");
###### Binode types
Use,
+###### expr precedence
+ $TERM use
+
###### SimpleStatement Grammar
| use Expression ${
$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;
###### ComplexStatement Grammar
| CondStatement ${ $0 = $<1; }$
+###### expr precedence
+ $TERM for then while do
+ $TERM else
+ $TERM switch case
+
###### Grammar
$*cond_statement
- // both ForThen and Whilepart open scopes, and CondSuffix only
+ // A CondStatement must end with EOL, as does CondSuffix and
+ // IfSuffix.
+ // ForPart, ThenPart, SwitchPart, CasePart are non-empty and
+ // may or may not end with EOL
+ // WhilePart and IfPart include an appropriate Suffix
+
+
+ // Both ForPart and Whilepart open scopes, and CondSuffix only
// closes one - so in the first branch here we have another to close.
- 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(config2context(config), CloseSequential);
+ CondStatement -> ForPart OptNL ThenPart OptNL WhilePart CondSuffix ${
+ $0 = $<CS;
+ $0->forpart = $<FP;
+ $0->thenpart = $<TP;
+ $0->condpart = $WP.condpart; $WP.condpart = NULL;
+ $0->dopart = $WP.dopart; $WP.dopart = NULL;
+ var_block_close(c, CloseSequential);
}$
- | forPart WhilePart CondSuffix ${
- $0 = $<3;
- $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);
+ | ForPart OptNL WhilePart CondSuffix ${
+ $0 = $<CS;
+ $0->forpart = $<FP;
+ $0->condpart = $WP.condpart; $WP.condpart = NULL;
+ $0->dopart = $WP.dopart; $WP.dopart = NULL;
+ var_block_close(c, CloseSequential);
}$
- | whilePart CondSuffix ${
- $0 = $<2;
- $0->condpart = $1.condpart; $1.condpart = NULL;
- $0->dopart = $1.dopart; $1.dopart = NULL;
+ | WhilePart CondSuffix ${
+ $0 = $<CS;
+ $0->condpart = $WP.condpart; $WP.condpart = NULL;
+ $0->dopart = $WP.dopart; $WP.dopart = NULL;
}$
- | switchPart CondSuffix ${
- $0 = $<2;
- $0->condpart = $<1;
+ | SwitchPart OptNL CasePart CondSuffix ${
+ $0 = $<CS;
+ $0->condpart = $<SP;
+ $CP->next = $0->casepart;
+ $0->casepart = $<CP;
}$
- | ifPart IfSuffix ${
- $0 = $<2;
- $0->condpart = $1.condpart; $1.condpart = NULL;
- $0->thenpart = $1.thenpart; $1.thenpart = NULL;
+ | SwitchPart : IN OptNL CasePart CondSuffix OUT Newlines ${
+ $0 = $<CS;
+ $0->condpart = $<SP;
+ $CP->next = $0->casepart;
+ $0->casepart = $<CP;
+ }$
+ | IfPart IfSuffix ${
+ $0 = $<IS;
+ $0->condpart = $IP.condpart; $IP.condpart = NULL;
+ $0->thenpart = $IP.thenpart; $IP.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);
+ }$
+ | Newlines CasePart CondSuffix ${
+ $0 = $<CS;
+ $CP->next = $0->casepart;
+ $0->casepart = $<CP;
}$
| CasePart CondSuffix ${
- $0 = $<2;
- $1->next = $0->casepart;
- $0->casepart = $<1;
+ $0 = $<CS;
+ $CP->next = $0->casepart;
+ $0->casepart = $<CP;
}$
- $void
- Case -> case
- | NEWLINE Case
- $*casepart
- CasePart -> Case Expression OpenScope Block ${
- $0 = calloc(1,sizeof(struct casepart));
- $0->value = $<2;
- $0->action = $<4;
- var_block_close(config2context(config), CloseParallel);
- }$
+ IfSuffix -> Newlines ${ $0 = new(cond_statement); }$
+ | Newlines ElsePart ${ $0 = $<EP; }$
+ | ElsePart ${$0 = $<EP; }$
- $*cond_statement
- IfSuffix -> ${ $0 = new(cond_statement); }$
- | NEWLINE IfSuffix ${ $0 = $<2; }$
- | else OpenScope Block ${
+ ElsePart -> else OpenBlock Newlines ${
$0 = new(cond_statement);
- $0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
+ $0->elsepart = $<OB;
+ var_block_close(c, CloseElse);
}$
| else OpenScope CondStatement ${
$0 = new(cond_statement);
- $0->elsepart = $<3;
- var_block_close(config2context(config), CloseElse);
+ $0->elsepart = $<CS;
+ 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 ${
- $0 = reorder_bilist($<3);
- }$
- | for OpenScope Block ${
- $0 = $<3;
+ $*casepart
+ CasePart -> case Expression OpenScope ColonBlock ${
+ $0 = calloc(1,sizeof(struct casepart));
+ $0->value = $<Ex;
+ $0->action = $<Bl;
+ var_block_close(c, CloseParallel);
}$
- ThenPart -> Then OpenScope SimpleStatements ${
- $0 = reorder_bilist($<3);
- var_block_close(config2context(config), CloseSequential);
- }$
- | Then OpenScope Block ${
- $0 = $<3;
- var_block_close(config2context(config), CloseSequential);
+ $*exec
+ // These scopes are closed in CondSuffix
+ ForPart -> for OpenBlock ${
+ $0 = $<Bl;
}$
- // This scope is closed in CondSuffix
- WhileHead -> While OpenScope Block ${
- $0 = $<3;
- }$
- whileHead -> while OpenScope Block ${
- $0 = $<3;
+ ThenPart -> then OpenBlock ${
+ $0 = $<OB;
+ var_block_close(c, CloseSequential);
}$
$cond_statement
// This scope is closed in CondSuffix
- 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;
+ WhilePart -> while UseBlock OptNL do Block ${
+ $0.condpart = $<UB;
+ $0.dopart = $<Bl;
}$
- 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;
+ | while OpenScope Expression ColonBlock ${
+ $0.condpart = $<Exp;
+ $0.dopart = $<Bl;
}$
- ifPart -> if OpenScope Expression OpenScope Block ${
- $0.type = Xcond_statement;
- $0.condpart = $<3;
- $0.thenpart = $<5;
- var_block_close(config2context(config), CloseParallel);
+ IfPart -> if UseBlock OptNL then OpenBlock ClosePara ${
+ $0.condpart = $<UB;
+ $0.thenpart = $<Bl;
+ }$
+ | if OpenScope Expression OpenScope ColonBlock ClosePara ${
+ $0.condpart = $<Ex;
+ $0.thenpart = $<Bl;
}$
- | if OpenScope Block Then OpenScope Block ${
- $0.type = Xcond_statement;
- $0.condpart = $<3;
- $0.thenpart = $<6;
- var_block_close(config2context(config), CloseParallel);
+ | if OpenScope Expression OpenScope OptNL then Block ClosePara ${
+ $0.condpart = $<Ex;
+ $0.thenpart = $<Bl;
}$
$*exec
// This scope is closed in CondSuffix
- switchPart -> switch OpenScope Expression ${
- $0 = $<3;
+ SwitchPart -> switch OpenScope Expression ${
+ $0 = $<Ex;
}$
- | switch OpenScope Block ${
- $0 = $<3;
+ | switch UseBlock ${
+ $0 = $<Bl;
}$
###### print exec cases
struct casepart *cp;
if (cs->forpart) {
do_indent(indent, "for");
- if (bracket) printf(" {\n"); else printf(":\n");
+ if (bracket) printf(" {\n"); else printf("\n");
print_exec(cs->forpart, indent+1, bracket);
if (cs->thenpart) {
if (bracket)
do_indent(indent, "} then {\n");
else
- do_indent(indent, "then:\n");
+ do_indent(indent, "then\n");
print_exec(cs->thenpart, indent+1, bracket);
}
if (bracket) do_indent(indent, "}\n");
if (bracket)
do_indent(indent, "while {\n");
else
- do_indent(indent, "while:\n");
+ do_indent(indent, "while\n");
print_exec(cs->condpart, indent+1, bracket);
if (bracket)
do_indent(indent, "} do {\n");
else
- do_indent(indent, "do:\n");
+ do_indent(indent, "do\n");
print_exec(cs->dopart, indent+1, bracket);
if (bracket)
do_indent(indent, "}\n");
if (bracket)
printf(" {\n");
else
- printf(":\n");
+ printf("\n");
print_exec(cs->elsepart, indent+1, bracket);
if (bracket)
do_indent(indent, "}\n");
###### Parser: grammar
$void
- Ocean -> DeclarationList
+ Ocean -> OptNL DeclarationList
+
+ OptNL ->
+ | OptNL NEWLINE
+ Newlines -> NEWLINE
+ | Newlines NEWLINE
DeclarationList -> Declaration
| DeclarationList Declaration
- Declaration -> DeclareConstant
+ Declaration -> ERROR Newlines ${
+ tok_err(c,
+ "error: unhandled parse error", &$1);
+ }$
+ | DeclareConstant
| DeclareProgram
| DeclareStruct
- | NEWLINE
## top level grammar
###### top level grammar
- DeclareConstant -> const Open ConstList Close
- | const Open SimpleConstList }
- | const : ConstList
- | const SimpleConstList NEWLINE
+ DeclareConstant -> const { IN OptNL ConstList OUT OptNL } Newlines
+ | const { SimpleConstList } Newlines
+ | const IN OptNL ConstList OUT Newlines
+ | const SimpleConstList Newlines
- ConstList -> ComplexConsts
- | NEWLINE ConstList
- ComplexConsts -> ComplexConst ComplexConsts
- | ComplexConst
- ComplexConst -> SimpleConstList NEWLINE
+ ConstList -> ConstList SimpleConstLine
+ | SimpleConstLine
SimpleConstList -> SimpleConstList ; Const
| Const
| SimpleConstList ;
+ SimpleConstLine -> SimpleConstList Newlines
+ | ERROR Newlines ${ tok_err(c, "Syntax error in constant", &$1); }$
$*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);
}
if (target == -1) {
if (i)
- printf("const:\n");
+ printf("const\n");
target = i;
} else {
printf(" %.*s :: ", v->name->name.len, v->name->name.txt);
###### 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 ${
+ Program -> program OpenScope Varlist ColonBlock Newlines ${
$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();
- }$
- | ERROR ${
- tok_err(config2context(config),
- "error: unhandled parse error", &$1);
+ $0->left = reorder_bilist($<Vl);
+ $0->right = $<Bl;
+ var_block_close(c, CloseSequential);
+ if (c->scope_stack && !c->parse_error) abort();
}$
Varlist -> Varlist ArgDecl ${
$*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:
+ const
pi ::= 3.141_592_6
four ::= 2 + 2 ; five ::= 10/2
const pie ::= "I like Pie";
cake ::= "The cake is"
++ " a lie"
- struct fred:
+ struct fred
size:[four]number
name:string
alive:Boolean
*/
if A > B:
bigger := "yes"
- else:
+ else
bigger := "no"
print "Is", A, "bigger than", B,"? ", bigger
/* If a variable is not used after the 'if', no
if A > B * 2:
double:string = "yes"
print A, "is more than twice", B, "?", double
- else:
+ else
double := B*2
print "double", B, "is", double
while a != b:
if a < b:
b = b - a
- else:
+ else
a = a - b
print "GCD of", A, "and", B,"is", a
else if a <= 0:
print a, "is not positive, cannot calculate GCD"
- else:
+ else
print b, "is not positive, cannot calculate GCD"
- for:
+ for
togo := 10
f1 := 1; f2 := 1
print "Fibonacci:", f1,f2,
print ""
/* Binary search... */
- for:
+ for
lo:= 0; hi := 100
target := 77
- while:
+ while
mid := (lo + hi) / 2
if mid == target:
use Found
if mid < target:
lo = mid
- else:
+ else
hi = mid
if hi - lo < 1:
use GiveUp
use True
- do: pass
+ do pass
case Found:
print "Yay, I found", target
case GiveUp:
print "", list[i],
print
+ if 1 == 2 then print "yes"; else print "no"
+
bob:fred
bob.name = "Hello"
bob.alive = (bob.name == "Hello")