X-Git-Url: https://ocean-lang.org/code/?a=blobdiff_plain;f=csrc%2Foceani.mdc;h=06f71be3268da0b30eb962be214eab1c4d23f558;hb=a571467ffc33a814c65f5a410a4f70509787b9aa;hp=86b3e3cb844ddd5fde3ffe8c9243bb21e962a735;hpb=4bee4f99bc7a0ab4dcd635766acdd15e96f29f5f;p=ocean diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 86b3e3c..06f71be 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 @@ -1002,7 +1005,7 @@ like "if" and the code following it. ###### Grammar $void - OpenScope -> ${ scope_push(config2context(config)); }$ + OpenScope -> ${ scope_push(c); }$ Each variable records a scope depth and is in one of four states: @@ -1093,7 +1096,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); @@ -1455,7 +1458,9 @@ propagation is needed. ###### 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; @@ -1476,6 +1481,16 @@ propagation is needed. 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 @@ -1663,7 +1678,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) @@ -1686,13 +1700,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; @@ -1731,9 +1744,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; @@ -1746,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); - *ok = 0; return NULL; } else { if (!type_compat(type, t->array.member, rules)) { type_err(c, "error: have %1 but need %2", prog, t->array.member, rules, type); - *ok = 0; } return t->array.member; } @@ -1919,7 +1930,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; } @@ -1949,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); - if (f->index < 0) { + if (f->index < 0) type_err(c, "error: cannot find requested field in %1", f->left, st, 0, NULL); - *ok = 0; - } } if (f->index >= 0) { struct type *ft = st->structure.fields[f->index].type; - if (!type_compat(type, ft, rules)) { + if (!type_compat(type, ft, rules)) type_err(c, "error: have %1 but need %2", prog, ft, rules, type); - *ok = 0; - } return ft; } break; @@ -1994,41 +2001,57 @@ 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; - } - } }$ + 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 - 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; }$ - 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 ${ { @@ -2040,10 +2063,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); } }$ @@ -2146,7 +2169,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); } }$ @@ -2157,7 +2180,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); } }$ @@ -2168,7 +2191,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); } }$ @@ -2189,11 +2212,9 @@ an executable. case Xval: { struct val *val = cast(val, prog); - if (!type_compat(type, val->val.type, rules)) { + if (!type_compat(type, val->val.type, rules)) type_err(c, "error: expected %1%r found %2", prog, type, rules, val->val.type); - *ok = 0; - } return val->val.type; } @@ -2257,38 +2278,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) { @@ -2296,16 +2317,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) { @@ -2314,25 +2335,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; } } @@ -2342,9 +2363,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; @@ -2384,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 - *ok = 0; // NOTEST return Tnone; // NOTEST } if (v->merged) @@ -2394,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); - *ok = 0; return v->val.type; } + if (v->val.type == Tnone && v->where_decl == prog) + type_err(c, "error: variable used but not declared: %v", + prog, NULL, 0, NULL); if (v->val.type == NULL) { if (type && *ok != 0) { v->val = val_prepare(type); @@ -2410,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); - *ok = 0; } if (!type) return v->val.type; @@ -2459,8 +2480,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; @@ -2471,17 +2495,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 @@ -2527,73 +2553,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 @@ -2605,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); - if (type && type != Tbool) { + if (type && type != Tbool) type_err(c, "error: %1 operation found where %2 expected", prog, Tbool, 0, type); - *ok = 0; - } return Tbool; ###### interp binode cases @@ -2668,15 +2702,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 @@ -2696,7 +2732,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; @@ -2706,7 +2743,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 @@ -2725,11 +2763,9 @@ expression operator. if (t) t = propagate_types(b->left, c, ok, t, 0); } - if (!type_compat(type, Tbool, 0)) { + if (!type_compat(type, Tbool, 0)) type_err(c, "error: Comparison returns %1 but %2 expected", prog, Tbool, rules, type); - *ok = 0; - } return Tbool; ###### interp binode cases @@ -2778,34 +2814,35 @@ precedence is handled better I might be able to discard this. 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; } }$ - | 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; @@ -2833,7 +2870,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; @@ -2843,19 +2881,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; @@ -2872,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); - if (!type_compat(type, Tnum, 0)) { + if (!type_compat(type, Tnum, 0)) type_err(c, "error: Arithmetic returns %1 but %2 expected", prog, Tnum, rules, type); - *ok = 0; - } return Tnum; case Concat: /* both must be Tstr, result is Tstr */ propagate_types(b->left, c, ok, Tstr, 0); propagate_types(b->right, c, ok, Tstr, 0); - if (!type_compat(type, Tstr, 0)) { + if (!type_compat(type, Tstr, 0)) type_err(c, "error: Concat returns %1 but %2 expected", prog, Tstr, rules, type); - *ok = 0; - } return Tstr; case Bracket: @@ -3017,45 +3056,41 @@ is in-place. ###### Grammar - $void - OptNL -> Newlines - | - - Newlines -> NEWLINE - | Newlines NEWLINE - $*binode - Open -> { - | NEWLINE { - Close -> } - | NEWLINE } Block -> Open Statementlist Close ${ $0 = $<2; }$ - | Open Newlines Statementlist Close ${ $0 = $<3; }$ | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$ - | Open Newlines SimpleStatements } ${ $0 = reorder_bilist($<3); }$ - | : Statementlist ${ $0 = $<2; }$ - | : SimpleStatements ${ $0 = reorder_bilist($<2); }$ + | : SimpleStatements $$NEWLINE ${ $0 = reorder_bilist($<2); }$ + | : Statementlist $$NEWLINE ${ $0 = $<2; }$ Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$ + | Newlines ComplexStatements ${ $0 = reorder_bilist($<2); }$ ComplexStatements -> ComplexStatements ComplexStatement ${ - $0 = new(binode); - $0->op = Block; - $0->left = $<1; - $0->right = $<2; + if ($2 == NULL) { + $0 = $<1; + } else { + $0 = new(binode); + $0->op = Block; + $0->left = $<1; + $0->right = $<2; + } }$ - | ComplexStatements NEWLINE ${ $0 = $<1; }$ | ComplexStatement ${ - $0 = new(binode); - $0->op = Block; - $0->left = NULL; - $0->right = $<1; + if ($1 == NULL) { + $0 = NULL; + } else { + $0 = new(binode); + $0->op = Block; + $0->left = NULL; + $0->right = $<1; + } }$ $*exec - ComplexStatement -> SimpleStatements NEWLINE ${ + ComplexStatement -> SimpleStatementLine ${ $0 = reorder_bilist($<1); }$ + | ComplexStatement NEWLINE ${ $0 = $<1; }$ ## ComplexStatement Grammar $*binode @@ -3073,7 +3108,11 @@ is in-place. }$ | SimpleStatements ; ${ $0 = $<1; }$ + SimpleStatementLine -> SimpleStatements NEWLINE ${ $0 = $<1; }$ + | SimpleStatementLine NEWLINE ${ $0 = $<1; }$ + SimpleStatement -> pass ${ $0 = NULL; }$ + | ERROR ${ tok_err(c, "Syntax error in statement", &$1); }$ ## SimpleStatement Grammar ###### print binode cases @@ -3083,10 +3122,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 @@ -3118,11 +3157,9 @@ is in-place. if (t && t != Tnone && t != Tbool) { if (!type) type = t; - else if (t != type) { + else if (t != type) type_err(c, "error: expected %1%r, found %2", e->left, type, rules, t); - *ok = 0; - } } } return type; @@ -3191,7 +3228,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(","); } @@ -3262,7 +3299,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 { @@ -3277,9 +3314,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; @@ -3288,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, ""); - 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("::"); @@ -3306,7 +3343,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"); @@ -3338,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)); } - if (t && t->dup == NULL) { + if (t && t->dup == NULL) type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL); - *ok = 0; - } return Tnone; break; @@ -3389,13 +3424,21 @@ function. $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; @@ -3529,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. - CondStatement -> ForThen WhilePart CondSuffix ${ + CondStatement -> ForPart ThenPart WhilePart CondSuffix ${ + $0 = $<4; + $0->forpart = $<1; + $0->thenpart = $<2; + $0->condpart = $3.condpart; $3.condpart = NULL; + $0->dopart = $3.dopart; $3.dopart = NULL; + var_block_close(c, CloseSequential); + }$ + | ForPart WhilePart CondSuffix ${ $0 = $<3; - $0->forpart = $1.forpart; $1.forpart = NULL; - $0->thenpart = $1.thenpart; $1.thenpart = NULL; + $0->forpart = $<1; + $0->thenpart = NULL; $0->condpart = $2.condpart; $2.condpart = NULL; $0->dopart = $2.dopart; $2.dopart = NULL; - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ | WhilePart CondSuffix ${ $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; + $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 - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ CondSuffix -> IfSuffix ${ $0 = $<1; // This is where we close scope of the whole // "for" or "while" statement - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ | CasePart CondSuffix ${ $0 = $<2; @@ -3567,40 +3620,26 @@ defined. }$ $*casepart - CasePart -> Newlines case Expression OpenScope Block ${ - $0 = calloc(1,sizeof(struct casepart)); - $0->value = $<3; - $0->action = $<5; - var_block_close(config2context(config), CloseParallel); - }$ - | case Expression OpenScope Block ${ + CasePart -> case Expression OpenScope Block ${ $0 = calloc(1,sizeof(struct casepart)); $0->value = $<2; $0->action = $<4; - var_block_close(config2context(config), CloseParallel); + var_block_close(c, CloseParallel); }$ + | CasePart NEWLINE ${ $0 = $<1; }$ $*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; - var_block_close(config2context(config), CloseElse); - }$ - | Newlines else OpenScope CondStatement ${ - $0 = new(cond_statement); - $0->elsepart = $<4; - var_block_close(config2context(config), CloseElse); + var_block_close(c, CloseElse); }$ | else OpenScope CondStatement ${ $0 = new(cond_statement); $0->elsepart = $<3; - var_block_close(config2context(config), CloseElse); + var_block_close(c, CloseElse); }$ $*exec @@ -3611,58 +3650,49 @@ defined. | for OpenScope Block ${ $0 = $<3; }$ + | ForPart NEWLINE ${ $0 = $<1; }$ ThenPart -> then OpenScope SimpleStatements ${ $0 = reorder_bilist($<3); - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ | 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 - WhileHead -> while OpenScope Block ${ - $0 = $<3; - }$ + WhileHead -> while OpenScope Block ${ $0 = $<3; }$ + | WhileHead NEWLINE ${ $0 = $<1; }$ $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; }$ - | WhileHead OptNL do Block ${ + | WhileHead do Block ${ $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; - var_block_close(config2context(config), CloseParallel); + var_block_close(c, CloseParallel); }$ - | if OpenScope Block OptNL then OpenScope Block ${ + | if OpenScope Block then OpenScope Block ${ $0.type = Xcond_statement; $0.condpart = $<3; - $0.thenpart = $<7; - var_block_close(config2context(config), CloseParallel); + $0.thenpart = $<6; + var_block_close(c, CloseParallel); }$ + | IfPart NEWLINE ${ $0 = $<1; }$ $*exec // This scope is closed in CondSuffix @@ -3672,6 +3702,7 @@ defined. | switch OpenScope Block ${ $0 = $<3; }$ + | SwitchPart NEWLINE ${ $0 = $<1; }$ ###### print exec cases @@ -3909,14 +3940,19 @@ various declarations in the parse context. $void Ocean -> DeclarationList + | Newlines DeclarationList DeclarationList -> Declaration | DeclarationList Declaration - Declaration -> DeclareConstant + Declaration -> Declaration NEWLINE + | DeclareConstant | DeclareProgram | DeclareStruct - | NEWLINE + | ERROR NEWLINE ${ + tok_err(c, + "error: unhandled parse error", &$1); + }$ ## top level grammar @@ -3946,19 +3982,20 @@ searching through for the Nth constant for decreasing N. ###### top level grammar DeclareConstant -> const Open ConstList Close - | const Open Newlines ConstList Close | 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 ; SimpleConstList ; + | SimpleConstList ; + SimpleConstLine -> SimpleConstList NEWLINE + | SimpleConstLine NEWLINE + | ERROR NEWLINE ${ tok_err(c, "Syntax error in constant", &$1); }$ $*type CType -> Type ${ $0 = $<1; }$ @@ -3968,7 +4005,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; @@ -3976,17 +4013,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); } @@ -4045,7 +4082,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); @@ -4054,17 +4090,13 @@ analysis is a bit more interesting at this level. } }$ $*binode - Program -> program OpenScope Varlist Block OptNL ${ + Program -> program OpenScope Varlist Block ${ $0 = new(binode); $0->op = Program; $0->left = reorder_bilist($<3); $0->right = $<4; - var_block_close(config2context(config), CloseSequential); - if (config2context(config)->scope_stack) abort(); - }$ - | 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 ${ @@ -4077,7 +4109,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; } }$