X-Git-Url: https://ocean-lang.org/code/?a=blobdiff_plain;f=csrc%2Foceani.mdc;h=ab6abe91f67156e03a0e81926897d320e652b04a;hb=850a39a0a761e0af89c15253f075ecd9e9ecc6ee;hp=f4d8517f2692bac0623cb2da5bab58f4d4fa05ab;hpb=6e1684630c7e1af7c3f441acbed3acccc543ba2e;p=ocean diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index f4d8517..ab6abe9 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 @@ -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,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 +1094,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 +1456,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 +1479,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 +1676,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 +1698,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 +1742,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 +1757,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 +1928,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 +1958,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 +1999,50 @@ 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 -> { - | NEWLINE Open + | Newlines { Close -> } - | NEWLINE Close + | Newlines } $*fieldlist - FieldBlock -> Open FieldList Close ${ $0 = $<2; }$ + FieldBlock -> Open FieldList } ${ $0 = $<2; }$ | Open SimpleFieldList } ${ $0 = $<2; }$ - | : FieldList ${ $0 = $<2; }$ + | : FieldList $$NEWLINE ${ $0 = $<2; }$ - FieldList -> SimpleFieldList NEWLINE ${ $0 = $<1; }$ - | FieldList SimpleFieldList NEWLINE ${ + FieldList -> FieldLines ${ $0 = $<1; }$ + | Newlines FieldLines ${ $0 = $<2; }$ + FieldLines -> SimpleFieldListLine ${ $0 = $<1; }$ + | FieldLines SimpleFieldListLine ${ $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; @@ -2047,10 +2061,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); } }$ @@ -2153,7 +2167,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); } }$ @@ -2164,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); } }$ @@ -2175,7 +2189,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); } }$ @@ -2196,11 +2210,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; } @@ -2264,38 +2276,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) { @@ -2303,16 +2315,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) { @@ -2321,25 +2333,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; } } @@ -2349,9 +2361,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; @@ -2391,7 +2403,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) @@ -2401,9 +2412,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); @@ -2417,7 +2430,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; @@ -2466,8 +2478,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; @@ -2478,17 +2493,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 @@ -2534,73 +2551,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 @@ -2612,11 +2639,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 @@ -2675,15 +2700,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 @@ -2703,7 +2730,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; @@ -2713,7 +2741,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 @@ -2732,11 +2761,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 @@ -2785,34 +2812,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; @@ -2840,7 +2868,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; @@ -2850,19 +2879,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; @@ -2879,22 +2913,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: @@ -3024,17 +3054,14 @@ is in-place. ###### Grammar - $void - Newlines -> NEWLINE - | Newlines NEWLINE - $*binode Block -> Open Statementlist Close ${ $0 = $<2; }$ | Open SimpleStatements } ${ $0 = reorder_bilist($<2); }$ | : SimpleStatements ${ $0 = reorder_bilist($<2); }$ - | : Statementlist ${ $0 = $<2; }$ + | : Statementlist $$OUT ${ $0 = $<2; }$ Statementlist -> ComplexStatements ${ $0 = reorder_bilist($<1); }$ + | Newlines ComplexStatements ${ $0 = reorder_bilist($<2); }$ ComplexStatements -> ComplexStatements ComplexStatement ${ if ($2 == NULL) { @@ -3058,10 +3085,10 @@ is in-place. }$ $*exec - ComplexStatement -> SimpleStatements NEWLINE ${ + ComplexStatement -> SimpleStatementLine ${ $0 = reorder_bilist($<1); }$ - | Newlines ${ $0 = NULL; }$ + | ComplexStatement NEWLINE ${ $0 = $<1; }$ ## ComplexStatement Grammar $*binode @@ -3077,9 +3104,13 @@ is in-place. $0->left = NULL; $0->right = $<1; }$ - | SimpleStatements ; ${ $0 = $<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 ###### print binode cases @@ -3089,10 +3120,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 @@ -3124,11 +3155,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; @@ -3197,7 +3226,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(","); } @@ -3268,7 +3297,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 { @@ -3283,9 +3312,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; @@ -3294,7 +3323,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("::"); @@ -3312,7 +3341,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"); @@ -3344,10 +3373,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; @@ -3395,13 +3422,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; @@ -3528,51 +3563,53 @@ defined. case Xcond_statement: free_cond_statement(cast(cond_statement, e)); break; ###### ComplexStatement Grammar - | CondStatement ${ $0 = $<1; }$ + | CondStatement $$NEWLINE ${ $0 = $<1; }$ ###### Grammar $*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 -> forPart ThenPart 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(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ - | forPart WhilePart CondSuffix ${ + | 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); + var_block_close(c, CloseSequential); }$ - | whilePart CondSuffix ${ + | 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 ${ + | 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; @@ -3580,108 +3617,120 @@ defined. $0->casepart = $<1; }$ - $void - Case -> case - | NEWLINE Case $*casepart - CasePart -> 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 -> ${ $0 = new(cond_statement); }$ - | NEWLINE IfSuffix ${ $0 = $<2; }$ + | IfSuffix NEWLINE ${ $0 = $<1; }$ | else OpenScope Block ${ $0 = new(cond_statement); $0->elsepart = $<3; - var_block_close(config2context(config), CloseElse); + var_block_close(c, CloseElse); + }$ + | else OpenScope SimpleStatements NEWLINE ${ + $0 = new(cond_statement); + $0->elsepart = reorder_bilist($<3); + 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); }$ - $void - Then -> then - | NEWLINE Then - While -> while - | NEWLINE While - Do -> do - | NEWLINE Do $*exec // These scopes are closed in CondSuffix - forPart -> for OpenScope SimpleStatements ${ + ForPart -> for OpenScope SimpleStatements ; ${ + $0 = reorder_bilist($<3); + }$ + | for OpenScope SimpleStatements NEWLINE ${ $0 = reorder_bilist($<3); }$ | for OpenScope Block ${ $0 = $<3; }$ + | ForPart NEWLINE ${ $0 = $<1; }$ - ThenPart -> Then OpenScope SimpleStatements ${ + ThenPart -> then OpenScope SimpleStatements ; ${ $0 = reorder_bilist($<3); - var_block_close(config2context(config), CloseSequential); + var_block_close(c, CloseSequential); }$ - | Then OpenScope Block ${ + | then OpenScope SimpleStatements NEWLINE ${ + $0 = reorder_bilist($<3); + var_block_close(c, CloseSequential); + }$ + | then OpenScope Block ${ $0 = $<3; - var_block_close(config2context(config), CloseSequential); + 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 -> while OpenScope Block ${ $0 = $<3; }$ + | WhileHead NEWLINE ${ $0 = $<1; }$ $cond_statement // This scope is closed in CondSuffix - whilePart -> while OpenScope Expression Block ${ + WhilePart -> while OpenScope Expression Block ${ $0.type = Xcond_statement; $0.condpart = $<3; $0.dopart = $<4; }$ - | whileHead Do Block ${ + | WhileHead do Block ${ $0.type = Xcond_statement; $0.condpart = $<1; $0.dopart = $<3; }$ - WhilePart -> While OpenScope Expression Block ${ + | WhilePart NEWLINE ${ $0 = $<1; }$ + + IfPart -> if OpenScope Expression OpenScope Block ${ $0.type = Xcond_statement; $0.condpart = $<3; - $0.dopart = $<4; + $0.thenpart = $<5; + var_block_close(c, CloseParallel); }$ - | WhileHead Do Block ${ + | if OpenScope Expression OpenScope then Block ${ $0.type = Xcond_statement; - $0.condpart = $<1; - $0.dopart = $<3; + $0.condpart = $<3; + $0.thenpart = $<6; + var_block_close(c, CloseParallel); }$ - - ifPart -> if OpenScope Expression OpenScope Block ${ + | if OpenScope Expression OpenScope then SimpleStatements ; ${ $0.type = Xcond_statement; $0.condpart = $<3; - $0.thenpart = $<5; - var_block_close(config2context(config), CloseParallel); + $0.thenpart = reorder_bilist($<6); + var_block_close(c, CloseParallel); + }$ + | 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 Block Then OpenScope Block ${ + | if OpenScope Block then OpenScope Block ${ $0.type = Xcond_statement; $0.condpart = $<3; $0.thenpart = $<6; - var_block_close(config2context(config), CloseParallel); + var_block_close(c, CloseParallel); }$ + | IfPart NEWLINE ${ $0 = $<1; }$ $*exec // This scope is closed in CondSuffix - switchPart -> switch OpenScope Expression ${ + SwitchPart -> switch OpenScope Expression ${ $0 = $<3; }$ | switch OpenScope Block ${ $0 = $<3; }$ + | SwitchPart NEWLINE ${ $0 = $<1; }$ ###### print exec cases @@ -3919,14 +3968,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 @@ -3957,17 +4011,19 @@ searching through for the Nth constant for decreasing N. DeclareConstant -> const Open ConstList Close | const Open SimpleConstList } - | const : ConstList + | const : ConstList $$NEWLINE | const SimpleConstList NEWLINE - ConstList -> ComplexConsts - | NEWLINE ConstList - ComplexConsts -> ComplexConst ComplexConsts - | ComplexConst - ComplexConst -> SimpleConstList NEWLINE + ConstList -> ConstLines + | Newlines ConstLines + ConstLines -> ConstLines SimpleConstLine + | SimpleConstLine SimpleConstList -> SimpleConstList ; Const | Const | SimpleConstList ; + SimpleConstLine -> SimpleConstList NEWLINE + | SimpleConstLine NEWLINE + | ERROR NEWLINE ${ tok_err(c, "Syntax error in constant", &$1); }$ $*type CType -> Type ${ $0 = $<1; }$ @@ -3977,7 +4033,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; @@ -3985,17 +4041,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); } @@ -4054,7 +4110,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); @@ -4068,12 +4123,8 @@ analysis is a bit more interesting at this level. $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 ${ @@ -4086,7 +4137,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; } }$ @@ -4303,6 +4354,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")