]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani.mdc
oceani: modify grammar to not waste stack on newlines
[ocean] / csrc / oceani.mdc
index a3eba942acbd3cd92e407ee61b83446e1893bbf0..06f71be3268da0b30eb962be214eab1c4d23f558 100644 (file)
@@ -123,6 +123,9 @@ structures can be used.
        #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>
@@ -169,8 +172,9 @@ structures can be used.
                struct parse_context context = {
                        .config = {
                                .ignored = (1 << TK_line_comment)
                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 = "_",
                        },
                                .word_start = "_",
                                .word_cont = "_",
                        },
@@ -1001,7 +1005,7 @@ like "if" and the code following it.
 ###### Grammar
 
        $void
 ###### Grammar
 
        $void
-       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:
 
@@ -1034,7 +1038,6 @@ Each variable records a scope depth and is in one of four states:
   in scope.  It is permanently out of scope now and can be removed from
   the "in scope" stack.
 
   in scope.  It is permanently out of scope now and can be removed from
   the "in scope" stack.
 
-
 ###### variable fields
        int depth, min_depth;
        enum { OutScope, PendingScope, CondScope, InScope } scope;
 ###### variable fields
        int depth, min_depth;
        enum { OutScope, PendingScope, CondScope, InScope } scope;
@@ -1093,7 +1096,7 @@ list of in_scope names.
 
                        v = t->previous;
                        free_value(t->val);
 
                        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);
                                // This is a global constant
                                free_exec(t->where_decl);
                        free(t);
@@ -1455,7 +1458,9 @@ propagation is needed.
 ###### core functions
 
        static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
 ###### 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;
 
        {
                struct type *t;
 
@@ -1476,6 +1481,16 @@ propagation is needed.
                return Tnone;
        }
 
                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
 #### Interpreting
 
 Interpreting an `exec` doesn't require anything but the `exec`.  State
@@ -1491,7 +1506,6 @@ in `val` or the pointer to a value in `lval`.  If `lval` is set, but a
 simple value is required, `inter_exec()` will dereference `lval` to
 get the value.
 
 simple value is required, `inter_exec()` will dereference `lval` to
 get the value.
 
-
 ###### core functions
 
        struct lrval {
 ###### core functions
 
        struct lrval {
@@ -1664,7 +1678,6 @@ make a copy of an array with controllable depth.
                $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)
@@ -1687,13 +1700,12 @@ make a copy of an array with controllable depth.
        }$
 
        | [ 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);
                else if (!v->constant)
                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;
 
                $0 = calloc(1, sizeof(struct type));
                *($0) = array_prototype;
@@ -1732,9 +1744,9 @@ make a copy of an array with controllable depth.
 
 ###### print binode cases
        case Index:
 
 ###### print binode cases
        case Index:
-               print_exec(b->left, -1, 0);
+               print_exec(b->left, -1, bracket);
                printf("[");
                printf("[");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
                printf("]");
                break;
 
                printf("]");
                break;
 
@@ -1747,13 +1759,11 @@ make a copy of an array with controllable depth.
                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);
                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);
                        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;
                }
                        }
                        return t->array.member;
                }
@@ -1920,7 +1930,7 @@ function will be needed.
        case Xfieldref:
        {
                struct fieldref *f = cast(fieldref, e);
        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;
        }
                printf(".%.*s", f->name.len, f->name.txt);
                break;
        }
@@ -1950,19 +1960,15 @@ function will be needed.
                                 f->left, st, 0, NULL);
                else if (f->index == -2) {
                        f->index = find_struct_index(st, f->name);
                                 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);
                                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 (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);
                                type_err(c, "error: have %1 but need %2", prog,
                                         ft, rules, type);
-                               *ok = 0;
-                       }
                        return ft;
                }
                break;
                        return ft;
                }
                break;
