struct symset go_to;
char completed;
char starts_line;
+ int min_prefix;
};
###### grammar fields
struct symset LA = INIT_SYMSET;
unsigned short sn = 0;
+ if (is->min_prefix == 0 ||
+ (bs > 0 && bs < is->min_prefix))
+ is->min_prefix = bs;
if (bs == pr->body_size)
continue;
s = pr->body[bs];
for (s = 0; s < g->states; s++) {
int j;
struct itemset *is = g->statetab[s];
- printf(" Itemset %d:%s\n", s, is->starts_line?" (startsline)":"");
+ printf(" Itemset %d:%s min prefix=%d\n",
+ s, is->starts_line?" (startsline)":"", is->min_prefix);
for (j = 0; j < is->items.cnt; j++) {
report_item(g, is->items.syms[j]);
if (is->items.data != NO_DATA)
short reduce_sym;
short shift_sym;
short starts_line;
+ short min_prefix;
};
}
if (prod >= 0)
- fprintf(f, "\t[%d] = { %d, goto_%d, %d, %d, %d, 0, %d },\n",
+ fprintf(f, "\t[%d] = { %d, goto_%d, %d, %d, %d, 0, %d, %d },\n",
i, is->go_to.cnt, i, prod,
g->productions[prod]->body_size,
g->productions[prod]->head->num,
- is->starts_line);
+ is->starts_line, is->min_prefix);
else
- fprintf(f, "\t[%d] = { %d, goto_%d, -1, -1, -1, %d, %d },\n",
+ fprintf(f, "\t[%d] = { %d, goto_%d, -1, -1, -1, %d, %d, %d },\n",
i, is->go_to.cnt, i, shift_sym,
- is->starts_line);
+ is->starts_line, is->min_prefix);
}
fprintf(f, "};\n\n");
}
short starts_indented;
short indents;
short since_newline;
+ short since_indent;
} *stack;
void **asn_stack;
int stack_size;
* sizeof(p->asn_stack[0]));
}
next->state = newstate;
- next->newline_permitted = 0;
- if (p->tos)
- next->newline_permitted =
- (p->stack[p->tos-1].newline_permitted?:-1)+1;
- if (next->indents > next->starts_indented)
- next->newline_permitted = 0;
- if (next->indents && next->newline_permitted > 2)
- next->newline_permitted = 0;
if (states[newstate].starts_line)
next->newline_permitted = 1;
+ else if (next->indents)
+ next->newline_permitted = 0;
+ else if (p->tos)
+ next->newline_permitted =
+ p->stack[p->tos-1].newline_permitted;
+ else
+ next->newline_permitted = 0;
+
if (next->since_newline) {
if (p->tos)
next->since_newline = p->stack[p->tos-1].since_newline + 1;
else
next->since_newline = 1;
}
+ if (next->indents)
+ next->since_indent = 0;
+ else if (p->tos)
+ next->since_indent = p->stack[p->tos-1].since_indent + 1;
+ else
+ next->since_indent = 1;
+
p->stack[p->tos] = *next;
p->asn_stack[p->tos] = asn;
p->tos++;
continue;
}
if (next.sym == TK_out) {
- if (tos->indents > tos->starts_indented ||
- (tos->indents == 1 &&
- states[tos->state].reduce_size != 1)) {
- tos->indents -= 1;
- if (tos->indents <= tos->starts_indented) {
- // no internal indent any more, reassess 'newline_permitted'
- if (states[tos->state].starts_line)
- tos->newline_permitted = 1;
- else if (p.tos > 1)
- tos->newline_permitted = (p.stack[p.tos-2].newline_permitted ?:-1)+1;
+ if (states[tos->state].reduce_size >= 0 &&
+ states[tos->state].reduce_size <= tos->since_indent)
+ goto force_reduce;
+ if (states[tos->state].min_prefix >= tos->since_indent) {
+ // OK to cancel
+ struct frame *in = tos - tos->since_indent;
+ in->indents -= 1;
+ if (in->indents == 0) {
+ /* Reassess since_indent and newline_permitted */
+ if (in > p.stack) {
+ in->since_indent = in[-1].since_indent + 1;
+ in->newline_permitted = in[-1].newline_permitted;
+ } else {
+ in->since_indent = 0;
+ in->newline_permitted = 0;
+ }
+ if (states[in->state].starts_line)
+ in->newline_permitted = 0;
+ while (in < tos) {
+ in += 1;
+ in->since_indent = in[-1].since_indent + 1;
+ if (states[in->state].starts_line)
+ in->newline_permitted = 1;
+ else
+ in->newline_permitted = in[-1].newline_permitted;
+ }
}
free(tk);
tk = NULL;
// will fail).
}
if (next.sym == TK_newline) {
- if (! tos->newline_permitted) {
+ if (!tos->newline_permitted) {
free(tk);
tk = NULL;
parser_trace_action(trace, "Discard");
if (next.indents == 0)
break;
next.indents -= 1;
+ // FIXME update since_indent here
}
}
if (p.tos == 0 && tk->num == TK_eof)