freeing function. The symbol leads us to the right free function through
`do_free`.
-The `indents` count and the `starts_indented` flag track the line
-indents in the symbol. These are used to allow indent information to
-guide parsing and error recovery.
+The `indents` count tracks the line indents in the symbol. These are
+used to allow indent information to guide parsing and error recovery.
`since_newline` tracks how many stack frames since the last
start-of-line (whether indented or not). So if `since_newline` is
short newline_permitted;
short sym;
- short starts_indented;
short indents;
short since_newline;
+ short since_indent;
} *stack;
void **asn_stack;
int stack_size;
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++;
{
int i;
p->tos -= num;
- next->starts_indented =
- p->stack[p->tos].starts_indented;
next->since_newline =
p->stack[p->tos].since_newline;
next->indents = 0;
parser_trace(trace, &p, &next, tk, states, non_term, config->known_count);
if (next.sym == TK_in) {
- next.starts_indented = 1;
next.indents = 1;
next.since_newline = 0;
free(tk);
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;
- else
- tos->newline_permitted = 0;
+ 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;
}
if (shift(&p, &next, tk, states)) {
next.since_newline = !(tk->num == TK_newline);
- next.starts_indented = 0;
next.indents = 0;
tk = NULL;
parser_trace_action(trace, "Shift");
pop(&p, size, &frame, do_free);
else {
frame.indents = next.indents;
- frame.starts_indented = frame.indents;
frame.since_newline = 1;
next.indents = 0;
- next.starts_indented = 0;
}
res = memdup(buf, bufsize);
memset(buf, 0, bufsize);
if (next.indents == 0)
break;
next.indents -= 1;
+ // FIXME update since_indent here
}
}
if (p.tos == 0 && tk->num == TK_eof)
fputs(non_term[sym - TK_reserved - knowns],
trace);
if (f->indents)
- fprintf(trace, "%c%d", f->starts_indented?':':'.',
- f->indents);
+ fprintf(trace, ".%d", f->indents);
if (f->since_newline == 0)
fputs("/", trace);
fputs(" ", trace);
else
text_dump(trace, tk->txt, 20);
if (n->indents)
- fprintf(trace, "%c%d", n->starts_indented?':':'.',
- n->indents);
+ fprintf(trace, ".%d", n->indents);
if (n->since_newline == 0)
fputs("/", trace);
fputs("]", trace);