X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=97c195382cd8955c4e0c16e154125e5d7fa2e93b;hp=1f4805e85eb9a901571474f45051b618ca60fee6;hb=1dd9f61bbc7e8890b5407ba084793817e55fe502;hpb=20effd70ff4d91a7501dc062e60caaa9e362bed5 diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 1f4805e..97c1953 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -123,6 +123,9 @@ structures can be used. #define config2context(_conf) container_of(_conf, struct parse_context, \ config) +###### Parser: reduce + struct parse_context *c = config2context(config); + ###### Parser: code #include @@ -148,8 +151,8 @@ structures can be used. ## core functions #include - static char Usage[] = "Usage: oceani --trace --print --noexec --brackets" - "--section=SectionName prog.ocn\n"; + static char Usage[] = + "Usage: oceani --trace --print --noexec --brackets --section=SectionName prog.ocn\n"; static const struct option long_options[] = { {"trace", 0, NULL, 't'}, {"print", 0, NULL, 'p'}, @@ -168,9 +171,7 @@ structures can be used. char *section = NULL; struct parse_context context = { .config = { - .ignored = (1 << TK_line_comment) - | (1 << TK_block_comment) - | (1 << TK_mark), + .ignored = (1 << TK_mark), .number_chars = ".,_+- ", .word_start = "_", .word_cont = "_", @@ -630,8 +631,8 @@ there are errors. ###### includes #include - #include "string.h" - #include "number.h" + #include "parse_string.h" + #include "parse_number.h" ###### libs myLDLIBS := libnumber.o libstring.o -lgmp @@ -1002,7 +1003,8 @@ like "if" and the code following it. ###### Grammar $void - OpenScope -> ${ scope_push(config2context(config)); }$ + OpenScope -> ${ scope_push(c); }$ + ClosePara -> ${ var_block_close(c, CloseParallel); }$ Each variable records a scope depth and is in one of four states: @@ -1093,7 +1095,7 @@ list of in_scope names. 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); @@ -1675,7 +1677,6 @@ make a copy of an array with controllable depth. $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) @@ -1698,13 +1699,12 @@ make a copy of an array with controllable depth. }$ | [ IDENTIFIER ] Type ${ { - struct parse_context *c = config2context(config); struct variable *v = var_ref(c, $2.txt); if (!v) - tok_err(config2context(config), "error: name undeclared", &$2); + tok_err(c, "error: name undeclared", &$2); else if (!v->constant) - tok_err(config2context(config), "error: array size must be a constant", &$2); + tok_err(c, "error: array size must be a constant", &$2); $0 = calloc(1, sizeof(struct type)); *($0) = array_prototype; @@ -1743,9 +1743,9 @@ make a copy of an array with controllable depth. ###### print binode cases case Index: - print_exec(b->left, -1, 0); + print_exec(b->left, -1, bracket); printf("["); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); printf("]"); break; @@ -1929,7 +1929,7 @@ function will be needed. 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; } @@ -1999,50 +1999,47 @@ function will be needed. } ###### top level grammar - DeclareStruct -> struct IDENTIFIER FieldBlock ${ { - struct type *t = - add_type(config2context(config), $2.txt, &structure_prototype); - int cnt = 0; - struct fieldlist *f; - - for (f = $3; f; f=f->prev) - cnt += 1; - - t->structure.nfields = cnt; - t->structure.fields = calloc(cnt, sizeof(struct field)); - f = $3; - while (cnt > 0) { - cnt -= 1; - t->structure.fields[cnt] = f->f; - f->f.init = val_prepare(Tnone); - f = f->prev; - } - } }$ + DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ { + struct type *t = + add_type(c, $2.txt, &structure_prototype); + int cnt = 0; + struct fieldlist *f; + + for (f = $3; f; f=f->prev) + cnt += 1; + + t->structure.nfields = cnt; + t->structure.fields = calloc(cnt, sizeof(struct field)); + f = $3; + while (cnt > 0) { + cnt -= 1; + t->structure.fields[cnt] = f->f; + f->f.init = val_prepare(Tnone); + f = f->prev; + } + } }$ - $void - Open -> { - | NEWLINE Open - Close -> } - | NEWLINE Close $*fieldlist - FieldBlock -> Open FieldList Close ${ $0 = $<2; }$ - | Open SimpleFieldList } ${ $0 = $<2; }$ - | : FieldList ${ $0 = $<2; }$ - - FieldList -> SimpleFieldList NEWLINE ${ $0 = $<1; }$ - | FieldList SimpleFieldList NEWLINE ${ - $2->prev = $<1; - $0 = $<2; + FieldBlock -> { IN OptNL FieldLines OUT OptNL } ${ $0 = $ SimpleFieldList Newlines ${ $0 = $prev = $ Field ${ $0 = $<1; }$ + SimpleFieldList -> Field ${ $0 = $prev = $<1; - $0 = $<3; + $F->prev = $ IDENTIFIER : Type = Expression ${ { int ok; @@ -2053,10 +2050,10 @@ function will be needed. $0->f.init = val_prepare($0->f.type); do { ok = 1; - propagate_types($<5, config2context(config), &ok, $3, 0); + propagate_types($<5, c, &ok, $3, 0); } while (ok == 2); if (!ok) - config2context(config)->parse_error = 1; + c->parse_error = 1; else $0->f.init = interp_exec($5); } }$ @@ -2075,7 +2072,7 @@ function will be needed. { 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; @@ -2159,7 +2156,7 @@ an executable. 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); } }$ @@ -2170,7 +2167,7 @@ an executable. 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); } }$ @@ -2181,7 +2178,7 @@ an executable. 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); } }$ @@ -2268,38 +2265,38 @@ link to find the primary instance. $*var VariableDecl -> IDENTIFIER : ${ { - struct variable *v = var_decl(config2context(config), $1.txt); + struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; if (v) v->where_decl = $0; else { - v = var_ref(config2context(config), $1.txt); + v = var_ref(c, $1.txt); $0->var = v; - type_err(config2context(config), "error: variable '%v' redeclared", + type_err(c, "error: variable '%v' redeclared", $0, NULL, 0, NULL); - type_err(config2context(config), "info: this is where '%v' was first declared", + type_err(c, "info: this is where '%v' was first declared", v->where_decl, NULL, 0, NULL); } } }$ | IDENTIFIER :: ${ { - struct variable *v = var_decl(config2context(config), $1.txt); + struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; if (v) { v->where_decl = $0; v->constant = 1; } else { - v = var_ref(config2context(config), $1.txt); + v = var_ref(c, $1.txt); $0->var = v; - type_err(config2context(config), "error: variable '%v' redeclared", + type_err(c, "error: variable '%v' redeclared", $0, NULL, 0, NULL); - type_err(config2context(config), "info: this is where '%v' was first declared", + type_err(c, "info: this is where '%v' was first declared", v->where_decl, NULL, 0, NULL); } } }$ | IDENTIFIER : Type ${ { - struct variable *v = var_decl(config2context(config), $1.txt); + struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; if (v) { @@ -2307,16 +2304,16 @@ link to find the primary instance. v->where_set = $0; v->val = val_prepare($<3); } else { - v = var_ref(config2context(config), $1.txt); + v = var_ref(c, $1.txt); $0->var = v; - type_err(config2context(config), "error: variable '%v' redeclared", + type_err(c, "error: variable '%v' redeclared", $0, NULL, 0, NULL); - type_err(config2context(config), "info: this is where '%v' was first declared", + type_err(c, "info: this is where '%v' was first declared", v->where_decl, NULL, 0, NULL); } } }$ | IDENTIFIER :: Type ${ { - struct variable *v = var_decl(config2context(config), $1.txt); + struct variable *v = var_decl(c, $1.txt); $0 = new_pos(var, $1); $0->var = v; if (v) { @@ -2325,25 +2322,25 @@ link to find the primary instance. v->val = val_prepare($<3); v->constant = 1; } else { - v = var_ref(config2context(config), $1.txt); + v = var_ref(c, $1.txt); $0->var = v; - type_err(config2context(config), "error: variable '%v' redeclared", + type_err(c, "error: variable '%v' redeclared", $0, NULL, 0, NULL); - type_err(config2context(config), "info: this is where '%v' was first declared", + type_err(c, "info: this is where '%v' was first declared", v->where_decl, NULL, 0, NULL); } } }$ $*exec Variable -> IDENTIFIER ${ { - struct variable *v = var_ref(config2context(config), $1.txt); + struct variable *v = var_ref(c, $1.txt); $0 = new_pos(var, $1); if (v == NULL) { /* This might be a label - allocate a var just in case */ - v = var_decl(config2context(config), $1.txt); + v = var_decl(c, $1.txt); if (v) { - v->val = val_prepare(Tlabel); - v->val.label = &v->val; + v->val = val_prepare(Tnone); + v->where_decl = $0; v->where_set = $0; } } @@ -2353,9 +2350,9 @@ link to find the primary instance. $*type Type -> IDENTIFIER ${ - $0 = find_type(config2context(config), $1.txt); + $0 = find_type(c, $1.txt); if (!$0) { - tok_err(config2context(config), + tok_err(c, "error: undefined type", &$1); $0 = Tnone; @@ -2406,6 +2403,9 @@ link to find the primary instance. v->where_decl, NULL, 0, NULL); return v->val.type; } + if (v->val.type == Tnone && v->where_decl == prog) + type_err(c, "error: variable used but not declared: %v", + prog, NULL, 0, NULL); if (v->val.type == NULL) { if (type && *ok != 0) { v->val = val_prepare(type); @@ -2467,8 +2467,11 @@ room for ambiguity, so a full conditional expression is allowed in there. ###### Grammar + $LEFT if $$ifelse + ## expr precedence + $*exec - Expression -> BoolExpr if Expression else Expression ${ { + Expression -> Expression if Expression else Expression $$ifelse ${ { struct binode *b1 = new(binode); struct binode *b2 = new(binode); b1->op = CondExpr; @@ -2479,17 +2482,19 @@ room for ambiguity, so a full conditional expression is allowed in there. b2->right = $<5; $0 = b1; } }$ - | BoolExpr ${ $0 = $<1; }$ + ## expression grammar ###### print binode cases case CondExpr: b2 = cast(binode, b->right); - print_exec(b2->left, -1, 0); + if (bracket) printf("("); + print_exec(b2->left, -1, bracket); printf(" if "); - print_exec(b->left, -1, 0); + print_exec(b->left, -1, bracket); printf(" else "); - print_exec(b2->right, -1, 0); + print_exec(b2->right, -1, bracket); + if (bracket) printf(")"); break; ###### propagate binode cases @@ -2535,73 +2540,83 @@ if the result would make a difference. OrElse, Not, -###### Grammar +###### expr precedence + $LEFT or + $LEFT and + $LEFT not - $*exec - BoolExpr -> BoolExpr or BTerm ${ { +###### expression grammar + | Expression or Expression ${ { struct binode *b = new(binode); b->op = Or; b->left = $<1; b->right = $<3; $0 = b; } }$ - | BoolExpr or else BTerm ${ { + | Expression or else Expression ${ { struct binode *b = new(binode); b->op = OrElse; b->left = $<1; b->right = $<4; $0 = b; } }$ - | BTerm ${ $0 = $<1; }$ - BTerm -> BTerm and BFact ${ { + | Expression and Expression ${ { struct binode *b = new(binode); b->op = And; b->left = $<1; b->right = $<3; $0 = b; } }$ - | BTerm and then BFact ${ { + | Expression and then Expression ${ { struct binode *b = new(binode); b->op = AndThen; b->left = $<1; b->right = $<4; $0 = b; } }$ - | BFact ${ $0 = $<1; }$ - BFact -> not BFact ${ { + | not Expression ${ { struct binode *b = new(binode); b->op = Not; b->right = $<2; $0 = b; } }$ - ## other BFact ###### print binode cases case And: - print_exec(b->left, -1, 0); + if (bracket) printf("("); + print_exec(b->left, -1, bracket); printf(" and "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); + if (bracket) printf(")"); break; case AndThen: - print_exec(b->left, -1, 0); + if (bracket) printf("("); + print_exec(b->left, -1, bracket); printf(" and then "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); + if (bracket) printf(")"); break; case Or: - print_exec(b->left, -1, 0); + if (bracket) printf("("); + print_exec(b->left, -1, bracket); printf(" or "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); + if (bracket) printf(")"); break; case OrElse: - print_exec(b->left, -1, 0); + if (bracket) printf("("); + print_exec(b->left, -1, bracket); printf(" or else "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); + if (bracket) printf(")"); break; case Not: + if (bracket) printf("("); printf("not "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); + if (bracket) printf(")"); break; ###### propagate binode cases @@ -2674,15 +2689,17 @@ expression operator. Eql, NEql, -###### other BFact - | Expr CMPop Expr ${ { +###### expr precedence + $LEFT < > <= >= == != CMPop + +###### expression grammar + | Expression CMPop Expression ${ { struct binode *b = new(binode); b->op = $2.op; b->left = $<1; b->right = $<3; $0 = b; } }$ - | Expr ${ $0 = $<1; }$ ###### Grammar @@ -2702,7 +2719,8 @@ expression operator. 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; @@ -2712,7 +2730,8 @@ expression operator. 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 @@ -2782,34 +2801,36 @@ precedence is handled better I might be able to discard this. Absolute, Negate, Bracket, -###### Grammar +###### expr precedence + $LEFT + - Eop + $LEFT * / % ++ Top + $LEFT Uop + $TERM ( ) - $*exec - Expr -> Expr Eop Term ${ { +###### expression grammar + | Expression Eop Expression ${ { struct binode *b = new(binode); b->op = $2.op; b->left = $<1; b->right = $<3; $0 = b; } }$ - | Term ${ $0 = $<1; }$ - Term -> Term Top Factor ${ { + | Expression Top Expression ${ { struct binode *b = new(binode); b->op = $2.op; b->left = $<1; b->right = $<3; $0 = b; } }$ - | Factor ${ $0 = $<1; }$ - Factor -> ( Expression ) ${ { + | ( Expression ) ${ { struct binode *b = new_pos(binode, $1); b->op = Bracket; b->right = $<2; $0 = b; } }$ - | Uop Factor ${ { + | Uop Expression ${ { struct binode *b = new(binode); b->op = $1.op; b->right = $<2; @@ -2837,7 +2858,8 @@ precedence is handled better I might be able to discard this. 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; @@ -2847,19 +2869,24 @@ precedence is handled better I might be able to discard this. case Concat: fputs(" ++ ", stdout); break; default: abort(); // NOTEST } // NOTEST - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); + if (bracket) printf(")"); break; case Absolute: + if (bracket) printf("("); printf("+"); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); + if (bracket) printf(")"); break; case Negate: + if (bracket) printf("("); printf("-"); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); + if (bracket) printf(")"); break; case Bracket: printf("("); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); printf(")"); break; @@ -3015,19 +3042,35 @@ is in-place. ###### Binode types Block, -###### Grammar +###### expr precedence + $TERM pass - $void - Newlines -> NEWLINE - | Newlines NEWLINE +###### Grammar $*binode - Block -> Open Statementlist Close ${ $0 = $<2; }$ - | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$ - | : SimpleStatements ${ $0 = reorder_bilist($<2); }$ - | : Statementlist ${ $0 = $<2; }$ - - Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$ + Block -> { IN OptNL Statementlist OUT OptNL } ${ $0 = $ OpenScope { IN OptNL Statementlist OUT OptNL } ${ $0 = $ { OpenScope IN OptNL Statementlist OUT OptNL } ${ $0 = $ { IN OptNL Statementlist OUT OptNL } ${ $0 = $ ComplexStatements ${ $0 = reorder_bilist($ ComplexStatements ComplexStatement ${ if ($2 == NULL) { @@ -3051,10 +3094,12 @@ is in-place. }$ $*exec - ComplexStatement -> SimpleStatements NEWLINE ${ - $0 = reorder_bilist($<1); + ComplexStatement -> SimpleStatements Newlines ${ + $0 = reorder_bilist($left = NULL; $0->right = $<1; }$ - | SimpleStatements ; ${ $0 = $<1; }$ SimpleStatement -> pass ${ $0 = NULL; }$ + | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$ ## SimpleStatement Grammar ###### print binode cases @@ -3082,10 +3127,10 @@ is in-place. if (b->left == NULL) printf("pass"); else - print_exec(b->left, indent, 0); + print_exec(b->left, indent, bracket); if (b->right) { printf("; "); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); } } else { // block, one per line @@ -3147,6 +3192,9 @@ same solution. ###### Binode types Print, +##### expr precedence + $TERM print , + ###### SimpleStatement Grammar | print ExpressionList ${ @@ -3188,7 +3236,7 @@ same solution. while (b) { if (b->left) { printf(" "); - print_exec(b->left, -1, 0); + print_exec(b->left, -1, bracket); if (b->right) printf(","); } @@ -3259,7 +3307,7 @@ it is declared, and error will be raised as the name is created as | 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 { @@ -3274,9 +3322,9 @@ it is declared, and error will be raised as the name is created as case Assign: do_indent(indent, ""); - print_exec(b->left, indent, 0); + print_exec(b->left, indent, bracket); printf(" = "); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); if (indent >= 0) printf("\n"); break; @@ -3285,7 +3333,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, ""); - 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("::"); @@ -3303,7 +3351,7 @@ it is declared, and error will be raised as the name is created as } if (b->right) { printf("= "); - print_exec(b->right, indent, 0); + print_exec(b->right, indent, bracket); } if (indent >= 0) printf("\n"); @@ -3379,18 +3427,29 @@ function. ###### Binode types Use, +###### expr precedence + $TERM use + ###### SimpleStatement Grammar | use Expression ${ $0 = new_pos(binode, $1); $0->op = Use; $0->right = $<2; + if ($0->right->type == Xvar) { + struct var *v = cast(var, $0->right); + if (v->var->val.type == Tnone) { + /* Convert this to a label */ + v->var->val = val_prepare(Tlabel); + v->var->val.label = &v->var->val; + } + } }$ ###### print binode cases case Use: do_indent(indent, "use "); - print_exec(b->right, -1, 0); + print_exec(b->right, -1, bracket); if (indent >= 0) printf("\n"); break; @@ -3519,157 +3578,145 @@ defined. ###### ComplexStatement Grammar | CondStatement ${ $0 = $<1; }$ +###### expr precedence + $TERM for then while do + $TERM else + $TERM switch case + ###### Grammar $*cond_statement - // both ForThen and Whilepart open scopes, and CondSuffix only + // A CondStatement must end with EOL, as does CondSuffix and + // IfSuffix. + // ForPart, ThenPart, SwitchPart, CasePart are non-empty and + // may or may not end with EOL + // WhilePart and IfPart include an appropriate Suffix + + + // Both ForPart and Whilepart open scopes, and CondSuffix only // closes one - so in the first branch here we have another to close. - CondStatement -> forPart ThenPart WhilePart CondSuffix ${ - $0 = $<4; - $0->forpart = $<1; - $0->thenpart = $<2; - $0->condpart = $3.condpart; $3.condpart = NULL; - $0->dopart = $3.dopart; $3.dopart = NULL; - var_block_close(config2context(config), CloseSequential); + CondStatement -> ForPart OptNL ThenPart OptNL WhilePart CondSuffix ${ + $0 = $forpart = $thenpart = $condpart = $WP.condpart; $WP.condpart = NULL; + $0->dopart = $WP.dopart; $WP.dopart = NULL; + var_block_close(c, CloseSequential); }$ - | forPart WhilePart CondSuffix ${ - $0 = $<3; - $0->forpart = $<1; - $0->thenpart = NULL; - $0->condpart = $2.condpart; $2.condpart = NULL; - $0->dopart = $2.dopart; $2.dopart = NULL; - var_block_close(config2context(config), CloseSequential); + | ForPart OptNL WhilePart CondSuffix ${ + $0 = $forpart = $condpart = $WP.condpart; $WP.condpart = NULL; + $0->dopart = $WP.dopart; $WP.dopart = NULL; + var_block_close(c, CloseSequential); }$ - | whilePart CondSuffix ${ - $0 = $<2; - $0->condpart = $1.condpart; $1.condpart = NULL; - $0->dopart = $1.dopart; $1.dopart = NULL; + | WhilePart CondSuffix ${ + $0 = $condpart = $WP.condpart; $WP.condpart = NULL; + $0->dopart = $WP.dopart; $WP.dopart = NULL; }$ - | switchPart CondSuffix ${ - $0 = $<2; - $0->condpart = $<1; + | SwitchPart OptNL CasePart CondSuffix ${ + $0 = $condpart = $next = $0->casepart; + $0->casepart = $condpart = $1.condpart; $1.condpart = NULL; - $0->thenpart = $1.thenpart; $1.thenpart = NULL; + | SwitchPart : IN OptNL CasePart CondSuffix OUT Newlines ${ + $0 = $condpart = $next = $0->casepart; + $0->casepart = $condpart = $IP.condpart; $IP.condpart = NULL; + $0->thenpart = $IP.thenpart; $IP.thenpart = NULL; // This is where we close an "if" statement - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ CondSuffix -> IfSuffix ${ $0 = $<1; // This is where we close scope of the whole // "for" or "while" statement - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); + }$ + | Newlines CasePart CondSuffix ${ + $0 = $next = $0->casepart; + $0->casepart = $next = $0->casepart; - $0->casepart = $<1; + $0 = $next = $0->casepart; + $0->casepart = $ case - | NEWLINE Case - $*casepart - CasePart -> Case Expression OpenScope Block ${ - $0 = calloc(1,sizeof(struct casepart)); - $0->value = $<2; - $0->action = $<4; - var_block_close(config2context(config), CloseParallel); - }$ + IfSuffix -> Newlines ${ $0 = new(cond_statement); }$ + | Newlines ElsePart ${ $0 = $ ${ $0 = new(cond_statement); }$ - | NEWLINE IfSuffix ${ $0 = $<2; }$ - | else OpenScope Block ${ + ElsePart -> else OpenBlock Newlines ${ $0 = new(cond_statement); - $0->elsepart = $<3; - var_block_close(config2context(config), CloseElse); + $0->elsepart = $elsepart = $<3; - var_block_close(config2context(config), CloseElse); + $0->elsepart = $ then - | NEWLINE Then - While -> while - | NEWLINE While - Do -> do - | NEWLINE Do - $*exec - // These scopes are closed in CondSuffix - forPart -> for OpenScope SimpleStatements ${ - $0 = reorder_bilist($<3); - }$ - | for OpenScope Block ${ - $0 = $<3; + $*casepart + CasePart -> case Expression OpenScope ColonBlock ${ + $0 = calloc(1,sizeof(struct casepart)); + $0->value = $action = $ Then OpenScope SimpleStatements ${ - $0 = reorder_bilist($<3); - var_block_close(config2context(config), CloseSequential); - }$ - | Then OpenScope Block ${ - $0 = $<3; - var_block_close(config2context(config), CloseSequential); + $*exec + // These scopes are closed in CondSuffix + ForPart -> for OpenBlock ${ + $0 = $ While OpenScope Block ${ - $0 = $<3; - }$ - whileHead -> while OpenScope Block ${ - $0 = $<3; + ThenPart -> then OpenBlock ${ + $0 = $ while OpenScope Expression Block ${ - $0.type = Xcond_statement; - $0.condpart = $<3; - $0.dopart = $<4; - }$ - | whileHead Do Block ${ - $0.type = Xcond_statement; - $0.condpart = $<1; - $0.dopart = $<3; + WhilePart -> while UseBlock OptNL do Block ${ + $0.condpart = $ While OpenScope Expression Block ${ - $0.type = Xcond_statement; - $0.condpart = $<3; - $0.dopart = $<4; - }$ - | WhileHead Do Block ${ - $0.type = Xcond_statement; - $0.condpart = $<1; - $0.dopart = $<3; + | while OpenScope Expression ColonBlock ${ + $0.condpart = $ if OpenScope Expression OpenScope Block ${ - $0.type = Xcond_statement; - $0.condpart = $<3; - $0.thenpart = $<5; - var_block_close(config2context(config), CloseParallel); + IfPart -> if UseBlock OptNL then OpenBlock ClosePara ${ + $0.condpart = $ switch OpenScope Expression ${ - $0 = $<3; + SwitchPart -> switch OpenScope Expression ${ + $0 = $forpart) { do_indent(indent, "for"); - if (bracket) printf(" {\n"); else printf(":\n"); + if (bracket) printf(" {\n"); else printf("\n"); print_exec(cs->forpart, indent+1, bracket); if (cs->thenpart) { if (bracket) do_indent(indent, "} then {\n"); else - do_indent(indent, "then:\n"); + do_indent(indent, "then\n"); print_exec(cs->thenpart, indent+1, bracket); } if (bracket) do_indent(indent, "}\n"); @@ -3698,12 +3745,12 @@ defined. if (bracket) do_indent(indent, "while {\n"); else - do_indent(indent, "while:\n"); + do_indent(indent, "while\n"); print_exec(cs->condpart, indent+1, bracket); if (bracket) do_indent(indent, "} do {\n"); else - do_indent(indent, "do:\n"); + do_indent(indent, "do\n"); print_exec(cs->dopart, indent+1, bracket); if (bracket) do_indent(indent, "}\n"); @@ -3768,7 +3815,7 @@ defined. if (bracket) printf(" {\n"); else - printf(":\n"); + printf("\n"); print_exec(cs->elsepart, indent+1, bracket); if (bracket) do_indent(indent, "}\n"); @@ -3907,15 +3954,23 @@ various declarations in the parse context. ###### Parser: grammar $void - Ocean -> DeclarationList + Ocean -> OptNL DeclarationList + + OptNL -> + | OptNL NEWLINE + Newlines -> NEWLINE + | Newlines NEWLINE DeclarationList -> Declaration | DeclarationList Declaration - Declaration -> DeclareConstant + Declaration -> ERROR Newlines ${ + tok_err(c, + "error: unhandled parse error", &$1); + }$ + | DeclareConstant | DeclareProgram | DeclareStruct - | NEWLINE ## top level grammar @@ -3944,19 +3999,18 @@ searching through for the Nth constant for decreasing N. ###### top level grammar - DeclareConstant -> const Open ConstList Close - | const Open SimpleConstList } - | const : ConstList - | const SimpleConstList NEWLINE + DeclareConstant -> const { IN OptNL ConstList OUT OptNL } Newlines + | const { SimpleConstList } Newlines + | const IN OptNL ConstList OUT Newlines + | const SimpleConstList Newlines - ConstList -> ComplexConsts - | NEWLINE ConstList - ComplexConsts -> ComplexConst ComplexConsts - | ComplexConst - ComplexConst -> SimpleConstList NEWLINE + ConstList -> ConstList SimpleConstLine + | SimpleConstLine SimpleConstList -> SimpleConstList ; Const | Const | SimpleConstList ; + SimpleConstLine -> SimpleConstList Newlines + | ERROR Newlines ${ tok_err(c, "Syntax error in constant", &$1); }$ $*type CType -> Type ${ $0 = $<1; }$ @@ -3966,7 +4020,7 @@ searching through for the Nth constant for decreasing N. 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; @@ -3974,17 +4028,17 @@ searching through for the Nth constant for decreasing N. var->var = v; v->constant = 1; } else { - v = var_ref(config2context(config), $1.txt); - tok_err(config2context(config), "error: name already declared", &$1); - type_err(config2context(config), "info: this is where '%v' was first declared", + v = var_ref(c, $1.txt); + tok_err(c, "error: name already declared", &$1); + type_err(c, "info: this is where '%v' was first declared", v->where_decl, NULL, 0, NULL); } do { ok = 1; - propagate_types($5, config2context(config), &ok, $3, 0); + propagate_types($5, c, &ok, $3, 0); } while (ok == 2); if (!ok) - config2context(config)->parse_error = 1; + c->parse_error = 1; else if (v) { v->val = interp_exec($5); } @@ -4006,7 +4060,7 @@ searching through for the Nth constant for decreasing N. if (target == -1) { if (i) - printf("const:\n"); + printf("const\n"); target = i; } else { printf(" %.*s :: ", v->name->name.len, v->name->name.txt); @@ -4043,7 +4097,6 @@ analysis is a bit more interesting at this level. ###### 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); @@ -4052,17 +4105,13 @@ analysis is a bit more interesting at this level. } }$ $*binode - Program -> program OpenScope Varlist Block ${ + Program -> program OpenScope Varlist ColonBlock Newlines ${ $0 = new(binode); $0->op = Program; - $0->left = reorder_bilist($<3); - $0->right = $<4; - var_block_close(config2context(config), CloseSequential); - if (config2context(config)->scope_stack) abort(); - }$ - | ERROR ${ - tok_err(config2context(config), - "error: unhandled parse error", &$1); + $0->left = reorder_bilist($right = $scope_stack && !c->parse_error) abort(); }$ Varlist -> Varlist ArgDecl ${ @@ -4075,7 +4124,7 @@ analysis is a bit more interesting at this level. $*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; } }$ @@ -4184,14 +4233,14 @@ things which will likely grow as the languages grows. ###### demo: hello - const: + const pi ::= 3.141_592_6 four ::= 2 + 2 ; five ::= 10/2 const pie ::= "I like Pie"; cake ::= "The cake is" ++ " a lie" - struct fred: + struct fred size:[four]number name:string alive:Boolean @@ -4206,7 +4255,7 @@ things which will likely grow as the languages grows. */ 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 @@ -4215,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 - else: + else double := B*2 print "double", B, "is", double @@ -4226,15 +4275,15 @@ things which will likely grow as the languages grows. while a != b: if a < b: b = b - a - else: + else a = a - b print "GCD of", A, "and", B,"is", a else if a <= 0: print a, "is not positive, cannot calculate GCD" - else: + else print b, "is not positive, cannot calculate GCD" - for: + for togo := 10 f1 := 1; f2 := 1 print "Fibonacci:", f1,f2, @@ -4247,21 +4296,21 @@ things which will likely grow as the languages grows. print "" /* Binary search... */ - for: + for lo:= 0; hi := 100 target := 77 - while: + while mid := (lo + hi) / 2 if mid == target: use Found if mid < target: lo = mid - else: + else hi = mid if hi - lo < 1: use GiveUp use True - do: pass + do pass case Found: print "Yay, I found", target case GiveUp: @@ -4292,6 +4341,8 @@ things which will likely grow as the languages grows. print "", list[i], print + if 1 == 2 then print "yes"; else print "no" + bob:fred bob.name = "Hello" bob.alive = (bob.name == "Hello")