reduction, or start error handling. 2D tokens (IN, OUT, EOL) also need
to be handled.
+###### parser vars
+
+ struct parser p = { 0 };
+ struct token *tk = NULL;
+ int accepted = 0;
+
+###### heart of parser
+
+ shift(&p, TK_eof, NULL, states);
+ while (!accepted && p.tos > 0) {
+ struct frame *tos = &p.stack[p.tos-1];
+ if (!tk)
+ tk = tok_copy(token_next(tokens));
+ parser_trace(trace, &p,
+ tk, states, non_term, config->known_count);
+
+ ## try shift or ignore
+ ## try reduce
+ ## handle error
+ }
+
+
We return whatever `asn` was returned by reducing production zero.
When we find `TK_in` and `TK_out` tokens which report indents we need
Here the NEWLINE will be shifted because nothing can be reduced until
the `if` is seen.
+For other tokens, we shift the next token if that is possible, otherwise
+we try to reduce a production.
+
+###### try shift or ignore
+
+ if (tk->num == TK_in) {
+ free(tk);
+ tk = NULL;
+ parser_trace_action(trace, "Record");
+ continue;
+ }
+ if (tk->num == TK_out) {
+ if (1) {
+ // OK to cancel
+ free(tk);
+ tk = NULL;
+ parser_trace_action(trace, "Cancel");
+ continue;
+ }
+ // fall through to error handling as both SHIFT and REDUCE
+ // will fail.
+ }
+ if (tk->num == TK_newline) {
+ if (1) {
+ free(tk);
+ tk = NULL;
+ parser_trace_action(trace, "Discard");
+ continue;
+ }
+ }
+ if (shift(&p, tk->num, tk, states)) {
+ tk = NULL;
+ parser_trace_action(trace, "Shift");
+ ## did shift
+ continue;
+ }
+
We have already discussed the bulk of the handling of a "reduce" action,
with the `pop()` and `shift()` functions doing much of the work. There
is a little more complexity needed to manage storage for the asn (Abstract
FILE *trace, const char *non_term[],
struct token_config *config)
{
- struct parser p = { 0 };
- struct token *tk = NULL;
- int accepted = 0;
## parser vars
- shift(&p, TK_eof, NULL, states);
- while (!accepted && p.tos > 0) {
- struct frame *tos = &p.stack[p.tos-1];
- if (!tk)
- tk = tok_copy(token_next(tokens));
- parser_trace(trace, &p,
- tk, states, non_term, config->known_count);
+ ## heart of parser
- if (tk->num == TK_in) {
- free(tk);
- tk = NULL;
- parser_trace_action(trace, "Record");
- continue;
- }
- if (tk->num == TK_out) {
- if (1) {
- // OK to cancel
-
- free(tk);
- tk = NULL;
- parser_trace_action(trace, "Cancel");
- continue;
- }
- // fall through to error handling as both SHIFT and REDUCE
- // will fail.
- }
- if (tk->num == TK_newline) {
- if (1) {
- free(tk);
- tk = NULL;
- parser_trace_action(trace, "Discard");
- continue;
- }
- }
- if (shift(&p, tk->num, tk, states)) {
- tk = NULL;
- parser_trace_action(trace, "Shift");
- ## did shift
- continue;
- }
-
- ## try reduce
- ## handle error
- }
free(tk);
pop(&p, p.tos, do_free);
free(p.asn_stack);