Algorithm Search⌘K

Proofs: LL(k) parsing

These are the human proofs of LL(k) parsing, at full length.

The LL(k) tables are conflict-free exactly for LL(k) grammars, and LLK-PARSE accepts exactly the sentences in linear time with exact error positions full

This proof shows: correctness.

Statement. Let G=(V,Σ,R,S)G = (V, \Sigma, R, S) be a grammar in which every nonterminal derives some terminal string, and let k≥1k \ge 1. Then:

  1. LLK-TABLES reports a conflict if and only if GG is not LL(k);
  2. if it reports none, then for every input w=a1⋯anw = a_1 \cdots a_n, LLK-PARSE stops after at most c⋅(n+1)c \cdot (n + 1) steps, where cc depends only on GG and kk;
  3. it accepts if and only if w∈L(G)w \in L(G), and then it returns a parse tree of ww with root SS;
  4. if it reports an error at position pp (with p=n+1p = n + 1 meaning the end of the input), then a1⋯ap−1a_1 \cdots a_{p-1} is a prefix of a sentence, and a1⋯apa_1 \cdots a_p is not when p≤np \le n.

Setup. For α∈(V∪Σ)∗\alpha \in (V \cup \Sigma)^* write L(α)L(\alpha) for the set of terminal strings that α\alpha derives; by the hypothesis, L(α)≠∅L(\alpha) \neq \emptyset for every α\alpha. The sets computed at line L12 are the least fixed point of FA=⋃A→Y1⋯YmFY1⊕k⋯⊕kFYmF_A = \bigcup_{A \to Y_1 \cdots Y_m} F_{Y_1} \oplus_k \cdots \oplus_k F_{Y_m}, with Fa={a}F_a = \{a\} for a terminal. They equal FIRSTk(A)\mathrm{FIRST}_k(A). Each element of the fixed point is FIRSTk\mathrm{FIRST}_k of a derived string, by induction on the iteration. Conversely, by induction on the height of a parse tree with root AA and yield xx, FIRSTk(x)\mathrm{FIRST}_k(x) enters the fixed point, since FIRSTk(x1⋯xm)\mathrm{FIRST}_k(x_1 \cdots x_m) depends only on the FIRSTk(xj)\mathrm{FIRST}_k(x_j). The operation ⊕k\oplus_k is associative, and FIRSTk(αβ)=FIRSTk(α)⊕kFIRSTk(β)\mathrm{FIRST}_k(\alpha \beta) = \mathrm{FIRST}_k(\alpha) \oplus_k \mathrm{FIRST}_k(\beta). So the set UU of line L15 is FIRSTk(Y1⋯Ym)⊕kL\mathrm{FIRST}_k(Y_1 \cdots Y_m) \oplus_k L, and the set LjL_j of line L17 is FIRSTk(Yj+1⋯Ym)⊕kL\mathrm{FIRST}_k(Y_{j+1} \cdots Y_m) \oplus_k L. Every UU is nonempty because every symbol is productive.

Step 1: every table comes from a left-sentential form. Claim: for every table T(A,L)T(A, L) that LLK-TABLES creates, there is a leftmost derivation S⇒lm∗uAαS \Rightarrow_{lm}^* u A \alpha with u∈Σ∗u \in \Sigma^* and FIRSTk(α)=L\mathrm{FIRST}_k(\alpha) = L. For T(S,{ε})T(S, \{\varepsilon\}) take u=α=εu = \alpha = \varepsilon. If T(Yj,Lj)T(Y_j, L_j) is created while T(A,L)T(A, L) is filled, with the production A→Y1⋯YmA \to Y_1 \cdots Y_m and a form uAαu A \alpha for T(A,L)T(A, L), then

uAα⇒lmuY1⋯Ymα⇒lm∗uz1⋯zj−1YjYj+1⋯Ymα,u A \alpha \Rightarrow_{lm} u Y_1 \cdots Y_m \alpha \Rightarrow_{lm}^* u z_1 \cdots z_{j-1} Y_j Y_{j+1} \cdots Y_m \alpha,

where each YiY_i with i<ji < j is derived to some zi∈L(Yi)z_i \in L(Y_i), leftmost. The context is α′=Yj+1⋯Ymα\alpha' = Y_{j+1} \cdots Y_m \alpha, and FIRSTk(α′)=FIRSTk(Yj+1⋯Ym)⊕kL=Lj\mathrm{FIRST}_k(\alpha') = \mathrm{FIRST}_k(Y_{j+1} \cdots Y_m) \oplus_k L = L_j.

