BUILD fills each cell with exactly the productions whose PREDICT set contains the token full
This proof shows: correctness.
Statement. Let G=(V,Σ,R,S) be a grammar in which every nonterminal is reachable from S. When BUILD(G) stops, the computed sets equal Null, FIRST(A) and FOLLOW(A) as defined on the page, for each A∈V, and each cell satisfies invariant (T): M[A,a] holds exactly the productions A→α with a∈PREDICT(A→α). LOOKUP(M,A,a) returns error exactly when no production of A has a in its PREDICT set, and the unique such production when there is one. Without the reachability hypothesis, Null and FIRST are still exact, and the computed FOLLOW(A) contains the true one.
Setup. We treat $ as an extra terminal and work with sentential forms of S$. For a string γ over V∪Σ∪{$}, FIRST(γ)={a:γ⇒∗aρ}. We use the splitting lemma of the derivation page in its general form, whose proof is the same: if Y1⋯Yk⇒mγ, then γ=γ1⋯γk with Yi⇒miγi and ∑mi=m. A consequence: a∈FIRST(Y1⋯Yk) if and only if there is an i with Y1⋯Yi−1⇒∗ε and a∈FIRST(Yi), since the first terminal of γ lies in the first nonempty piece γi. The computation of Null is proved correct on the nullable symbol page. We write F(⋅) and Fo(⋅) for the sets that the loops compute.
Step 1: termination. Each loop of SETS repeats a pass only when the pass added an element to some set. The sets are subsets of the finite sets V, V×Σ and V×(Σ∪{$}), and elements are never removed. So each loop makes at most ∣V∣(∣Σ∣+1)+1 passes, and BUILD stops.
Step 2: FIRST is sound. Claim: if a is added to F(A), then a∈FIRST(A). Induction on the order of the additions. The rule of lines L3 and L4 adds a when A→X1⋯Xk, X1⋯Xi−1 is nullable, and a∈F(Xi), where F(a)={a} for a terminal. If Xi is a nonterminal, a was added to F(Xi) earlier, so Xi⇒∗aρ by the induction hypothesis. In both cases A⇒X1⋯Xk⇒∗Xi⋯Xk⇒∗aρXi+1⋯Xk.
Step 3: FIRST is complete. Claim: if A⇒maρ, then a∈F(A) when the loop stops. Strong induction on m≥1. The first step is A⇒X1⋯Xk, and X1⋯Xk⇒m−1aρ. By the splitting lemma there is an i with X1⋯Xi−1⇒∗ε and Xi⇒miaρ′ with mi≤m−1. If Xi is the terminal a, the rule adds a to F(A). Otherwise a∈F(Xi) by the induction hypothesis, and the last pass of the loop changed nothing, so the rule for A→X1⋯Xk and this i found a already in F(A). With Step 2, F(A)=FIRST(A), and then the formula of the page gives FIRST(α) for each string α by the consequence of the splitting lemma.
Step 4: FOLLOW is complete. Claim: if S$⇒mβAγ, then FIRST(γ)⊆Fo(A). Since a∈FOLLOW(A) means S$⇒∗βAaγ′, and a∈FIRST(aγ′), this gives FOLLOW(A)⊆Fo(A). Induction on m.
-
m=0: the form is S$, so A=S and γ=$, and line L6 puts $ in Fo(S).
-
m≥1: the last step rewrites C→η in δ1Cδ2, giving δ1ηδ2=βAγ, and S$⇒m−1δ1Cδ2. Three cases for the position of this occurrence of A.
- In δ2: δ2=ρAγ, and the same occurrence has the right context γ in δ1Cδ2. The induction hypothesis applies.
- In δ1: δ1=βAρ and γ=ρηδ2. In the earlier form the right context is ρCδ2, and ρCδ2⇒ρηδ2, so FIRST(γ)⊆FIRST(ρCδ2)⊆Fo(A) by the induction hypothesis.
- In η: η=η1Aη2 and γ=η2δ2. Let a∈FIRST(η2δ2). By the splitting lemma, either a∈FIRST(η2), and lines L7 and L8 put a in Fo(A) for the production C→η1Aη2; or η2 is nullable and a∈FIRST(δ2). In the second case a∈Fo(C) by the induction hypothesis for the occurrence of C in δ1Cδ2, and line L8 adds Fo(C) to Fo(A) because η2 is nullable.
In each case the last pass of the loop changed nothing, so the element is in Fo(A) when the loop stops.
Step 5: FOLLOW is sound when every nonterminal is reachable. Claim: each element added to Fo(A) is in FOLLOW(A). Induction on the order of the additions. Line L6 adds $ to Fo(S), and S$ itself shows $∈FOLLOW(S). Line L8 uses a production B→αAβ. Since B is reachable, S$⇒∗ρBτ for some ρ,τ. If a∈FIRST(β), then S$⇒∗ραAβτ⇒∗ραAaρ′τ. If β is nullable and b was added earlier to Fo(B), then b∈FOLLOW(B) by the induction hypothesis, so S$⇒∗ρ′Bbτ′, and ρ′Bbτ′⇒ρ′αAβbτ′⇒∗ρ′αAbτ′. In both cases the token is in FOLLOW(A). (Without reachability this step fails: a production of an unreachable B can add tokens to Fo(A). Step 4 does not use reachability.)
Step 6: the cells. Lines L3 to L6 add p=A→α to M[A,a] exactly when a∈FIRST(α), or α is nullable and a∈FOLLOW(A); by Steps 2 to 5 these are the true sets. That is the definition of a∈PREDICT(p), and no other line adds to a cell. So (T) holds. LOOKUP reads the cell at line L7 and returns error when it is empty (line L8), reports the conflict when it has two or more productions (line L9), and returns its only production otherwise (line L10).
So BUILD fills every cell as (T) says, and LOOKUP returns its content. ■