@@ -1995,41 +2001,57 @@ function will be needed.
 
 ###### top level grammar
        DeclareStruct -> struct IDENTIFIER FieldBlock ${ {
 
 ###### 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;
-               }
-       } }$
+                       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;
+                       }
+               } }$
+               | DeclareStruct NEWLINE
 
 
+       $void
+       Newlines -> NEWLINE
+               | Newlines NEWLINE
+       Open -> {
+               | Newlines {
+       Close -> }
+               | Newlines }
        $*fieldlist
        $*fieldlist
-       FieldBlock -> Open SimpleFieldList Close ${ $0 = $<2; }$
-               | Open Newlines SimpleFieldList Close ${ $0 = $<3; }$
-               | : FieldList  ${ $0 = $<2; }$
-
-       FieldList -> Field NEWLINE ${ $0 = $<1; }$
-               | FieldList NEWLINE ${ $0 = $<1; }$
-               | FieldList Field NEWLINE ${
+       FieldBlock -> Open FieldList } ${ $0 = $<2; }$
+               | Open SimpleFieldList } ${ $0 = $<2; }$
+               | : FieldList $$NEWLINE ${ $0 = $<2; }$
+
+       FieldList -> FieldLines ${ $0 = $<1; }$
+               | Newlines FieldLines ${ $0 = $<2; }$
+       FieldLines -> SimpleFieldListLine ${ $0 = $<1; }$
+               | FieldLines SimpleFieldListLine ${
                        $2->prev = $<1;
                        $0 = $<2;
                }$
 
                        $2->prev = $<1;
                        $0 = $<2;
                }$
 
-       SimpleFieldList -> Field ; ${ $0 = $<1; }$
-               | SimpleFieldList Field ; ${
-                       $2->prev = $<1;
-                       $0 = $<2;
+       SimpleFieldListLine -> SimpleFieldList NEWLINE ${ $0 = $<1; }$
+               | SimpleFieldListLine NEWLINE ${ $0 = $<1; }$
+               | ERROR NEWLINE ${ tok_err(c, "Syntax error in struct field", &$1); }$
+
+       SimpleFieldList -> Field ${ $0 = $<1; }$
+               | SimpleFieldList ; Field ${
+                       $3->prev = $<1;
+                       $0 = $<3;
+               }$
+               | SimpleFieldList ; ${
+                       $0 = $<1;
                }$
 
        Field -> IDENTIFIER : Type = Expression ${ {
                }$
 
        Field -> IDENTIFIER : Type = Expression ${ {
@@ -2041,10 +2063,10 @@ function will be needed.
                        $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;
+                               c->parse_error = 1;
                        else
                                $0->f.init = interp_exec($5);
                } }$
                        else
                                $0->f.init = interp_exec($5);
                } }$
@@ -2147,7 +2169,7 @@ an executable.
                        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",
                                                &$1);
                        }
                        }$
                                                &$1);
                        }
                        }$
@@ -2158,7 +2180,7 @@ an executable.
                        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",
                                        &$1);
                        }
                        }$
                                        &$1);
                        }
                        }$
@@ -2169,7 +2191,7 @@ an executable.
                        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",
                                        &$1);
                        }
                        }$
                                        &$1);
                        }
                        }$
@@ -2190,11 +2212,9 @@ an executable.
        case Xval:
        {
                struct val *val = cast(val, prog);
        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);
                        type_err(c, "error: expected %1%r found %2",
                                   prog, type, rules, val->val.type);
-                       *ok = 0;
-               }
                return val->val.type;
        }
 
                return val->val.type;
        }
 