Step 2: the stack invariant. Read the stack from the top as (X1,t1),…,(Xq,tq)(X_1, t_1), \ldots, (X_q, t_q). Claim: at each test of line L2, whenever Xj∈VX_j \in V, its table is tj=T(Xj,FIRSTk(Xj+1⋯Xq))t_j = T(X_j, \mathrm{FIRST}_k(X_{j+1} \cdots X_q)). Moreover, if i−1i - 1 tokens have been matched, the tree built so far is the tree of a leftmost derivation S⇒lm∗a1⋯ai−1X1⋯XqS \Rightarrow_{lm}^* a_1 \cdots a_{i-1} X_1 \cdots X_q, with one slot for each stack entry.

At the start the stack is (S,T(S,{ε}))(S, T(S, \{\varepsilon\})). A match removes the top terminal; the matched prefix grows by it, and the other entries keep their tables and the symbols below them. Now take an expansion of (X1,T(X1,L))(X_1, T(X_1, L)) with L=FIRSTk(X2⋯Xq)L = \mathrm{FIRST}_k(X_2 \cdots X_q), by X1→Y1⋯YmX_1 \to Y_1 \cdots Y_m. It pushes YjY_j with the table T(Yj,Lj)T(Y_j, L_j), where

Lj=FIRSTk(Yj+1⋯Ym)⊕kFIRSTk(X2⋯Xq)=FIRSTk(Yj+1⋯YmX2⋯Xq).L_j = \mathrm{FIRST}_k(Y_{j+1} \cdots Y_m) \oplus_k \mathrm{FIRST}_k(X_2 \cdots X_q) = \mathrm{FIRST}_k(Y_{j+1} \cdots Y_m X_2 \cdots X_q).

That is the claim for the new stack. The step rewrites the leftmost nonterminal of a1⋯ai−1X1⋯Xqa_1 \cdots a_{i-1} X_1 \cdots X_q, so it is a leftmost step.

A consequence: when X1∈VX_1 \in V is on top with the table T(X1,L)T(X_1, L), the keys of the table are the union over the productions X1→βX_1 \to \beta of FIRSTk(β)⊕kL\mathrm{FIRST}_k(\beta) \oplus_k L, which is FIRSTk(X1⋯Xq)\mathrm{FIRST}_k(X_1 \cdots X_q).

Step 3: acceptance gives a parse tree. The parser accepts only when the stack is empty and i=n+1i = n + 1. By Step 2 the tree is then the tree of a derivation S⇒lm∗a1⋯anS \Rightarrow_{lm}^* a_1 \cdots a_n, so it is a parse tree of ww, and w∈L(G)w \in L(G).

Step 4: sentences are accepted. Assume no conflict, let w∈L(G)w \in L(G), and fix a parse tree tt of ww. As in the LL(1) case, the claim is that the parser expands the nodes of tt in preorder with their productions in tt. Suppose that so far it has done so, and that the top slot is the node xx of tt, with i−1i - 1 tokens matched. The stack then holds the slots of tt that come after the matched leaves, in preorder of the remaining frontier. If xx is a terminal leaf, it is aia_i and the parser matches it. If xx is labeled X1∈VX_1 \in V and uses X1→βX_1 \to \beta in tt, the subtrees of the stack slots spell ai⋯ana_i \cdots a_n. So ai⋯an∈L(βX2⋯Xq)a_i \cdots a_n \in L(\beta X_2 \cdots X_q), and u=FIRSTk(ai⋯an)u = \mathrm{FIRST}_k(a_i \cdots a_n), the lookahead of line L7, lies in FIRSTk(β)⊕kL\mathrm{FIRST}_k(\beta) \oplus_k L with L=FIRSTk(X2⋯Xq)L = \mathrm{FIRST}_k(X_2 \cdots X_q) by Step 2. Line L18 then put X1→βX_1 \to \beta into T(X1,L)[u]T(X_1, L)[u]. Since there is no conflict, it is the only production there, and the parser expands xx as tt does. When all nodes of tt are processed, the stack is empty, i=n+1i = n + 1, and the parser accepts.

Step 5: conflicts are exactly the violations of LL(k). Suppose LLK-TABLES reports a conflict in T(A,L)T(A, L), between productions A→βA \to \beta and A→γA \to \gamma that share a lookahead uu. Take the form u0Aαu_0 A \alpha of Step 1, with FIRSTk(α)=L\mathrm{FIRST}_k(\alpha) = L. Then u∈FIRSTk(βα)∩FIRSTk(γα)u \in \mathrm{FIRST}_k(\beta \alpha) \cap \mathrm{FIRST}_k(\gamma \alpha), so there are x∈L(βα)x \in L(\beta \alpha) and y∈L(γα)y \in L(\gamma \alpha) with FIRSTk(x)=FIRSTk(y)=u\mathrm{FIRST}_k(x) = \mathrm{FIRST}_k(y) = u, and GG is not LL(k).

