Algorithm Search⌘K

Proofs: Parse chart

These are the human proofs of Parse chart, at full length.

FILL adds exactly the sound edges, so READ decides membership and returns a parse tree full

This proof shows: correctness.

Statement. Let GG be any context-free grammar and w=a1⋯anw = a_1 \cdots a_n. Call an edge (i,j,A→α⋅β)(i, j, A \to \alpha \cdot \beta) sound if

(P) S⇒∗w[0:i] A δS \Rightarrow^* w[0:i] \, A \, \delta for some δ∈(V∪Σ)∗\delta \in (V \cup \Sigma)^*, and (D) α⇒∗w[i:j]\alpha \Rightarrow^* w[i:j].

When FILL stops, the chart contains exactly the sound edges. Consequently READ finds a complete edge (0,n,S→γ⋅)(0, n, S \to \gamma \cdot) if and only if w∈L(G)w \in L(G), and in that case following the backpointers terminates and yields a parse tree of ww. FILL itself stops, because there are at most ∣G∣(n+1)2|G| (n + 1)^2 edges and each is pushed on the agenda once.

Proof.

Step 1 (only sound edges). By induction on the order in which edges are added. L5 adds (0,0,S→⋅γ)(0, 0, S \to \cdot \gamma): (P) holds with δ=ε\delta = \varepsilon and (D) is ε⇒∗ε\varepsilon \Rightarrow^* \varepsilon. Prediction at L7, from a sound (i,j,A→α⋅Bβ′)(i, j, A \to \alpha \cdot B \beta'), adds (j,j,B→⋅γ)(j, j, B \to \cdot \gamma): from S⇒∗w[0:i]Aδ⇒w[0:i]αBβ′δ⇒∗w[0:j]Bβ′δS \Rightarrow^* w[0:i] A \delta \Rightarrow w[0:i] \alpha B \beta' \delta \Rightarrow^* w[0:j] B \beta' \delta we get (P), and (D) is trivial. The scan at L9 appends aj+1a_{j+1} to α\alpha, so (D) holds for w[i:j+1]w[i:j+1], and (P) is unchanged. The fundamental rule at L8 or L10 combines (i,j,A→α⋅Bβ′)(i, j, A \to \alpha \cdot B \beta') with (j,k,B→γ⋅)(j, k, B \to \gamma \cdot), both sound: αB⇒∗w[i:j]γ⇒∗w[i:j]w[j:k]=w[i:k]\alpha B \Rightarrow^* w[i:j] \gamma \Rightarrow^* w[i:j] w[j:k] = w[i:k], and (P) is that of the active edge.

Step 2 (the fundamental rule fires). Suppose the edges e′=(i,k,A→α′⋅Bβ)e' = (i, k, A \to \alpha' \cdot B \beta) and f=(k,j,B→γ⋅)f = (k, j, B \to \gamma \cdot) are both added. Each is pushed on the agenda once and popped later. If ff was added before e′e' is popped, L8 finds ff in COMPLETE(k,B)(k, B) when e′e' is popped. Otherwise e′e' was popped, hence added and put into WAITING(k,B)(k, B) at L3, before ff was added, and L10 finds e′e' when ff is popped. Either way (i,j,A→α′B⋅β)(i, j, A \to \alpha' B \cdot \beta) is added.

Step 3 (all sound edges). Let e=(i,j,A→α⋅β)e = (i, j, A \to \alpha \cdot \beta) be sound. Take a tree for the derivation in (P), with root SS and frontier w[0:i]Aδw[0:i] A \delta, and at its leaf AA attach a node xx with the children αβ\alpha \beta, where the children in α\alpha get the subtrees of a derivation α⇒∗w[i:j]\alpha \Rightarrow^* w[i:j] and the children in β\beta stay leaves. Call the result TT. In TT, every leaf to the left of the last child of α\alpha is a terminal or ε\varepsilon.

Walk TT depth first, from left to right, and record an event (y,0)(y, 0) when the walk enters an inner node yy and an event (y,d)(y, d) when it has finished the dd-th child of yy. Stop at the event (x,∣α∣)(x, |\alpha|). For each recorded event (y,d)(y, d), all leaves to the left of yy and all leaves below the first dd children of yy are terminals or ε\varepsilon: they lie to the left of the end of α\alpha in TT. So with ss the number of terminals to the left of yy and tt the number up to the end of the dd-th child, the event names the edge E(y,d)=(s,t,C→μ⋅ν)E(y, d) = (s, t, C \to \mu \cdot \nu), where C→μνC \to \mu \nu is the production of yy and ∣μ∣=d|\mu| = d. The last event names E(x,∣α∣)=eE(x, |\alpha|) = e. We show by induction along the walk that each named edge is added.

  • (y,0)(y, 0) for the root: yy is SS, s=0s = 0, and L5 adds (0,0,S→⋅γ)(0, 0, S \to \cdot \gamma).
  • (y,0)(y, 0) for a node yy that is the (d+1)(d + 1)-th child of its parent zz: the event (z,d)(z, d) came before, so E(z,d)E(z, d), whose dot is before the label of yy, is added, and when it is popped, prediction at L7 adds E(y,0)E(y, 0).
  • (y,d)(y, d) with d≥1d \ge 1 and a terminal dd-th child: the event (y,d−1)(y, d - 1) came before; when its edge is popped, the next input token is that terminal, and the scan at L9 adds E(y,d)E(y, d).
  • (y,d)(y, d) with d≥1d \ge 1 and a nonterminal dd-th child uu: this child lies to the left of the end of α\alpha, so it is an inner node, with a production B→γB \to \gamma; the events (y,d−1)(y, d - 1) and (u,∣γ∣)(u, |\gamma|) came before, so their edges (s,k,…⋅B…)(s, k, \ldots \cdot B \ldots) and (k,t,B→γ⋅)(k, t, B \to \gamma \cdot) are added, and by Step 2 the fundamental rule adds E(y,d)E(y, d).

So ee is added. Together with Step 1, the chart holds exactly the sound edges.

Step 4 (READ). A complete edge (0,n,S→γ⋅)(0, n, S \to \gamma \cdot) is sound iff γ⇒∗w\gamma \Rightarrow^* w for a production S→γS \to \gamma, that is, iff w∈L(G)w \in L(G); (P) holds trivially. By Steps 1 and 3, READ finds such an edge iff w∈L(G)w \in L(G). Every backpointer of an edge ee names edges that were already in the chart when ee was added, so the relation "is named by a backpointer of" is contained in the order of insertion and has no cycle; following backpointers from any edge reaches only finitely many edges and stops. For an edge built by L8, L9 or L10, the backpointer is the shorter edge for A→α′⋅XβA \to \alpha' \cdot X \beta and the child, a token or a complete edge for XX; for an edge built by L5 or L7, it is empty. Unfolding the chain of an edge (i,j,A→γ⋅)(i, j, A \to \gamma \cdot) therefore lists children X1,…,XmX_1, \ldots, X_m with γ=X1⋯Xm\gamma = X_1 \cdots X_m and consecutive spans from ii to jj, each a token equal to its terminal or a complete edge for its nonterminal. By induction on the insertion order, the tree built from (i,j,A→γ⋅)(i, j, A \to \gamma \cdot) is a parse tree with root AA and yield w[i:j]w[i:j], so the tree read from (0,n,S→γ⋅)(0, n, S \to \gamma \cdot) is a parse tree of ww. ■\blacksquare

Back to Parse chart