]> ocean-lang.org Git - ocean/commitdiff
oceani: updates for new approach to parsing indents.
authorNeilBrown <neil@brown.name>
Wed, 10 Mar 2021 01:37:46 +0000 (12:37 +1100)
committerNeilBrown <neil@brown.name>
Wed, 10 Mar 2021 04:31:43 +0000 (15:31 +1100)
Now that IN is a valid stand-alone token, it makes sense to change the
grammar for ocean.
We don't need the ':' before an indent if there is some other terminal
there.  So:

  while
     statements
  do
     statements

doesn't require any ':'.
We use the ':' to separate an expression from following statements,
in 'if' and 'while' and 'case'.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index 54b08d02fd14fc6226164410754ccb99b30bf3c6..e3739ed940802dd324eebc14fec1eefdc03c8be4 100644 (file)
@@ -163,7 +163,7 @@ Now some contants
        oceani_tests += "consts"
 
 ###### test: consts
        oceani_tests += "consts"
 
 ###### test: consts
-       const:
+       const
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
                pi ::= 3.141 592 653
                four ::= 2 + 2 ; five ::= 10/2
        const pie ::= "I like Pie";
@@ -189,12 +189,12 @@ Test merging of variables from multiple cases
 
        program:
                for i:=0; then i=i+1; while i < 5:
 
        program:
                for i:=0; then i=i+1; while i < 5:
-                       switch i
+                       switch i:
                                case 0: num:="zero"
                                case 1: num:="one"
                                case 2: num:="two"
                                case 3: num:="three"
                                case 0: num:="zero"
                                case 1: num:="one"
                                case 2: num:="two"
                                case 3: num:="three"
-                               else:   num:="many"
+                               else    num:="many"
                        print num,", ",
                print
 
                        print num,", ",
                print
 
@@ -214,7 +214,7 @@ Now we need to test if/else and some different loops
                a := 4
                if a < 5:
                        print "Success"
                a := 4
                if a < 5:
                        print "Success"
-               else:
+               else
                        print "Failure"
                for b:=1; then b=b+b; while b < 100:
                        print '', b,
                        print "Failure"
                for b:=1; then b=b+b; while b < 100:
                        print '', b,
@@ -222,12 +222,12 @@ Now we need to test if/else and some different loops
                // Newtons method for square root of 2
                target ::= 2
                guess := target
                // Newtons method for square root of 2
                target ::= 2
                guess := target
-               for:
+               for
                        count: number = 0
                        count: number = 0
-               while:
+               while
                        current := guess * guess
                        use +(current - target) > 0.000000001
                        current := guess * guess
                        use +(current - target) > 0.000000001
-               do:
+               do
                        guess = (guess + (target / guess) ) / 2
                        print count, guess
                        count = count + 1
                        guess = (guess + (target / guess) ) / 2
                        print count, guess
                        count = count + 1
@@ -236,7 +236,7 @@ Now we need to test if/else and some different loops
                for j:=0; then j = j+3 ; while j < 10:
                        if j != 0 and then 20 / j > 3:
                                print "20 /", j," =", 20 / j
                for j:=0; then j = j+3 ; while j < 10:
                        if j != 0 and then 20 / j > 3:
                                print "20 /", j," =", 20 / j
-                       else:
+                       else
                                print "I won't calculate 20 /", j
                pi ::= 3.1415926535897
                if 355/113 == pi or else +(pi - 355/113) < 0.001:
                                print "I won't calculate 20 /", j
                pi ::= 3.1415926535897
                if 355/113 == pi or else +(pi - 355/113) < 0.001:
@@ -249,7 +249,7 @@ Now we need to test if/else and some different loops
                then { i = i+1 }
                while i <= 10:
                        sum = sum + i
                then { i = i+1 }
                while i <= 10:
                        sum = sum + i
-               else:
+               else
                        pass
                        print "sum 1..10 is", sum
 
                        pass
                        print "sum 1..10 is", sum
 