Conversely, suppose there is no conflict but GG is not LL(k). Take two leftmost derivations S⇒lm∗u0Aα⇒lmu0βα⇒lm∗u0xS \Rightarrow_{lm}^* u_0 A \alpha \Rightarrow_{lm} u_0 \beta \alpha \Rightarrow_{lm}^* u_0 x and S⇒lm∗u0Aα⇒lmu0γα⇒lm∗u0yS \Rightarrow_{lm}^* u_0 A \alpha \Rightarrow_{lm} u_0 \gamma \alpha \Rightarrow_{lm}^* u_0 y with β≠γ\beta \ne \gamma and FIRSTk(x)=FIRSTk(y)=u\mathrm{FIRST}_k(x) = \mathrm{FIRST}_k(y) = u. Run the parser on u0x∈L(G)u_0 x \in L(G). By Step 4 it follows the tree of the first derivation in preorder, so at some point it has matched u0u_0 and has AA on top, with the stack AαA \alpha and the table T(A,FIRSTk(α))T(A, \mathrm{FIRST}_k(\alpha)) by Step 2. Both FIRSTk(βα)\mathrm{FIRST}_k(\beta \alpha) and FIRSTk(γα)\mathrm{FIRST}_k(\gamma \alpha) contain uu, so line L16 saw a conflict in this table, a contradiction. This proves part 1.

Step 6: no left recursion. Assume no conflict, so that GG is LL(k) by Step 5. Claim: no nonterminal AA that is reachable from SS has a derivation A⇒+βAδA \Rightarrow^+ \beta A \delta with β⇒∗ε\beta \Rightarrow^* \varepsilon.

Suppose one does. Along the path to the inner AA we get nonterminals A0=A,A1,…,Ar=AA_0 = A, A_1, \ldots, A_r = A, with r≥1r \ge 1, and productions pj=Aj→βjAj+1δjp_j = A_j \to \beta_j A_{j+1} \delta_j with βj⇒∗ε\beta_j \Rightarrow^* \varepsilon, indices modulo rr. Each AjA_j is reachable from SS, because AA is and A⇒∗⋯Aj⋯A \Rightarrow^* \cdots A_j \cdots. Among all complete trees whose root is one of the AjA_j, choose one of least height, with root AjA_j, root production qq and yield xx. Then q≠pjq \ne p_j, since otherwise its child Aj+1A_{j+1} would root a lower complete tree.

Going once around the cycle from AjA_j with pjp_j first, and deriving each β\beta to ε\varepsilon before the next step, gives Aj⇒lm+AjζA_j \Rightarrow_{lm}^+ A_j \zeta for a string ζ\zeta. Pick z∈L(ζ)z \in L(\zeta), nonempty if possible. Since AjA_j is reachable and every symbol is productive, some leftmost derivation reaches u0Ajαu_0 A_j \alpha with u0∈Σ∗u_0 \in \Sigma^*; let y∈L(α)y \in L(\alpha). For any m≥0m \ge 0, S⇒lm∗u0AjζmαS \Rightarrow_{lm}^* u_0 A_j \zeta^m \alpha, and from this form:

  • applying qq first gives u0xzmyu_0 x z^m y;
  • applying pjp_j first gives u0Ajζm+1α⇒∗u0xzm+1yu_0 A_j \zeta^{m+1} \alpha \Rightarrow^* u_0 x z^{m+1} y.

If z≠εz \neq \varepsilon, take m=km = k; then both strings after u0u_0 start with xzkx z^k, which has length at least kk. If z=εz = \varepsilon, both strings are u0xyu_0 x y. Either way the first kk tokens after u0u_0 agree while the productions qq and pjp_j differ, against the LL(k) condition.

Step 7: the tree is small, and the parser stops. Steps 5 and 6 of the proof for LL(1) parsing use only the absence of the left recursion of Step 6, and they apply word for word. When mm tokens have been matched, every downward path between inner nodes with the same start index has distinct labels, because all labels in the tree are reachable from SS. So the partial tree has at most c0(m+1)c_0 (m + 1) inner nodes, with c0=(2∣V∣+1)(1+r0∣V∣+1)c_0 = (2|V| + 1)(1 + r_0^{|V| + 1}) and r0≥2r_0 \ge 2 at least the length of every right side. Each step is a match (at most nn), an expansion (one new inner node) or the last step, so there are at most c⋅(n+1)c \cdot (n + 1) steps with c=c0+2c = c_0 + 2. This is part 2. If w∉L(G)w \notin L(G), the parser stops and cannot accept by Step 3, so it reports an error. With Step 4 this is part 3.