@@ -2258,38 +2278,38 @@ link to find the primary instance.
 
        $*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);
                        $0->var = v;
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
                                 $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 :: ${ {
                                 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);
                        $0->var = v;
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
                                 $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 ${ {
                                 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) {
@@ -2297,16 +2317,16 @@ link to find the primary instance.
                        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);
                        $0->var = v;
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
                                 $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 ${ {
                                 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) {
@@ -2315,25 +2335,25 @@ link to find the primary instance.
                        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);
                        $0->var = v;
                        $0->var = v;
-                       type_err(config2context(config), "error: variable '%v' redeclared",
+                       type_err(c, "error: variable '%v' redeclared",
                                 $0, NULL, 0, NULL);
                                 $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 ${ {
                                 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) {
                        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;
                        }
                }
                                v->where_set = $0;
                        }
                }
@@ -2343,9 +2363,9 @@ link to find the primary instance.
 
        $*type
        Type -> IDENTIFIER ${
 
        $*type
        Type -> IDENTIFIER ${
-               $0 = find_type(config2context(config), $1.txt);
+               $0 = find_type(c, $1.txt);
                if (!$0) {
                if (!$0) {
-                       tok_err(config2context(config),
+                       tok_err(c,
                                "error: undefined type", &$1);
 
                        $0 = Tnone;
                                "error: undefined type", &$1);
 
                        $0 = Tnone;
@@ -2385,7 +2405,6 @@ link to find the primary instance.
                struct variable *v = var->var;
                if (!v) {
                        type_err(c, "%d:BUG: no variable!!", prog, NULL, 0, NULL); // NOTEST
                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)
                        return Tnone;                                   // NOTEST
                }
                if (v->merged)
@@ -2395,9 +2414,11 @@ link to find the primary instance.
                                 prog, NULL, 0, NULL);
                        type_err(c, "info: name was defined as a constant here",
                                 v->where_decl, NULL, 0, NULL);
                                 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;
                }
                        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);
                if (v->val.type == NULL) {
                        if (type && *ok != 0) {
                                v->val = val_prepare(type);
@@ -2411,7 +2432,6 @@ link to find the primary instance.
                                 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);
                                 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;
                }
                if (!type)
                        return v->val.type;
@@ -2460,8 +2480,11 @@ room for ambiguity, so a full conditional expression is allowed in there.
 
 ###### Grammar
 
 
 ###### Grammar
 
+       $LEFT if $$ifelse
+       ## expr precedence
+
        $*exec
        $*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;
                        struct binode *b1 = new(binode);
                        struct binode *b2 = new(binode);
                        b1->op = CondExpr;
@@ -2472,17 +2495,19 @@ room for ambiguity, so a full conditional expression is allowed in there.
                        b2->right = $<5;
                        $0 = b1;
                } }$
                        b2->right = $<5;
                        $0 = b1;
                } }$
-               | BoolExpr ${ $0 = $<1; }$
+               ## expression grammar
 
 ###### print binode cases
 
        case CondExpr:
                b2 = cast(binode, b->right);
 
 ###### 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 ");
                printf(" if ");
-               print_exec(b->left, -1, 0);
+               print_exec(b->left, -1, bracket);
                printf(" else ");
                printf(" else ");
-               print_exec(b2->right, -1, 0);
+               print_exec(b2->right, -1, bracket);
+               if (bracket) printf(")");
                break;
 
 ###### propagate binode cases
                break;
 
 ###### propagate binode cases
@@ -2528,73 +2553,83 @@ if the result would make a difference.
        OrElse,
        Not,
 
        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;
                } }$
                        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;
                } }$
                        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;
                } }$
                        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;
                } }$
                        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;
                } }$
                        struct binode *b = new(binode);
                        b->op = Not;
                        b->right = $<2;
                        $0 = b;
                } }$
-               ## other BFact
 
 ###### print binode cases
        case And:
 
 ###### print binode cases
        case And:
-               print_exec(b->left, -1, 0);
+               if (bracket) printf("(");
+               print_exec(b->left, -1, bracket);
                printf(" and ");
                printf(" and ");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
+               if (bracket) printf(")");
                break;
        case AndThen:
                break;
        case AndThen:
-               print_exec(b->left, -1, 0);
+               if (bracket) printf("(");
+               print_exec(b->left, -1, bracket);
                printf(" and then ");
                printf(" and then ");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
+               if (bracket) printf(")");
                break;
        case Or:
                break;
        case Or:
-               print_exec(b->left, -1, 0);
+               if (bracket) printf("(");
+               print_exec(b->left, -1, bracket);
                printf(" or ");
                printf(" or ");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
+               if (bracket) printf(")");
                break;
        case OrElse:
                break;
        case OrElse:
-               print_exec(b->left, -1, 0);
+               if (bracket) printf("(");
+               print_exec(b->left, -1, bracket);
                printf(" or else ");
                printf(" or else ");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
+               if (bracket) printf(")");
                break;
        case Not:
                break;
        case Not:
+               if (bracket) printf("(");
                printf("not ");
                printf("not ");
-               print_exec(b->right, -1, 0);
+               print_exec(b->right, -1, bracket);
+               if (bracket) printf(")");
                break;
 
 ###### propagate binode cases
                break;
 
 ###### propagate binode cases
@@ -2606,11 +2641,9 @@ if the result would make a difference.
                /* both must be Tbool, result is Tbool */
                propagate_types(b->left, c, ok, Tbool, 0);
                propagate_types(b->right, c, ok, Tbool, 0);
                /* 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);
                        type_err(c, "error: %1 operation found where %2 expected", prog,
                                   Tbool, 0, type);
-                       *ok = 0;
-               }
                return Tbool;
 
 ###### interp binode cases
                return Tbool;
 
 ###### interp binode cases
@@ -2669,15 +2702,17 @@ expression operator.
        Eql,
        NEql,
 
        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;
        } }$
                struct binode *b = new(binode);
                b->op = $2.op;
                b->left = $<1;
                b->right = $<3;
                $0 = b;
        } }$
-       | Expr ${ $0 = $<1; }$
 
 ###### Grammar
 
 
 ###### Grammar
 
@@ -2697,7 +2732,8 @@ expression operator.
        case GtrEq:
        case Eql:
        case NEql:
        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;
                switch(b->op) {
                case Less:   printf(" < "); break;
                case LessEq: printf(" <= "); break;
@@ -2707,7 +2743,8 @@ expression operator.
                case NEql:   printf(" != "); break;
                default: abort();               // NOTEST
                }
                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
                break;
 
 ###### propagate binode cases
@@ -2726,11 +2763,9 @@ expression operator.
                        if (t)
                                t = propagate_types(b->left, c, ok, t, 0);
                }
                        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);
                        type_err(c, "error: Comparison returns %1 but %2 expected", prog,
                                    Tbool, rules, type);
-                       *ok = 0;
-               }
                return Tbool;
 
 ###### interp binode cases
                return Tbool;
 
 ###### interp binode cases
@@ -2779,34 +2814,35 @@ precedence is handled better I might be able to discard this.
        Absolute, Negate,
        Bracket,
 
        Absolute, Negate,
        Bracket,
 
-###### Grammar
+###### expr precedence
+       $LEFT + - Eop
+       $LEFT * / % ++ Top
+       $LEFT Uop
 
 
-       $*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;
                } }$
                        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;
                } }$
                        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;
                } }$
                        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;
                        struct binode *b = new(binode);
                        b->op = $1.op;
                        b->right = $<2;
@@ -2834,7 +2870,8 @@ precedence is handled better I might be able to discard this.
        case Divide:
        case Concat:
        case Rem:
        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;
                switch(b->op) {
                case Plus:   fputs(" + ", stdout); break;
                case Minus:  fputs(" - ", stdout); break;
@@ -2844,19 +2881,24 @@ precedence is handled better I might be able to discard this.
                case Concat: fputs(" ++ ", stdout); break;
                default: abort();       // NOTEST
                }                       // NOTEST
                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:
                break;
        case Absolute:
+               if (bracket) printf("(");
                printf("+");
                printf("+");
-               print_exec(b->right, indent, 0);
+               print_exec(b->right, indent, bracket);
+               if (bracket) printf(")");
                break;
        case Negate:
                break;
        case Negate:
+               if (bracket) printf("(");
                printf("-");
                printf("-");
-               print_exec(b->right, indent, 0);
+               print_exec(b->right, indent, bracket);
+               if (bracket) printf(")");
                break;
        case Bracket:
                printf("(");
                break;
        case Bracket:
                printf("(");
-               print_exec(b->right, indent, 0);
+               print_exec(b->right, indent, bracket);
                printf(")");
                break;
 
                printf(")");
                break;
 
@@ -2873,22 +2915,18 @@ precedence is handled better I might be able to discard this.
                 * unary ops fit here too */
                propagate_types(b->left, c, ok, Tnum, 0);
                propagate_types(b->right, c, ok, Tnum, 0);
                 * 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);
                        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);
                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);
                        type_err(c, "error: Concat returns %1 but %2 expected", prog,
                                   Tstr, rules, type);
