Proofs: Shared packed parse forest
These are the human proofs of Shared packed parse forest, at full length.
The binarized shared packed parse forest represents every parse tree of the input exactly once, and its construction stops full
This proof shows: correctness, termination.
We use the notation of the context-free grammar page: productions , for the empty string, for the start symbol, for the input length and for the grammar size. The input is , and . The line numbers are those of BUILD-SPPF and EXPAND on the page.
For a production and , write for the item . Line L1 computes two sets:
- , the triples with a symbol, , and (for a terminal , this means and );
- , the triples with .
Lemma 1: the chart
The bottom-up agenda of line L1 computes exactly these sets.
Proof. The agenda adds for each token, for each production and position, from and , and from for a production of . Each rule keeps the meaning of the facts, so by induction on the order in which facts are added, every fact is true. Conversely, take a true fact. If it is with a nonterminal, take a parse tree for it, and if it is , take parse trees for over consecutive pieces of . Induction on the total number of nodes in these trees shows that the fact is added: the fact with comes from and , which have fewer nodes, and comes from with the same trees minus the root. Both rules fire whichever premise is found first, because a new prefix fact scans the completed facts already found and a new completed fact scans the prefix facts waiting for it. There are finitely many facts and each is processed once, so the agenda empties.
The trees of a node
The forest has symbol nodes , intermediate nodes with , and packed nodes. Lines L7, L8 and L11 give each packed node of a node an optional left child and an optional right child. We assign to each node a set of objects, defined as the least sets closed under the following rules (so every object is finite):
- a terminal symbol node has the one tree ;
- an intermediate node has the sequences , for a packed node of with left child and right child , a sequence of (or a tree of , read as a sequence of length one, when is a symbol node) and a tree of ;
- a nonterminal symbol node has the trees , the node with children , for each packed node of , where is the empty sequence for a packed node without children (line L7), a single tree of the right child when there is no left child (line L8), and as above otherwise.
We say that such a tree is represented at , and that the choice of one packed node at each node used is its witness.
Lemma 2: soundness
Every node that is created satisfies its fact: for a symbol node, for an intermediate node. Every tree represented at a symbol node is a parse tree with root and yield , and every sequence represented at an intermediate node is a list of parse trees with roots whose yields concatenate to .
Proof. The root is created at line L3 only when . Line L11 creates a left node and a right node only after line L10 has checked and , which are exactly their facts, and line L8 creates a node whose fact is , which holds because . The trees and sequences are built by the rules above, and induction on their size shows the claim: at line L11 the left part covers with the symbols , the right part covers with , and at a symbol node the packed nodes come from a production of with (line L5), so applies a production of the grammar.
Lemma 3: completeness
Every node that is created is expanded exactly once. If the symbol node is created and is a parse tree with root and yield , then is represented at .
Proof. NODE creates a node only if its key is new, and pushes it onto the work stack at the same moment; line L4 pops each pushed node once and expands it at line L5 or L6 (a terminal symbol node has nothing to expand). So each node is expanded exactly once, after which its packed nodes are final.
Now induction on the height of . If is a terminal, is represented. Otherwise the root of uses a production , and its children have yields with and . By Lemma 1, for every and . When is expanded, line L5 calls EXPAND for because .
- If , line L7 adds the packed node without children, which represents , that is .
- If , line L8 adds a packed node whose only child is the symbol node .
- If , the loop of line L9 reaches , and line L10 finds both facts, so line L11 adds a packed node with right child and left child when , or the intermediate node when . That intermediate node is created now or was created before, and in either case it is expanded once, with EXPAND for over , where the same argument with in place of applies.
Following the chain down to , every symbol node is a child of some packed node in the chain. Each has smaller height, so by induction is represented at ; then the rules for intermediate and symbol nodes put at the intermediate node for , and at .
Lemma 4: one witness per tree
Each tree represented at a node has exactly one witness below .
Proof. The packed nodes of one node are distinct pairs (production, split). Let be represented at the symbol node . The production at the root of fixes , and the yields of the children fix the boundaries . The packed node of in a witness must have production and split , the start of the yield of the last child (or when ), and the packed node of the intermediate node must have split . So the choices along the chain are forced, and by induction on the size of , so are the choices in the subtrees.
Theorem
BUILD-SPPF stops. The parse trees of with root are exactly the trees represented at the root node, each with exactly one witness. If the forest has no cycle, the number of parse trees is , where for a terminal node and over the packed nodes of (a missing child counts as 1). If the forest has a cycle, has infinitely many parse trees.
Proof. Termination: the keys of nodes are symbol triples, at most , and item triples, at most ; each node is expanded once (Lemma 3), and each expansion runs the loop of line L9 at most times. The two inclusions are Lemmas 2 and 3 for the root ; if , there is no tree and line L2 returns the empty forest, which is correct by Lemma 1.
For the count, Lemma 4 makes the map from witnesses to trees one to one, so the number of trees at equals the number of witnesses, and in an acyclic forest the witnesses below are counted by the recurrence for by induction in reverse topological order.
For a cycle: every node has at least one packed node and at least one represented tree, by Lemma 2 read backward and Lemma 3 (every created node satisfies its fact, and a true fact has a tree). A cycle passes through a symbol node , since the left child of an intermediate node is an intermediate node of smaller or a symbol node, so no cycle uses intermediate nodes only. Following the cycle from back to itself, and completing every other child with any of its trees, gives a context with represented at whenever is. Starting from any tree at , the trees are all different (each is larger than the previous one). Every node is reachable from the root, since it was created as a child of a node already in the forest; completing a path from the root to in the same way gives a context with a tree of whenever is represented at . The trees are distinct parse trees of . So has infinitely many parse trees, and for a nonterminal that covers a piece of .
Remarks
The operations. COUNT applies the recurrence in a postorder found by an explicit depth-first search, after a depth-first search that looks for a back edge. TREE unranks: at each node it walks the packed nodes, subtracting until the rank falls inside one, and splits the remaining rank into a quotient and a remainder for the two children; by Lemma 4 the ranks give each tree once. ONE-TREE also works for a cyclic forest: it marks a node as soon as one of its packed nodes has all its children marked, and uses that packed node. Each node is marked after all children of its chosen packed node, so the choices follow a well-founded order and the tree they describe is finite. CONTAINS recomputes the boundaries of a given tree and checks the forced witness of Lemma 4 node by node.
The size. There are symbol and intermediate nodes, and each node has at most packed nodes, so the forest has nodes and edges. The grammar on shows that this is tight in : it has packed nodes, while the number of trees is the Catalan number .