- FILE *trace, const char *non_term[], int knowns)
- {
- struct parser p = { 0 };
- struct token *tk = NULL;
- int accepted = 0;
- void *ret;
-
- while (!accepted) {
- struct token *err_tk;
- if (!tk)
- tk = tok_copy(token_next(tokens));
- p.next.sym = tk->num;
- if (trace)
- parser_trace(trace, &p, tk, states, non_term, knowns);
-
- if (p.next.sym == TK_in) {
- p.next.starts_indented = 1;
- p.next.indents = 1;
- free(tk);
- tk = NULL;
- continue;
- }
- if (p.next.sym == TK_out) {
- if (p.stack[p.tos-1].indents > p.stack[p.tos-1].starts_indented ||
- (p.stack[p.tos-1].indents == 1 &&
- states[p.next.state].reduce_size > 1)) {
- p.stack[p.tos-1].indents -= 1;
- if (p.stack[p.tos-1].indents == p.stack[p.tos-1].starts_indented) {
- // no internal indent any more, reassess 'newline_permitted'
- if (states[p.stack[p.tos-1].state].starts_line)
- p.stack[p.tos-1].newline_permitted = 1;
- else if (p.tos > 1)
- p.stack[p.tos-1].newline_permitted = p.stack[p.tos-2].newline_permitted;
- }
- free(tk);
- tk = NULL;
- continue;
- }
- // fall through and force a REDUCE (as 'shift'
- // will fail).
- }
- if (p.next.sym == TK_newline) {
- if (! p.stack[p.tos-1].newline_permitted) {
- free(tk);
- tk = NULL;
- continue;
- }
- }
- if (shift(&p, tk, states)) {
- tk = NULL;
- continue;
- }
- if (states[p.next.state].reduce_prod >= 0) {
- void **body;
- int prod = states[p.next.state].reduce_prod;
- int size = states[p.next.state].reduce_size;
- int bufsize;
- static char buf[16*1024];
- p.next.sym = states[p.next.state].reduce_sym;
-
- body = p.asn_stack +
- (p.tos - states[p.next.state].reduce_size);
-
- bufsize = do_reduce(prod, body, buf);
-
- pop(&p, size, do_free);
- shift(&p, memdup(buf, bufsize), states);
- if (prod == 0)
- accepted = 1;
- continue;
- }
- if (tk->num == TK_out) {
- // Indent problem - synthesise tokens to get us
- // out of here.
- fprintf(stderr, "Synthesize %d to handle indent problem\n", states[p.next.state].shift_sym);
- p.next.sym = states[p.next.state].shift_sym;
- shift(&p, tok_copy(*tk), states);
- // FIXME need to report this error somehow
- continue;
- }
- /* Error. We walk up the stack until we
- * find a state which will accept TK_error.
- * We then shift in TK_error and see what state
- * that takes us too.
- * Then we discard input tokens until
- * we find one that is acceptable.
- */