X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Fparsergen.mdc;h=76fec3a70a779cefe4589a9d79e861a61acd726e;hp=04974c3c6a7d749908ba3e672179e253082fca4e;hb=ca00beb39b9d02578c1f0b556a2c2f70f28cf6e7;hpb=1241e83b69180195d70eb673a4266c710533ece3 diff --git a/csrc/parsergen.mdc b/csrc/parsergen.mdc index 04974c3..76fec3a 100644 --- a/csrc/parsergen.mdc +++ b/csrc/parsergen.mdc @@ -499,6 +499,8 @@ Now we have all the bits we need to parse a full production. vs = sym_find(g, tk.txt); if (vs->num == TK_newline) p.line_like = 1; + else if (vs->num == TK_out) + p.line_like = 2; else if (vs->precedence == 0) { err = "symbol after $$ must have precedence"; goto abort; @@ -1309,6 +1311,8 @@ into the go to set, so the item is ineffective. struct symbol *s; struct symset LA = INIT_SYMSET; unsigned short sn = 0; + struct symset LAnl = INIT_SYMSET; + unsigned short snnl = 0; if (is->min_prefix == 0 || (bs > 0 && bs < is->min_prefix)) @@ -1341,15 +1345,15 @@ into the go to set, so the item is ineffective. int to_end; add_first(pr, bs+1, &LA, g, &to_end); if (to_end) { - if (pr->line_like) - symset_add(&LA, TK_newline, 0); - else { - struct symset ss = set_find(g, is->items.data[i]); - symset_union(&LA, &ss); - } + struct symset ss = set_find(g, is->items.data[i]); + symset_union(&LA, &ss); } sn = save_set(g, LA); LA = set_find(g, sn); + if (symset_find(&LA, TK_newline)) + symset_add(&LAnl, TK_newline, 0); + snnl = save_set(g, LAnl); + LAnl = set_find(g, snnl); } /* Add productions for this symbol */ @@ -1360,19 +1364,25 @@ into the go to set, so the item is ineffective. int itm = item_num(p2, 0); int pos = symset_find(&is->items, itm); if (pos < 0) { - symset_add(&is->items, itm, sn); + if (g->productions[p2]->line_like) + symset_add(&is->items, itm, snnl); + else + symset_add(&is->items, itm, sn); /* Will have re-ordered, so start * from beginning again */ i = -1; } else if (type >= LALR) { struct symset ss = set_find(g, is->items.data[pos]); struct symset tmp = INIT_SYMSET; + struct symset *la = &LA; + if (g->productions[p2]->line_like) + la = &LAnl; symset_union(&tmp, &ss); - if (symset_union(&tmp, &LA)) { + if (symset_union(&tmp, la)) { is->items.data[pos] = save_set(g, tmp); i = -1; - }else + } else symset_free(tmp); } } @@ -1643,8 +1653,10 @@ it up a bit. First the items, with production number and associativity. printf(" [%d%s]", s->precedence, assoc_names[s->assoc]); } - if (pr->line_like) + if (pr->line_like == 1) printf(" $$NEWLINE"); + else if (pr->line_like) + printf(" $$OUT"); printf("\n"); } @@ -1783,14 +1795,10 @@ terminals to items where that terminal could be shifted and another which maps terminals to items that could be reduced when the terminal is in look-ahead. We report when we get conflicts between the two. -As a special case, if we find a SHIFT/REDUCE conflict, where a -terminal that could be shifted is in the lookahead set of some -reducable item, then set check if the reducable item also have -`TK_newline` in its lookahead set. If it does, then a newline will -force the reduction, but anything else can reasonably be shifted, so -that isn't really a conflict. Such apparent conflicts do not get -counted, and are reported as non-critical. This will not affect a -"traditional" grammar that does not include newlines as token. +As a special case, if we find a SHIFT/REDUCE conflict, on the NEWLINE +terminal, we ignore it. NEWLINES are handled specially with its own +rules for when to shift and when to reduce. Conflicts are expected, +but handled internally. static int conflicts_slr(struct grammar *g, enum grammar_type type) { @@ -1844,12 +1852,9 @@ counted, and are reported as non-critical. This will not affect a for (k = 0; k < la.cnt; k++) { int pos = symset_find(&shifts, la.syms[k]); if (pos >= 0 && la.syms[k] != TK_newline) { - if (symset_find(&la, TK_newline) < 0) { - printf(" State %d has SHIFT/REDUCE conflict on ", i); - cnt++; - } else - printf(" State %d has non-critical SHIFT/REDUCE conflict on ", i); - prtxt(g->symtab[la.syms[k]]->name); + printf(" State %d has SHIFT/REDUCE conflict on ", i); + cnt++; + prtxt(g->symtab[la.syms[k]]->name); printf(":\n"); report_item(g, shifts.data[pos]); report_item(g, itm);