@@ -289,7 +289,7 @@ Here I break it into two parts, keeping the array code separate.
                 */
                if A > B:
                        bigger := "yes"
                 */
                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
                        bigger := "no"
                print "Is", A, "bigger than", B,"? ", bigger
                /* If a variable is not used after the 'if', no
@@ -298,7 +298,7 @@ Here I break it into two parts, keeping the array code separate.
                if A > B * 2:
                        double:string = "yes"
                        print A, "is more than twice", B, "?", double
                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
 
                        double := B*2
                        print "double", B, "is", double
 
@@ -309,15 +309,15 @@ Here I break it into two parts, keeping the array code separate.
                        while a != b:
                                if a < b:
                                        b = b - a
                        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"
                                        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"
 
                        print b, "is not positive, cannot calculate GCD"
 
-               for:
+               for
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
@@ -331,25 +331,25 @@ Here I break it into two parts, keeping the array code separate.
 
                if bbool:
                        print astr ++ " was the str"
 
                if bbool:
                        print astr ++ " was the str"
-               else:
+               else
                        print "I found the str over " ++ astr
 
                /* Binary search... */
                        print "I found the str over " ++ astr
 
                /* Binary search... */
-               for:
+               for
                        lo:= 0; hi := 100
                        target := 77
                        lo:= 0; hi := 100
                        target := 77
-               while:
+               while
                        mid := (lo + hi) / 2
                        if mid == target:
                                use Found
                        if mid < target:
                                lo = mid
                        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
                                hi = mid
                        if hi - lo < 1:
                                use GiveUp
                        use True
-               do: pass
+               do pass
                case Found:
                        print "Yay, I found", target
                case GiveUp:
                case Found:
                        print "Yay, I found", target
                case GiveUp:
@@ -545,7 +545,7 @@ Time to test if structure declarations and accesses work correctly.
 
 ###### test: structs
 
 
 ###### test: structs
 
-       struct foo:
+       struct foo
                size:[3]number
                name:string
                active:Boolean
                size:[3]number
                name:string
                active:Boolean
@@ -560,7 +560,7 @@ Time to test if structure declarations and accesses work correctly.
                        case 2: nm:= "peter"
                        case 0: nm:= "bob"
                        case 1: nm:= "jane"
                        case 2: nm:= "peter"
                        case 0: nm:= "bob"
                        case 1: nm:= "jane"
-                       else: nm:= "janine"
+                       else    nm:= "janine"
 
                        info[i].name = nm
                        info[i].size[0] = i*i
 
                        info[i].name = nm
                        info[i].size[0] = i*i
@@ -710,7 +710,7 @@ various places that `type_err()` are called.
 
 ###### test: type_err3
 
 
 ###### test: type_err3
 
-       struct foo:
+       struct foo
                a: number
                b:string = "hello"
 
                a: number
                b:string = "hello"
 
@@ -722,11 +722,11 @@ various places that `type_err()` are called.
                print 45 + ( "Hello" ++ "there")
                c[5] = 1
 
                print 45 + ( "Hello" ++ "there")
                c[5] = 1
 
-               while:
+               while
                        use 1
                        use True
                        use "Hello"
                        use 1
                        use True
                        use "Hello"
-               do:
+               do
                        print
                case 1: print "one"
                case "Hello": print "Hello"
                        print
                case 1: print "one"
                case "Hello": print "Hello"
@@ -788,10 +788,10 @@ various places that `type_err()` are called.
        oceani_failing_tests += type_err_const type_err_const1
 
 ###### test: type_err_const
        oceani_failing_tests += type_err_const type_err_const1
 
 ###### test: type_err_const
-       const:
+       const
                foo :: number = 45
                bar ::= "string" + 56
                foo :: number = 45
                bar ::= "string" + 56
-       const:
+       const
                bar ::= "baz"
        program:
                foo := 4
                bar ::= "baz"
        program:
                foo := 4
@@ -805,7 +805,7 @@ various places that `type_err()` are called.
        .tmp.code:3:8: info: this is where 'foo' was first declared
 
 ###### test: type_err_const1
        .tmp.code:3:8: info: this is where 'foo' was first declared
 
 ###### test: type_err_const1
-       const:
+       const
                foo : number = 45
                bar := "string"
        program:
                foo : number = 45
                bar := "string"
        program:
index 0e6cebeb30b511853746129d4ebd3dcfa8522852..97c195382cd8955c4e0c16e154125e5d7fa2e93b 100644 (file)
@@ -1004,6 +1004,7 @@ like "if" and the code following it.
 
        $void
        OpenScope -> ${ scope_push(c); }$
 
        $void
        OpenScope -> ${ scope_push(c); }$
+       ClosePara -> ${ var_block_close(c, CloseParallel); }$
 
 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:
 
@@ -1998,7 +1999,7 @@ function will be needed.
        }
 
 ###### top level grammar
        }
 
 ###### top level grammar
-       DeclareStruct -> struct IDENTIFIER FieldBlock ${ {
+       DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ {
                        struct type *t =
                                add_type(c, $2.txt, &structure_prototype);
                        int cnt = 0;
                        struct type *t =
                                add_type(c, $2.txt, &structure_prototype);
                        int cnt = 0;
@@ -2017,40 +2018,28 @@ function will be needed.
                                f = f->prev;
                        }
                } }$
                                f = f->prev;
                        }
                } }$
-               | DeclareStruct NEWLINE
 
 
-       $void
-       Newlines -> NEWLINE
-               | Newlines NEWLINE
-       Open -> {
-               | Newlines {
-       Close -> }
-               | Newlines }
        $*fieldlist
        $*fieldlist
-       FieldBlock -> Open FieldList } ${ $0 = $<2; }$
-               | Open SimpleFieldList } ${ $0 = $<2; }$
-               | : FieldList ${ $0 = $<2; }$
-
-       FieldList -> FieldLines ${ $0 = $<1; }$
-               | Newlines FieldLines ${ $0 = $<2; }$
-       FieldLines -> SimpleFieldListLine ${ $0 = $<1; }$
-               | FieldLines SimpleFieldListLine ${
-                       $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;
                }$
 
                }$
 
-       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 ${ $0 = $<F; }$
                | SimpleFieldList ; Field ${
                | SimpleFieldList ; Field ${
-                       $3->prev = $<1;
-                       $0 = $<3;
+                       $F->prev = $<SFL;
+                       $0 = $<F;
                }$
                | SimpleFieldList ; ${
                }$
                | SimpleFieldList ; ${
-                       $0 = $<1;
+                       $0 = $<SFL;
                }$
                }$