-                       *ok = 0;
-               }
                return Tstr;
 
        case Bracket:
                return Tstr;
 
        case Bracket:
@@ -2948,7 +2986,6 @@ precedence is handled better I might be able to discard this.
                rv.str = text_join(left.str, right.str);
                break;
 
                rv.str = text_join(left.str, right.str);
                break;
 
-
 ###### value functions
 
        static struct text text_join(struct text a, struct text b)
 ###### value functions
 
        static struct text text_join(struct text a, struct text b)
@@ -3019,45 +3056,41 @@ is in-place.
 
 ###### Grammar
 
 
 ###### Grammar
 
-       $void
-       OptNL -> Newlines
-               |
-
-       Newlines -> NEWLINE
-               | Newlines NEWLINE
-
        $*binode
        $*binode
-       Open -> {
-               | NEWLINE {
-       Close -> }
-               | NEWLINE }
        Block -> Open Statementlist Close ${ $0 = $<2; }$
        Block -> Open Statementlist Close ${ $0 = $<2; }$
-               | Open Newlines Statementlist Close ${ $0 = $<3; }$
                | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$
                | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$
-               | Open Newlines SimpleStatements } ${ $0 = reorder_bilist($<3); }$
-               | : Statementlist ${ $0 = $<2; }$
-               | : SimpleStatements ${ $0 = reorder_bilist($<2); }$
+               | : SimpleStatements $$NEWLINE ${ $0 = reorder_bilist($<2); }$
+               | : Statementlist $$NEWLINE ${ $0 = $<2; }$
 
        Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$
 
        Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$
+               | Newlines ComplexStatements ${ $0 = reorder_bilist($<2); }$
 
        ComplexStatements -> ComplexStatements ComplexStatement ${
 
        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 ${
                | 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
                }$
 
        $*exec
-       ComplexStatement -> SimpleStatements NEWLINE ${
+       ComplexStatement -> SimpleStatementLine ${
                        $0 = reorder_bilist($<1);
                        }$
                        $0 = reorder_bilist($<1);
                        }$
+               | ComplexStatement NEWLINE ${ $0 = $<1; }$
                ## ComplexStatement Grammar
 
        $*binode
                ## ComplexStatement Grammar
 
        $*binode
@@ -3075,7 +3108,11 @@ is in-place.
                        }$
                | SimpleStatements ; ${ $0 = $<1; }$
 
                        }$
                | SimpleStatements ; ${ $0 = $<1; }$
 
+       SimpleStatementLine -> SimpleStatements NEWLINE ${ $0 = $<1; }$
+               | SimpleStatementLine NEWLINE ${ $0 = $<1; }$
+
        SimpleStatement -> pass ${ $0 = NULL; }$
        SimpleStatement -> pass ${ $0 = NULL; }$
+               | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
                ## SimpleStatement Grammar
 
 ###### print binode cases
                ## SimpleStatement Grammar
 
 ###### print binode cases
@@ -3085,10 +3122,10 @@ is in-place.
                        if (b->left == NULL)
                                printf("pass");
                        else
                        if (b->left == NULL)
                                printf("pass");
                        else
