+For terminal symbols, we just dump the token. For non-terminals we
+print the name of the symbol. The look ahead token is reported at the
+end inside square brackets.
+
+###### parser functions
+
+ static char *reserved_words[] = {
+ [TK_error] = "ERROR",
+ [TK_in] = "IN",
+ [TK_out] = "OUT",
+ [TK_newline] = "NEWLINE",
+ [TK_eof] = "$eof",
+ };
+ static void parser_trace_state(FILE *trace, struct frame *f, const struct state states[])
+ {
+ fprintf(trace, "(%d", f->state);
+ if (states[f->state].starts_line)
+ fprintf(trace, "s");
+ if (f->newline_permitted)
+ fprintf(trace, "n%d", f->since_newline);
+ fprintf(trace, ") ");
+ }
+
+ void parser_trace(FILE *trace, struct parser *p,
+ struct token *tk, const struct state states[],
+ const char *non_term[], int knowns)
+ {
+ int i;
+ if (!trace)
+ return;
+ for (i = 0; i < p->tos; i++) {
+ struct frame *f = &p->stack[i];
+ if (i) {
+ int sym = f->sym;
+ if (sym < TK_reserved &&
+ reserved_words[sym] != NULL)
+ fputs(reserved_words[sym], trace);
+ else if (sym < TK_reserved + knowns) {
+ struct token *t = p->asn_stack[i];
+ text_dump(trace, t->txt, 20);
+ } else
+ fputs(non_term[sym - TK_reserved - knowns],
+ trace);
+ if (f->indents)
+ fprintf(trace, ".%d", f->indents);
+ if (f->since_newline == 0)
+ fputs("/", trace);
+ fputs(" ", trace);
+ }
+ parser_trace_state(trace, f, states);
+ }
+ fprintf(trace, "[");
+ if (tk->num < TK_reserved &&
+ reserved_words[tk->num] != NULL)
+ fputs(reserved_words[tk->num], trace);
+ else
+ text_dump(trace, tk->txt, 20);
+ fputs("]", trace);
+ }
+
+ void parser_trace_action(FILE *trace, char *action)
+ {
+ if (trace)
+ fprintf(trace, " - %s\n", action);
+ }