Step 8: the inspected tokens stay consistent. Let hh be the end of the furthest lookahead used so far: the largest min⁡(i′+k−1,n)\min(i' + k - 1, n) over the expansions done so far at positions i′i', or 00 if there were none. Claim: at each test of line L2, with stack γ=X1⋯Xq\gamma = X_1 \cdots X_q and i−1i - 1 tokens matched, h≤i+k−1h \le i + k - 1, and ai⋯aha_i \cdots a_h is a prefix of some element of FIRSTk(γ)\mathrm{FIRST}_k(\gamma) (the empty string when h<ih < i).

The bound on hh holds because the positions i′i' never exceed ii. After an expansion at ii with the lookahead u=ai⋯amin⁡(i+k−1,n)u = a_i \cdots a_{\min(i+k-1, n)}, we have h=min⁡(i+k−1,n)h = \min(i + k - 1, n). The new stack βX2⋯Xq\beta X_2 \cdots X_q was chosen with u∈FIRSTk(β)⊕kFIRSTk(X2⋯Xq)u \in \mathrm{FIRST}_k(\beta) \oplus_k \mathrm{FIRST}_k(X_2 \cdots X_q), which is FIRSTk\mathrm{FIRST}_k of the new stack. After a match of X1=aiX_1 = a_i, let ai⋯aha_i \cdots a_h be a prefix of v=FIRSTk(aiz)v = \mathrm{FIRST}_k(a_i z) with z∈L(X2⋯Xq)z \in L(X_2 \cdots X_q). Then ai+1⋯aha_{i+1} \cdots a_h is a prefix of FIRSTk−1(z)\mathrm{FIRST}_{k-1}(z), which is a prefix of FIRSTk(z)∈FIRSTk(X2⋯Xq)\mathrm{FIRST}_k(z) \in \mathrm{FIRST}_k(X_2 \cdots X_q). Since every γ\gamma is productive, FIRSTk(γ)\mathrm{FIRST}_k(\gamma) is never empty, which covers h<ih < i.

Step 9: the valid prefix property. Suppose the parser reports an error at position pp, in configuration (i,γ)(i, \gamma). Every element v∈FIRSTk(γ)v \in \mathrm{FIRST}_k(\gamma) is FIRSTk(z)\mathrm{FIRST}_k(z) for some z∈L(γ)z \in L(\gamma), and a1⋯ai−1z∈L(G)a_1 \cdots a_{i-1} z \in L(G) by Step 2. We now check the three places where an error can be reported.

  • Line L5. Here p=ip = i and γ\gamma starts with the terminal X1X_1. The prefix a1⋯ai−1a_1 \cdots a_{i-1} extends to a sentence.
  • Line L8. Here p=i+dp = i + d, where uu and some key v∈FIRSTk(γ)v \in \mathrm{FIRST}_k(\gamma) share dd tokens. The prefix a1⋯ap−1a_1 \cdots a_{p-1} is a1⋯ai−1a_1 \cdots a_{i-1} followed by the first dd tokens of vv, so it starts a sentence. By Step 8, ai⋯aha_i \cdots a_h is a prefix of a key, so d≥h−i+1d \ge h - i + 1 and p>hp > h.
  • Line L11. Here γ=ε\gamma = \varepsilon and p=ip = i; then a1⋯ai−1∈L(G)a_1 \cdots a_{i-1} \in L(G). If the last decision ended at h≥ih \ge i, Step 8 with γ=ε\gamma = \varepsilon gives ai⋯ah=εa_i \cdots a_h = \varepsilon, so h<i=ph < i = p.

In all three cases p>hp > h, because at line L5 we have h≤i−1h \le i - 1: if h≥ih \ge i, then aia_i is the first token of an element of FIRSTk(X1⋯ )\mathrm{FIRST}_k(X_1 \cdots), which starts with X1X_1, so X1=aiX_1 = a_i and there is no error.

Now let p≤np \le n and suppose some sentence ss starts with a1⋯apa_1 \cdots a_p. Every expansion so far looked at tokens with positions at most h<ph < p, and every match at positions below i≤pi \le p. The parser therefore makes the same moves on ss as on ww and reaches the same configuration (i,γ)(i, \gamma). On ss it accepts by Step 4, and the rest of its run derives the rest of ss from γ\gamma, so FIRSTk(sisi+1⋯ )∈FIRSTk(γ)\mathrm{FIRST}_k(s_i s_{i+1} \cdots) \in \mathrm{FIRST}_k(\gamma). We look at the three lines again.

  • Line L5. On ss the parser matches X1=si=aiX_1 = s_i = a_i, a contradiction.
  • Line L8. On ss the lookahead is a key of tt that agrees with uu on its first d+1d + 1 tokens, because ss and ww agree up to position p=i+dp = i + d. This contradicts the maximality of dd.
  • Line L11. The stack is empty while ss has the token sp=aps_p = a_p left, so the parser would not accept ss.

This proves part 4. ■\blacksquare

Back to LL(k) parsing