-                               print_exec(b->left, indent, 0);
+                               print_exec(b->left, indent, bracket);
                        if (b->right) {
                                printf("; ");
                        if (b->right) {
                                printf("; ");
-                               print_exec(b->right, indent, 0);
+                               print_exec(b->right, indent, bracket);
                        }
                } else {
                        // block, one per line
                        }
                } else {
                        // block, one per line
@@ -3120,11 +3157,9 @@ is in-place.
                        if (t && t != Tnone && t != Tbool) {
                                if (!type)
                                        type = t;
                        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);
                                        type_err(c, "error: expected %1%r, found %2",
                                                 e->left, type, rules, t);
-                                       *ok = 0;
-                               }
                        }
                }
                return type;
                        }
                }
                return type;
@@ -3193,7 +3228,7 @@ same solution.
                while (b) {
                        if (b->left) {
                                printf(" ");
                while (b) {
                        if (b->left) {
                                printf(" ");
-                               print_exec(b->left, -1, 0);
+                               print_exec(b->left, -1, bracket);
                                if (b->right)
                                        printf(",");
                        }
                                if (b->right)
                                        printf(",");
                        }
@@ -3264,7 +3299,7 @@ it is declared, and error will be raised as the name is created as
 
        | VariableDecl ${
                        if ($1->var->where_set == NULL) {
 
        | 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 {
                                         "Variable declared with no type or value: %v",
                                         $1, NULL, 0, NULL);
                        } else {
@@ -3279,9 +3314,9 @@ it is declared, and error will be raised as the name is created as
 
        case Assign:
                do_indent(indent, "");
 
        case Assign:
                do_indent(indent, "");
-               print_exec(b->left, indent, 0);
+               print_exec(b->left, indent, bracket);
                printf(" = ");
                printf(" = ");
-               print_exec(b->right, indent, 0);
+               print_exec(b->right, indent, bracket);
                if (indent >= 0)
                        printf("\n");
                break;
                if (indent >= 0)
                        printf("\n");
                break;
@@ -3290,7 +3325,7 @@ it is declared, and error will be raised as the name is created as
                {
                struct variable *v = cast(var, b->left)->var;
                do_indent(indent, "");
                {
                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 (cast(var, b->left)->var->constant) {
                        if (v->where_decl == v->where_set) {
                                printf("::");
@@ -3308,7 +3343,7 @@ it is declared, and error will be raised as the name is created as
                }
                if (b->right) {
                        printf("= ");
                }
                if (b->right) {
                        printf("= ");
-                       print_exec(b->right, indent, 0);
+                       print_exec(b->right, indent, bracket);
                }
                if (indent >= 0)
                        printf("\n");
                }
                if (indent >= 0)
                        printf("\n");
@@ -3340,10 +3375,8 @@ it is declared, and error will be raised as the name is created as
                                propagate_types(b->left, c, ok, t,
                                                (b->op == Assign ? Rnoconstant : 0));
                }
                                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);
                        type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);
-                       *ok = 0;
-               }
                return Tnone;
 
                break;
                return Tnone;
 
                break;
@@ -3391,13 +3424,21 @@ function.
                $0 = new_pos(binode, $1);
                $0->op = Use;
                $0->right = $<2;
                $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 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;
                if (indent >= 0)
                        printf("\n");
                break;
@@ -3531,36 +3572,46 @@ defined.
        $*cond_statement
        // both ForThen and Whilepart open scopes, and CondSuffix only
        // closes one - so in the first branch here we have another to close.
        $*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 = $<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;
                        $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->dopart = $1.dopart; $1.dopart = NULL;
                        }$
                        }$
                | WhilePart CondSuffix ${
                        $0 = $<2;
                        $0->condpart = $1.condpart; $1.condpart = NULL;
                        $0->dopart = $1.dopart; $1.dopart = NULL;
                        }$
