Productive nonempty list positions #
A leftmost zero-visible trace remembers the boundary between the stack text displayed by a characteristic list nonterminal and its hidden zipper context. This module records the corresponding uniqueness fact for a nonempty list head. It is deliberately boundary-sensitive: equality of the underlying PDA stack would not suffice for the recursive split-right synchronization proof.
Two productive zero-visible traces from a common structural position to nonempty list positions with the same control state and exposed top symbol have equal exact positions, including the displayed/context boundary.
Split-right children with a common selected word inherit exact-position synchronization from the last-visible anchors of their two parent spines.
The common single source top middle consumes the same word on both sides.
Consequently each productive child future extends to a productive parent
future on leftWord ++ future. Boundary-sensitive synchronization of the
two parent zero-visible tails then identifies both displayed parent stacks
and both hidden contexts, which immediately identifies the split-right
children.
Nullable specialization of
splitRight_positions_eq_of_parent_anchor_position_eq.
The irreducible branch left after recursively peeling nullable paired
split-right markers. At least one selected single source top middle
completion consumes a nonempty terminal word. Both concrete parent spines,
their exact split rules, and the productive child futures are retained for
the terminal-extension argument.
- mk {Q T S : Type} [Fintype Q] [Fintype T] [Fintype S] {M : DPDA Q T S} {base : List (symbol T (Nonterminal M))} {completedWord beforeWord₁ leftWord₁ beforeWord₂ leftWord₂ suffix₁ suffix₂ future₁ future₂ : List T} {context₁ context₂ : List (StackSymbol M)} {source middle target₁ target₂ final₁ final₂ : State M} {top : StackSymbol M} {gamma₁ gamma₂ : List (StackSymbol M)} (parent₁ : ConcreteOperationalSpine M base (PDA_to_CFG.N.list source (top :: gamma₁) target₁) suffix₁ beforeWord₁ context₁) (length₁ : ↑(top :: gamma₁).length ≤ PDA_to_CFG.max_push (emptyStackPDA M)) (rule₁ : (PDA_to_CFG.N.list source (top :: gamma₁) target₁, [symbol.nonterminal (PDA_to_CFG.N.single source top middle), symbol.nonterminal (PDA_to_CFG.N.list middle gamma₁ target₁)]) ∈ (characteristicGrammar M).rules) (left₁ : (characteristicGrammar M).DerivesRightmost [symbol.nonterminal (PDA_to_CFG.N.single source top middle)] (List.map symbol.terminal leftWord₁)) (parent₂ : ConcreteOperationalSpine M base (PDA_to_CFG.N.list source (top :: gamma₂) target₂) suffix₂ beforeWord₂ context₂) (length₂ : ↑(top :: gamma₂).length ≤ PDA_to_CFG.max_push (emptyStackPDA M)) (rule₂ : (PDA_to_CFG.N.list source (top :: gamma₂) target₂, [symbol.nonterminal (PDA_to_CFG.N.single source top middle), symbol.nonterminal (PDA_to_CFG.N.list middle gamma₂ target₂)]) ∈ (characteristicGrammar M).rules) (left₂ : (characteristicGrammar M).DerivesRightmost [symbol.nonterminal (PDA_to_CFG.N.single source top middle)] (List.map symbol.terminal leftWord₂)) (word₁ : completedWord = beforeWord₁ ++ leftWord₁) (word₂ : completedWord = beforeWord₂ ++ leftWord₂) (nonnullable : leftWord₁ ≠ [] ∨ leftWord₂ ≠ []) (useful₁ : PDA.Reaches { state := middle, input := future₁, stack := gamma₁ ++ context₁ } { state := final₁, input := [], stack := [] }) (useful₂ : PDA.Reaches { state := middle, input := future₂, stack := gamma₂ ++ context₂ } { state := final₂, input := [], stack := [] }) (lookahead : List.take 1 future₁ = List.take 1 future₂) : ProductiveNonnullablePairedSplitResidual M
Instances For
Productive paired visible anchors synchronize exactly after recursively
peeling split-right markers whose selected single completes on ε.
The only branch not discharged by this shorter-frontier recursion is the
explicit nonnullable split residual above.