Spines of linear derivations #
A linear grammar derives a terminal word from a single nonterminal along a
single "spine": every sentential form has the shape
map terminal p ++ [nonterminal C] ++ map terminal s, until a terminal rule is
applied. This file reifies that spine as an inductive Spine, proves it sound
and complete with respect to grammar_derives, and equips it with the
bookkeeping (length, list of visited nonterminals, accumulated terminal counts)
needed for the linear pumping lemma.
Main declarations #
Spine— the caterpillar derivation from a nonterminal to a word.Spine.derives— soundness: a spine yields agrammar_derives.exists_spine— completeness: a linear derivation yields a spine.
A Spine g B w witnesses, for a linear grammar g, a derivation of the
terminal word w from the single nonterminal B, recorded as the chain of
rules applied along the unique nonterminal.
- last
{T : Type}
{g : grammar T}
(B : g.nt)
(m : List T)
(h : { input_L := [], input_N := B, input_R := [], output_string := List.map symbol.terminal m } ∈ g.rules)
: Spine g B m
The final step: a purely terminal rule
B → m. - cons {T : Type} {g : grammar T} (B C : g.nt) (u v m : List T) (h : { input_L := [], input_N := B, input_R := [], output_string := List.map symbol.terminal u ++ [symbol.nonterminal C] ++ List.map symbol.terminal v } ∈ g.rules) (rest : Spine g C m) : Spine g B (u ++ m ++ v)
Instances For
Soundness: a spine gives an actual derivation B ⇒* w.
Equations
- ⋯ = ⋯
Instances For
Completeness: every linear derivation is a spine #
From a terminal-only form, any derivation reaches only that same form.
A symbol list whose every element is a terminal is the image of a terminal word.
In a terminal sandwich map p ++ [nt C] ++ map s = u ++ [nt N'] ++ v, the
nonterminal is forced to line up: u = map p, N' = C, v = map s.
In a linear grammar, a transformation step from a terminal sandwich
map p ++ [nt C] ++ map s rewrites exactly the nonterminal C in place.
Completeness (general form): a linear derivation from a terminal sandwich
map p ++ [nt C] ++ map s to a terminal word map w factors through C.
Completeness: every linear derivation of a terminal word from a single
nonterminal B is witnessed by a spine.
Splitting a spine #
An upper bound on the number of terminals a single rule application produces.
Equations
- maxRuleLen g = List.foldr max 0 (List.map (fun (r : grule T g.nt) => r.output_string.length) g.rules)
Instances For
Every rule's output is no longer than maxRuleLen.
The result of splitting a spine B ⇒* w at a given depth: a top derivation
B ⇒* u·C·y and an inner spine C ⇒* wc, with w = u ++ wc ++ y.
- C : g.nt
- u : List T
- y : List T
- wc : List T
- hderiv : grammar_derives g [symbol.nonterminal B] (List.map symbol.terminal self.u ++ [symbol.nonterminal self.C] ++ List.map symbol.terminal self.y)
Instances For
Split a spine at depth k, peeling off the first k rule applications.
Equations
Instances For
One rule application produces at most maxRuleLen terminals.
Each additional step adds at most maxRuleLen terminals.
At full depth, cnt accounts for all but at most maxRuleLen symbols of the word.