+               | ERROR ${ tok_err(c, "Syntax error in struct field", &$1); }$
 
        Field -> IDENTIFIER : Type = Expression ${ {
                        int ok;
 
        Field -> IDENTIFIER : Type = Expression ${ {
                        int ok;
@@ -2083,7 +2072,7 @@ function will be needed.
        {
                int i;
 
        {
                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;
 
                for (i = 0; i < t->structure.nfields; i++) {
                        struct field *fl = t->structure.fields + i;
@@ -2816,6 +2805,7 @@ precedence is handled better I might be able to discard this.
        $LEFT + - Eop
        $LEFT * / % ++ Top
        $LEFT Uop
        $LEFT + - Eop
        $LEFT * / % ++ Top
        $LEFT Uop
+       $TERM ( )
 
 ###### expression grammar
                | Expression Eop Expression ${ {
 
 ###### expression grammar
                | Expression Eop Expression ${ {
@@ -3052,16 +3042,35 @@ is in-place.
 ###### Binode types
        Block,
 
 ###### Binode types
        Block,
 
+###### expr precedence
+       $TERM pass
+
 ###### Grammar
 
        $*binode
 ###### 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); }$
-               | Newlines ComplexStatements ${ $0 = reorder_bilist($<2); }$
+       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) {
 
        ComplexStatements -> ComplexStatements ComplexStatement ${
                        if ($2 == NULL) {
@@ -3085,10 +3094,12 @@ is in-place.
                }$
 
        $*exec
                }$
 
        $*exec
-       ComplexStatement -> SimpleStatementLine ${
-                       $0 = reorder_bilist($<1);
+       ComplexStatement -> SimpleStatements Newlines ${
+                       $0 = reorder_bilist($<SS);
+                       }$
+               |  SimpleStatements ; Newlines ${
+                       $0 = reorder_bilist($<SS);
                        }$
                        }$
-               | ComplexStatement NEWLINE ${ $0 = $<1; }$
                ## ComplexStatement Grammar
 
        $*binode
                ## ComplexStatement Grammar
 
        $*binode
@@ -3105,10 +3116,6 @@ is in-place.
                        $0->right = $<1;
                        }$
 
                        $0->right = $<1;
                        }$
 
-       SimpleStatementLine -> SimpleStatements NEWLINE ${ $0 = $<1; }$
-               | SimpleStatements ; NEWLINE ${ $0 = $<1; }$
-               | SimpleStatementLine NEWLINE ${ $0 = $<1; }$
-
        SimpleStatement -> pass ${ $0 = NULL; }$
                | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
                ## SimpleStatement Grammar
        SimpleStatement -> pass ${ $0 = NULL; }$
                | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$
                ## SimpleStatement Grammar
@@ -3185,6 +3192,9 @@ same solution.
 ###### Binode types
        Print,
 
 ###### Binode types
        Print,
 
+##### expr precedence
+       $TERM print ,
+
 ###### SimpleStatement Grammar
 
        | print ExpressionList ${
 ###### SimpleStatement Grammar
 
        | print ExpressionList ${
@@ -3417,6 +3427,9 @@ function.
 ###### Binode types
        Use,
 
 ###### Binode types
        Use,
 
+###### expr precedence
+       $TERM use       
+
 ###### SimpleStatement Grammar
        | use Expression ${
                $0 = new_pos(binode, $1);
 ###### SimpleStatement Grammar
        | use Expression ${
                $0 = new_pos(binode, $1);
@@ -3565,42 +3578,59 @@ defined.
 ###### ComplexStatement Grammar
        | CondStatement ${ $0 = $<1; }$
 
 ###### ComplexStatement Grammar
        | CondStatement ${ $0 = $<1; }$
 
+###### expr precedence
+       $TERM for then while do
+       $TERM else
+       $TERM switch case
+
 ###### Grammar
 
        $*cond_statement
 ###### 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.
        // 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;
+       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);
                        }$
                        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;
+               | 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 ${
                        var_block_close(c, CloseSequential);
                        }$
                | WhilePart CondSuffix ${
-                       $0 = $<2;
-                       $0->condpart = $1.condpart; $1.condpart = NULL;
-                       $0->dopart = $1.dopart; $1.dopart = NULL;
+                       $0 = $<CS;
+                       $0->condpart = $WP.condpart; $WP.condpart = NULL;
+                       $0->dopart = $WP.dopart; $WP.dopart = NULL;
+                       }$
+               | SwitchPart OptNL CasePart CondSuffix ${
+                       $0 = $<CS;
+                       $0->condpart = $<SP;
+                       $CP->next = $0->casepart;
+                       $0->casepart = $<CP;
                        }$
                        }$
-               | SwitchPart CasePart CondSuffix ${
-                       $0 = $<3;
-                       $0->condpart = $<1;
-                       $2->next = $0->casepart;
-                       $0->casepart = $<2;
+               | SwitchPart : IN OptNL CasePart CondSuffix OUT Newlines ${
+                       $0 = $<CS;
+                       $0->condpart = $<SP;
+                       $CP->next = $0->casepart;
+                       $0->casepart = $<CP;
                        }$
                | IfPart IfSuffix ${
                        }$
                | IfPart IfSuffix ${
-                       $0 = $<2;
-                       $0->condpart = $1.condpart; $1.condpart = NULL;
-                       $0->thenpart = $1.thenpart; $1.thenpart = NULL;
+                       $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(c, CloseSequential);
                        }$
                        // This is where we close an "if" statement
                        var_block_close(c, CloseSequential);
                        }$
@@ -3611,126 +3641,83 @@ defined.
                        // "for" or "while" statement
                        var_block_close(c, CloseSequential);
                }$
                        // "for" or "while" statement
                        var_block_close(c, CloseSequential);
                }$
+               | Newlines CasePart CondSuffix ${
+                       $0 = $<CS;
+                       $CP->next = $0->casepart;
+                       $0->casepart = $<CP;
+               }$
                | CasePart CondSuffix ${
                | CasePart CondSuffix ${
-                       $0 = $<2;
-                       $1->next = $0->casepart;
-                       $0->casepart = $<1;
+                       $0 = $<CS;
+                       $CP->next = $0->casepart;
+                       $0->casepart = $<CP;
                }$
 
                }$
 
-       $*casepart
-       CasePart -> case Expression OpenScope Block ${
-                       $0 = calloc(1,sizeof(struct casepart));
-                       $0->value = $<2;
-                       $0->action = $<4;
-                       var_block_close(c, CloseParallel);
-               }$
-               | CasePart NEWLINE ${ $0 = $<1; }$
+       IfSuffix -> Newlines ${ $0 = new(cond_statement); }$
+               | Newlines ElsePart ${ $0 = $<EP; }$
+               | ElsePart ${$0 = $<EP; }$
 
 
-       $*cond_statement
-       IfSuffix ->  ${ $0 = new(cond_statement); }$
-               | IfSuffix NEWLINE ${ $0 = $<1; }$
-               | else OpenScope Block ${
+       ElsePart -> else OpenBlock Newlines ${
                        $0 = new(cond_statement);
                        $0 = new(cond_statement);
-                       $0->elsepart = $<3;
-                       var_block_close(c, CloseElse);
-               }$
-               | else OpenScope SimpleStatements NEWLINE ${
-                       $0 = new(cond_statement);
-                       $0->elsepart = reorder_bilist($<3);
+                       $0->elsepart = $<OB;
                        var_block_close(c, CloseElse);
                }$
                | else OpenScope CondStatement ${
                        $0 = new(cond_statement);
                        var_block_close(c, CloseElse);
                }$
                | else OpenScope CondStatement ${
                        $0 = new(cond_statement);
-                       $0->elsepart = $<3;
+                       $0->elsepart = $<CS;
                        var_block_close(c, CloseElse);
                }$
 
                        var_block_close(c, CloseElse);
                }$
 
+       $*casepart
+       CasePart -> case Expression OpenScope ColonBlock ${
+                       $0 = calloc(1,sizeof(struct casepart));
+                       $0->value = $<Ex;
+                       $0->action = $<Bl;
+                       var_block_close(c, CloseParallel);
+               }$
+
        $*exec
        // These scopes are closed in CondSuffix
        $*exec
        // These scopes are closed in CondSuffix
-       ForPart -> for OpenScope SimpleStatements ; ${
-                       $0 = reorder_bilist($<3);
+       ForPart -> for OpenBlock ${
+                       $0 = $<Bl;
                }$
                }$
-               | for OpenScope SimpleStatements NEWLINE ${
-                       $0 = reorder_bilist($<3);
-               }$
-               |  for OpenScope Block ${
-                       $0 = $<3;
-               }$
-               |  ForPart NEWLINE ${ $0 = $<1; }$
 
 
-       ThenPart -> then OpenScope SimpleStatements ; ${
-                       $0 = reorder_bilist($<3);
-                       var_block_close(c, CloseSequential);
-               }$
-               | then OpenScope SimpleStatements NEWLINE ${
-                       $0 = reorder_bilist($<3);
+       ThenPart -> then OpenBlock ${
+                       $0 = $<OB;
                        var_block_close(c, CloseSequential);
                }$
                        var_block_close(c, CloseSequential);
                }$
-               |  then OpenScope Block ${
-                       $0 = $<3;
-                       var_block_close(c, CloseSequential);
-               }$
-               |  ThenPart NEWLINE ${ $0 = $<1; }$
-
-       // This scope is closed in CondSuffix
-       WhileHead -> while OpenScope Block ${ $0 = $<3; }$
-               | WhileHead NEWLINE ${ $0 = $<1; }$
 
        $cond_statement
        // This scope is closed in CondSuffix
 
        $cond_statement
        // This scope is closed in CondSuffix
-       WhilePart -> while OpenScope Expression Block ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<3;
-                       $0.dopart = $<4;
+       WhilePart -> while UseBlock OptNL do Block ${
+                       $0.condpart = $<UB;
+                       $0.dopart = $<Bl;
                }$
                }$
-               | WhileHead do Block ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<1;
-                       $0.dopart = $<3;
+               | while OpenScope Expression ColonBlock ${
+                       $0.condpart = $<Exp;
+                       $0.dopart = $<Bl;
                }$
                }$
-               | WhilePart NEWLINE ${ $0 = $<1; }$
 
 
-       IfPart -> if OpenScope Expression OpenScope Block ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<3;
-                       $0.thenpart = $<5;
-                       var_block_close(c, CloseParallel);
-               }$
-               | if OpenScope Expression OpenScope then Block ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<3;
-                       $0.thenpart = $<6;
-                       var_block_close(c, CloseParallel);
-               }$
-               | if OpenScope Expression OpenScope then SimpleStatements ; ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<3;
-                       $0.thenpart = reorder_bilist($<6);
-                       var_block_close(c, CloseParallel);
+       IfPart -> if UseBlock OptNL then OpenBlock ClosePara ${
+                       $0.condpart = $<UB;
+                       $0.thenpart = $<Bl;
                }$
                }$
-               | if OpenScope Expression OpenScope then SimpleStatements NEWLINE ${
-                       $0.type = Xcond_statement;
-                       $0.condpart = $<3;
-                       $0.thenpart = reorder_bilist($<6);
-                       var_block_close(c, CloseParallel);
+               | 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(c, CloseParallel);
+               | if OpenScope Expression OpenScope OptNL then Block ClosePara ${
+                       $0.condpart = $<Ex;
+                       $0.thenpart = $<Bl;
                }$
                }$
-               | IfPart NEWLINE ${ $0 = $<1; }$
 
        $*exec
        // This scope is closed in CondSuffix
        SwitchPart -> switch OpenScope Expression ${
 
        $*exec
        // This scope is closed in CondSuffix
        SwitchPart -> switch OpenScope Expression ${
-                       $0 = $<3;
+                       $0 = $<Ex;
                }$
                }$
-               | switch OpenScope Block ${
-                       $0 = $<3;
+               | switch UseBlock ${
+                       $0 = $<Bl;
                }$
                }$
-               | SwitchPart NEWLINE ${ $0 = $<1; }$
 
 ###### print exec cases
 
 
 ###### print exec cases
 
@@ -3740,13 +3727,13 @@ defined.
                struct casepart *cp;
                if (cs->forpart) {
                        do_indent(indent, "for");
                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
                        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");
                                print_exec(cs->thenpart, indent+1, bracket);
                        }
                        if (bracket) do_indent(indent, "}\n");
@@ -3758,12 +3745,12 @@ defined.
                                if (bracket)
                                        do_indent(indent, "while {\n");
                                else
                                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
                                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");
                                print_exec(cs->dopart, indent+1, bracket);
                                if (bracket)
                                        do_indent(indent, "}\n");
@@ -3828,7 +3815,7 @@ defined.
                        if (bracket)
                                printf(" {\n");
                        else
                        if (bracket)
                                printf(" {\n");
                        else
-                               printf(":\n");
+                               printf("\n");
                        print_exec(cs->elsepart, indent+1, bracket);
                        if (bracket)
                                do_indent(indent, "}\n");
                        print_exec(cs->elsepart, indent+1, bracket);
                        if (bracket)
                                do_indent(indent, "}\n");
@@ -3967,20 +3954,23 @@ various declarations in the parse context.
 ###### Parser: grammar
 
        $void
 ###### Parser: grammar
 
        $void
-       Ocean -> DeclarationList
-               | Newlines DeclarationList
+       Ocean -> OptNL DeclarationList
+
+       OptNL ->
+               | OptNL NEWLINE
+       Newlines -> NEWLINE
+               | Newlines NEWLINE
 
        DeclarationList -> Declaration
                | DeclarationList Declaration
 
 
        DeclarationList -> Declaration
                | DeclarationList Declaration
 
-       Declaration -> Declaration NEWLINE
-               | DeclareConstant
-               | DeclareProgram
-               | DeclareStruct
-               | ERROR NEWLINE ${
+       Declaration -> ERROR Newlines ${
                        tok_err(c,
                                "error: unhandled parse error", &$1);
                }$
                        tok_err(c,
                                "error: unhandled parse error", &$1);
                }$
+               | DeclareConstant
+               | DeclareProgram
+               | DeclareStruct
 
        ## top level grammar
 
 
        ## top level grammar
 
@@ -4009,21 +3999,18 @@ searching through for the Nth constant for decreasing N.
 
 ###### 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 -> ConstLines
-               | Newlines ConstLines
-       ConstLines -> ConstLines SimpleConstLine
+       ConstList -> ConstList SimpleConstLine
                | SimpleConstLine
        SimpleConstList -> SimpleConstList ; Const
                | Const
                | SimpleConstList ;
                | SimpleConstLine
        SimpleConstList -> SimpleConstList ; Const
                | Const
                | SimpleConstList ;
-       SimpleConstLine -> SimpleConstList NEWLINE
-               | SimpleConstLine NEWLINE
-               | ERROR NEWLINE ${ tok_err(c, "Syntax error in constant", &$1); }$
+       SimpleConstLine -> SimpleConstList Newlines
+               | ERROR Newlines ${ tok_err(c, "Syntax error in constant", &$1); }$
 
        $*type
        CType -> Type   ${ $0 = $<1; }$
 
        $*type
        CType -> Type   ${ $0 = $<1; }$
@@ -4073,7 +4060,7 @@ searching through for the Nth constant for decreasing N.
 
                        if (target == -1) {
                                if (i)
 
                        if (target == -1) {
                                if (i)
-                                       printf("const:\n");
+                                       printf("const\n");
                                target = i;
                        } else {
                                printf("    %.*s :: ", v->name->name.len, v->name->name.txt);
                                target = i;
                        } else {
                                printf("    %.*s :: ", v->name->name.len, v->name->name.txt);
@@ -4118,11 +4105,11 @@ analysis is a bit more interesting at this level.
        } }$
 
        $*binode
        } }$
 
        $*binode
-       Program -> program OpenScope Varlist Block ${
+       Program -> program OpenScope Varlist ColonBlock Newlines ${
                $0 = new(binode);
                $0->op = Program;
                $0 = new(binode);
                $0->op = Program;
-               $0->left = reorder_bilist($<3);
-               $0->right = $<4;
+               $0->left = reorder_bilist($<Vl);
+               $0->right = $<Bl;
                var_block_close(c, CloseSequential);
                if (c->scope_stack && !c->parse_error) abort();
                }$
                var_block_close(c, CloseSequential);
                if (c->scope_stack && !c->parse_error) abort();
                }$
@@ -4246,14 +4233,14 @@ things which will likely grow as the languages grows.
 
 ###### demo: hello
 
 
 ###### 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"
 
                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
                size:[four]number
                name:string
                alive:Boolean
@@ -4268,7 +4255,7 @@ things which will likely grow as the languages grows.
                 */
                if A > B:
                        bigger := "yes"
                 */
                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
                        bigger := "no"
                print "Is", A, "bigger than", B,"? ", bigger
                /* If a variable is not used after the 'if', no
@@ -4277,7 +4264,7 @@ things which will likely grow as the languages grows.
                if A > B * 2:
                        double:string = "yes"
                        print A, "is more than twice", B, "?", double
                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
 
                        double := B*2
                        print "double", B, "is", double
 
@@ -4288,15 +4275,15 @@ things which will likely grow as the languages grows.
                        while a != b:
                                if a < b:
                                        b = b - a
                        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"
                                        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"
 
                        print b, "is not positive, cannot calculate GCD"
 
-               for:
+               for
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
                        togo := 10
                        f1 := 1; f2 := 1
                        print "Fibonacci:", f1,f2,
@@ -4309,21 +4296,21 @@ things which will likely grow as the languages grows.
                print ""
 
                /* Binary search... */
                print ""
 
                /* Binary search... */
-               for:
+               for
                        lo:= 0; hi := 100
                        target := 77
                        lo:= 0; hi := 100
                        target := 77
-               while:
+               while
                        mid := (lo + hi) / 2
                        if mid == target:
                                use Found
                        if mid < target:
                                lo = mid
                        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
                                hi = mid
                        if hi - lo < 1:
                                use GiveUp
                        use True
-               do: pass
+               do pass
                case Found:
                        print "Yay, I found", target
                case GiveUp:
                case Found:
                        print "Yay, I found", target
                case GiveUp: