Non-Recursive Predictive Parser: Architecture and Algorithm (LL(1))

Non-Recursive Predictive Parser: Architecture and Algorithm (LL(1))

Verified Sources
Nov 4, 2026

A predictive parser is typically implemented either recursively (calling parsing routines per nonterminal) or non-recursively using an explicit stack and a parsing table. The non-recursive predictive parser (most often the table-driven LL(1) parser) has a clear architecture: it maintains a stack of grammar symbols, reads the next input token (lookahead), and consults a parsing table to decide whether to expand a nonterminal or match a terminal, until it reaches an accepting configuration. This approach eliminates recursion by simulating what the call stack would do in a recursive descent parser.

Key components

  • Parsing table MM
  • Lookahead aa
  • Parsing stack SS
  • Start symbol S0S_0
  • [End marker]{def="A special token (oror) appended to input to signal end"} $$$
  • LL(1) grammar: determinism depends on FIRST/FOLLOW properties

Dataflow overview (architecture)

This architecture is commonly presented alongside the standard LL(1) table construction (using FIRST and FOLLOW). For a correct parsing table, the grammar must be LL(1), ensuring at most one production per table cell.

Important: If the parsing table cell is empty or conflicts, the parser must report an error (no valid derivation for the observed lookahead).

From Grammar to Non-Recursive Predictive Parsing

Compute FIRST sets

1

Compute FIRST for terminals/nonterminals to know possible leading tokens."

Compute FOLLOW sets

2

Compute FOLLOW to place productions into cells where ϵ\epsilon can occur."

Build LL(1) parsing table M

3

Fill M[A,a] with the unique production A→α for lookahead a (if LL(1))."

Run non-recursive parse loop

4

Use explicit stack + table lookup with one-token lookahead."

Core algorithm idea

The non-recursive parser repeatedly inspects:

  1. the symbol on top of the stack, and
  2. the current input lookahead token.

Then:

  • If the top symbol is a terminal:
    • it must match the lookahead; otherwise error.
  • If the top symbol is a nonterminal:
    • consult parsing table M[nonterminal,lookahead]M[\text{nonterminal}, \text{lookahead}]:
      • if a production exists: replace the nonterminal on the stack with the RHS (pushed in reverse order),
      • else error.
  • When the stack top is \$$ and the input lookahead is also $$, the parser accepts.

This procedure is the iterative counterpart of the recursive approach that would “call” the appropriate production based on lookahead.

Key design invariants

  • The parser stack always contains a suffix of the right-sentential form that should correspond to the remaining portion of the input.
  • Table-driven expansion preserves derivation consistency: if the grammar is LL(1) and the table is correct, each step mimics choosing the same production that a deterministic recursive descent parser would choose.

Non-Recursive Predictive Parsing (Table-Driven LL(1))

  1. 1
    Step 1

    Push start symbol S0S_0 onto stack SS. Append end marker \`$ to input. Set input pointer so the current lookahead is the first token.

  2. 2
    Step 2

    Let XX be the top of stack. Let aa be the current lookahead token.

  3. 3
    Step 3

    If XX is a terminal (including possibly \`):if): if X == a,pop, pop XfromfromS$ and advance input to the next token; otherwise report error (terminal mismatch).

  4. 4
    Step 4

    If XX is a nonterminal: consult parsing table entry M[X,a]M[X,a].

  5. 5
    Step 5

    If M[X,a]=X→αM[X,a] = X \to \alpha for some production RHS α\alpha, pop XX, then push the symbols of α\alpha onto stack SS in reverse order. If α=ϵ\alpha = \epsilon, push nothing. If M[X,a]M[X,a] is empty, report error (no production for this lookahead).

  6. 6
    Step 6

    If X == \$ and $a == \$‘`, accept the input.

  7. 7
    Step 7

    On any mismatch or empty table entry, halt and report that the input is not in the language (or cannot be parsed under the LL(1) grammar).

To make MM correct, a production AtoalphaA \\to \\alpha must be placed into table cells that correspond to all possible lookahead tokens that can appear when AA is expanded. The standard LL(1) logic uses:

  • For each terminal tintextFIRST(alpha)t \\in \\text{FIRST}(\\alpha), add AtoalphaA \\to \\alpha to M[A,t]M[A,t].
  • If epsilonintextFIRST(alpha)\\epsilon \\in \\text{FIRST}(\\alpha), then AtoalphaA \\to \\alpha must also be placed for all terminals bintextFOLLOW(A)b \\in \\text{FOLLOW}(A), i.e., add AtoalphaA \\to \\alpha to M[A,b]M[A,b].
  • If alpha\\alpha derives epsilon\\epsilon, ensure the FOLLOW propagation handles lookaheads appropriately so the parser knows when to effectively “skip” the production.

Minimal architectural consequence

Because the runtime algorithm only consults M[X,a]M[X,a], all correctness depends on whether MM is constructed to satisfy LL(1) determinism (no conflicting productions in any cell).

Pro Tip: Push RHS in reverse order

When applying a production X→αX \to \alpha, you pop XX and push the RHS symbols so that the leftmost symbol of α\alpha becomes the new top of stack. In practice: push RHS from right to left.

Warning: Empty or conflicting table cells are hard parse failures

If M[X,a]M[X,a] is empty, the parser cannot proceed deterministically. If multiple productions would apply (not LL(1)), you either need a different grammar (e.g., LL(2)) or a different parsing strategy.

Operational complexity

Let nn be the number of input tokens (excluding \\`$). Each loop iteration either:

  • matches and advances the input (consuming at least one token), or
  • expands a nonterminal by pushing RHS symbols (which increases stack content but is bounded by the derivation steps for valid inputs).

For an LL(1) predictive parser, the number of expansions and matches is linear in the length of a valid derivation, so runtime is typically described as O(n)O(n) for parsing (ignoring the cost of building MM). Building FIRST/FOLLOW and MM is additional preprocessing.

Symbol handling guarantees

  • Terminals: exactly matched or error.
  • Nonterminals: expanded only when a table entry exists.
  • Epsilon productions: represent “push nothing”, so the parser effectively performs a zero-length derivation step.

What Each Step Does in the Parse Loop

Runtime loop responsibilities (conceptual counts for a valid input).

Common Questions for Non-Recursive Predictive Parsing

LL(1) Parsing (Predictive Parsing) Tutorial

Knowledge Check

Question 1 of 4
Q1Single choice

In a non-recursive predictive (LL(1)) parser, what is the typical role of the parsing table M?