-               | SwitchPart CondSuffix ${
-                       $0 = $<2;
+               | SwitchPart CasePart CondSuffix ${
+                       $0 = $<3;
                        $0->condpart = $<1;
                        $0->condpart = $<1;
+                       $2->next = $0->casepart;
+                       $0->casepart = $<2;
                        }$
                | 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
                        }$
                | 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
                        }$
 
        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;
@@ -3569,43 +3620,28 @@ defined.
                }$
 
        $*casepart
                }$
 
        $*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;
                        $0 = calloc(1,sizeof(struct casepart));
                        $0->value = $<2;
                        $0->action = $<4;
-                       var_block_close(config2context(config), CloseParallel);
+                       var_block_close(c, CloseParallel);
                }$
                }$
+               | CasePart NEWLINE ${ $0 = $<1; }$
 
        $*cond_statement
 
        $*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); }$
+               | IfSuffix NEWLINE ${ $0 = $<1; }$
                | 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);
-               }$
-               | 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;
                }$
                | else OpenScope CondStatement ${
                        $0 = new(cond_statement);
                        $0->elsepart = $<3;
-                       var_block_close(config2context(config), CloseElse);
+                       var_block_close(c, CloseElse);
                }$
 
                }$
 
-
        $*exec
        // These scopes are closed in CondSuffix
        ForPart -> for OpenScope SimpleStatements ${
        $*exec
        // These scopes are closed in CondSuffix
        ForPart -> for OpenScope SimpleStatements ${
@@ -3614,58 +3650,49 @@ defined.
                |  for OpenScope Block ${
                        $0 = $<3;
                }$
                |  for OpenScope Block ${
                        $0 = $<3;
                }$
+               |  ForPart NEWLINE ${ $0 = $<1; }$
 
        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);
-               }$
-
-       ThenPartNL -> ThenPart OptNL ${
-                       $0 = $<1;
+                       var_block_close(c, CloseSequential);
                }$
                }$
+               |  ThenPart NEWLINE ${ $0 = $<1; }$
 
        // This scope is closed in CondSuffix
 
        // This scope is closed in CondSuffix
-       WhileHead -> while OpenScope Block ${
-               $0 = $<3;
-               }$
+       WhileHead -> while OpenScope Block ${ $0 = $<3; }$
+               | WhileHead NEWLINE ${ $0 = $<1; }$
 
        $cond_statement
 
        $cond_statement
-       ForThen -> ForPart OptNL ThenPartNL ${
-                       $0.forpart = $<1;
-                       $0.thenpart = $<3;
-               }$
-               | ForPart OptNL ${
-                       $0.forpart = $<1;
-               }$
-
        // This scope is closed in CondSuffix
        WhilePart -> while OpenScope Expression Block ${
                        $0.type = Xcond_statement;
                        $0.condpart = $<3;
                        $0.dopart = $<4;
                }$
        // This scope is closed in CondSuffix
        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.type = Xcond_statement;
                        $0.condpart = $<1;
-                       $0.dopart = $<4;
+                       $0.dopart = $<3;
                }$
                }$
+               | WhilePart NEWLINE ${ $0 = $<1; }$
 
        IfPart -> if OpenScope Expression OpenScope Block ${
                        $0.type = Xcond_statement;
                        $0.condpart = $<3;
                        $0.thenpart = $<5;
 
        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.type = Xcond_statement;
                        $0.condpart = $<3;
-                       $0.thenpart = $<7;
-                       var_block_close(config2context(config), CloseParallel);
+                       $0.thenpart = $<6;
+                       var_block_close(c, CloseParallel);
                }$
                }$
+               | IfPart NEWLINE ${ $0 = $<1; }$
 
        $*exec
        // This scope is closed in CondSuffix
 
        $*exec
        // This scope is closed in CondSuffix
@@ -3675,6 +3702,7 @@ defined.
                | switch OpenScope Block ${
                        $0 = $<3;
                }$
                | switch OpenScope Block ${
                        $0 = $<3;
                }$
+               | SwitchPart NEWLINE ${ $0 = $<1; }$
 
 ###### print exec cases
 
 
 ###### print exec cases
 
@@ -3912,14 +3940,19 @@ various declarations in the parse context.
 
        $void
        Ocean -> DeclarationList
 
        $void
        Ocean -> DeclarationList
+               | Newlines DeclarationList
 
        DeclarationList -> Declaration
                | DeclarationList Declaration
 
 
        DeclarationList -> Declaration
                | DeclarationList Declaration
 
-       Declaration -> DeclareConstant
+       Declaration -> Declaration NEWLINE
+               | DeclareConstant
                | DeclareProgram
                | DeclareStruct
                | DeclareProgram
                | DeclareStruct
-               | NEWLINE
+               | ERROR NEWLINE ${
+                       tok_err(c,
+                               "error: unhandled parse error", &$1);
+               }$
 
        ## top level grammar
 
 
        ## top level grammar
 
@@ -3949,19 +3982,20 @@ searching through for the Nth constant for decreasing N.
 ###### top level grammar
 
        DeclareConstant -> const Open ConstList Close
 ###### top level grammar
 
        DeclareConstant -> const Open ConstList Close
-               | const Open Newlines ConstList Close
                | const Open SimpleConstList }
                | const Open SimpleConstList }
-               | const Open Newlines SimpleConstList }
-               | const : ConstList
-               | const SimpleConstList
-
-       ConstList -> ComplexConsts
-       ComplexConsts -> ComplexConst ComplexConsts
-               | ComplexConst
-       ComplexConst -> SimpleConstList NEWLINE
-       SimpleConstList -> Const ; SimpleConstList
+               | const : ConstList $$NEWLINE
+               | const SimpleConstList NEWLINE
+
+       ConstList -> ConstLines
+               | Newlines ConstLines
+       ConstLines -> ConstLines SimpleConstLine
+               | SimpleConstLine
+       SimpleConstList -> SimpleConstList ; Const
                | Const
                | Const
-               | Const ; SimpleConstList ;
+               | SimpleConstList ;
+       SimpleConstLine -> SimpleConstList NEWLINE
+               | SimpleConstLine NEWLINE
+               | ERROR NEWLINE ${ tok_err(c, "Syntax error in constant", &$1); }$
 
        $*type
        CType -> Type   ${ $0 = $<1; }$
 
        $*type
        CType -> Type   ${ $0 = $<1; }$
@@ -3971,7 +4005,7 @@ searching through for the Nth constant for decreasing N.
                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;
@@ -3979,17 +4013,17 @@ searching through for the Nth constant for decreasing N.
                        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;
+                       c->parse_error = 1;
                else if (v) {
                        v->val = interp_exec($5);
                }
                else if (v) {
                        v->val = interp_exec($5);
                }
@@ -4048,7 +4082,6 @@ analysis is a bit more interesting at this level.
 ###### 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);
@@ -4056,19 +4089,14 @@ analysis is a bit more interesting at this level.
                        c->prog = $<1;
        } }$
 
                        c->prog = $<1;
        } }$
 
-
        $*binode
        $*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;
                $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);
+               var_block_close(c, CloseSequential);
+               if (c->scope_stack && !c->parse_error) abort();
                }$
 
        Varlist -> Varlist ArgDecl ${
                }$
 
        Varlist -> Varlist ArgDecl ${
@@ -4081,7 +4109,7 @@ analysis is a bit more interesting at this level.
 
        $*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;
        } }$
@@ -4191,7 +4219,7 @@ things which will likely grow as the languages grows.
 ###### demo: hello
 
        const:
 ###### 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"
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
                cake ::= "The cake is"
@@ -4280,7 +4308,7 @@ things which will likely grow as the languages grows.
                // 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]
                // 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:
 
                print "Before sort:",
                for i:=0; then i = i + 1; while i < size: