ε-Free Indexed Grammars #
This file develops the stack-sensitive nullability infrastructure used by the normal-form pipeline. Nullability for indexed grammars depends on the current stack, so ε-elimination is organized around right-hand-side sublists whose deleted symbols are nullable at the stack they receive during expansion.
References #
- A. V. Aho, "Indexed grammars — an extension of context-free grammars", JACM 15(4), 1968.
A nonterminal A with stack σ is nullable if g can derive [] from
[indexed A σ].
Equations
- g.IsNullable A σ = g.Derives [IndexedGrammar.ISym.indexed A σ] []
Instances For
Generating the empty word is exactly nullability of the initial nonterminal with the empty stack.
In a no-ε indexed grammar, no single stacked nonterminal can derive the empty sentential form.
A nullable stacked nonterminal can be erased in any sentential context.
A one-step indexed rewrite of an appended sentential form rewrites either the left side or the right side of the append.
A terminal already present in a sentential form is still present after one indexed-grammar rewrite step. Indexed rules rewrite only one indexed nonterminal in its context.
A terminal already present in a sentential form is preserved by any indexed derivation.
A sentential form containing a terminal cannot derive the empty sentential form.
If a sentential form derives [], it contains no terminal.
A terminal RHS symbol appears as the corresponding terminal in any expansion.
Terminals in an expanded RHS come exactly from terminal RHS symbols.
If an expanded RHS can derive [], the original RHS contains no terminal symbols.
A sentential form whose every symbol is a nullable indexed nonterminal derives the empty sentential form.
If a sentential form derives [], every symbol in it is a nullable indexed nonterminal.
A sentential form derives [] exactly when all of its symbols are nullable indexed
nonterminals.
An expanded RHS derives [] exactly when every RHS symbol is a nonterminal nullable at
the stack it receives from the expansion.
Counted extraction for one nonterminal occurrence in an expanded RHS deriving [].
kept is obtained from rhs by deleting only RHS nonterminals that are nullable at
the stack they receive during expansion.
- nil {T : Type} {g : IndexedGrammar T} {σ : List g.flag} : g.NullableRhsSublist σ [] []
- keep {T : Type} {g : IndexedGrammar T} {σ : List g.flag} (s : IRhsSymbol T g.nt g.flag) {rhs kept : List (IRhsSymbol T g.nt g.flag)} (h : g.NullableRhsSublist σ rhs kept) : g.NullableRhsSublist σ (s :: rhs) (s :: kept)
- drop_none {T : Type} {g : IndexedGrammar T} {σ : List g.flag} {A : g.nt} {rhs kept : List (IRhsSymbol T g.nt g.flag)} (hnullable : g.IsNullable A σ) (h : g.NullableRhsSublist σ rhs kept) : g.NullableRhsSublist σ (IRhsSymbol.nonterminal A none :: rhs) kept
- drop_some {T : Type} {g : IndexedGrammar T} {σ : List g.flag} {A : g.nt} {f : g.flag} {rhs kept : List (IRhsSymbol T g.nt g.flag)} (hnullable : g.IsNullable A (f :: σ)) (h : g.NullableRhsSublist σ rhs kept) : g.NullableRhsSublist σ (IRhsSymbol.nonterminal A (some f) :: rhs) kept
Instances For
If an expanded RHS derives a terminal word, then the same word is derived by some sublist obtained by deleting only nullable RHS nonterminals. Nonempty terminal output keeps at least one RHS symbol.
Branch-wise strengthening of exists_nullableRhsSublist_derives_to_terminals: every
kept RHS symbol is assigned a nonempty terminal yield derived from that symbol.
Counted branch-wise RHS pruning. Besides deleting nullable RHS nonterminals, this records a counted terminal yield for every kept symbol, and the kept budgets together do not exceed the original derivation budget.
One epsilon-pruned step: apply an original rule, but keep only a nonempty RHS sublist whose deleted nonterminals are nullable at the stack used by the rule application.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Reflexive-transitive closure of epsilon-pruned indexed steps.
Equations
Instances For
Every nonempty generated word has a first start-rule expansion whose nullable deletions leave a nonempty RHS deriving the same word.
Every nonempty generated word has a complete derivation using only ε-pruned steps.
A pruned derivation from the start symbol can only end in a nonempty terminal word.
Semantic ε-elimination: pruned derivations from the start generate exactly the nonempty part of the original language.
First-step analysis for a nullable stacked nonterminal. Nullability is witnessed by a matching grammar rule whose expansion is nullable.
Nullability propagates backwards along a derivation.
If a non-consuming rule expands to a nullable sentential form, then its left-hand side is nullable at the same stack.
If a flag-consuming rule expands to a nullable sentential form, then its left-hand side is nullable when that flag is on top of the stack.
Rule-level characterization of nullable stacked nonterminals.
In a flag-separated grammar, nullability has three concrete sources: an explicit ε-rule, a non-consuming rule whose whole RHS is nullable at the inherited stack, or a pop rule whose single child is nullable after the pop.
A non-consuming rule whose expanded RHS is entirely nullable makes its LHS nullable.
A pop rule whose unique child is nullable after the pop makes its LHS nullable with the consumed flag on top of the stack.
In a flag-separated grammar, nullability is exactly generated by explicit ε-rules, non-consuming all-nullable RHSs, and pop rules whose child is nullable after the pop.
Empty-stack specialization of the flag-separated nullability equations.
Nonempty-stack specialization of the flag-separated nullability equations.
An explicit rule A → ε makes A nullable at every stack.
An explicit rule Af → ε makes A nullable at every stack whose top flag is f.
The semantic set of nullable stacked nonterminals.
Instances For
Finite unfoldings of the nullability equations, starting from no nullable states.
Equations
- g.NullableApprox 0 = ∅
- g.NullableApprox n.succ = g.NullableStep (g.NullableApprox n)
Instances For
A RHS sublist whose deletions are justified by one finite nullable approximation rank.
- nil {T : Type} {g : IndexedGrammar T} {n : ℕ} {σ : List g.flag} : g.ApproxNullableRhsSublist n σ [] []
- keep {T : Type} {g : IndexedGrammar T} {n : ℕ} {σ : List g.flag} (s : IRhsSymbol T g.nt g.flag) {rhs kept : List (IRhsSymbol T g.nt g.flag)} (h : g.ApproxNullableRhsSublist n σ rhs kept) : g.ApproxNullableRhsSublist n σ (s :: rhs) (s :: kept)
- drop_none {T : Type} {g : IndexedGrammar T} {n : ℕ} {σ : List g.flag} {A : g.nt} {rhs kept : List (IRhsSymbol T g.nt g.flag)} (hnullable : (A, σ) ∈ g.NullableApprox n) (h : g.ApproxNullableRhsSublist n σ rhs kept) : g.ApproxNullableRhsSublist n σ (IRhsSymbol.nonterminal A none :: rhs) kept
- drop_some {T : Type} {g : IndexedGrammar T} {n : ℕ} {σ : List g.flag} {A : g.nt} {f : g.flag} {rhs kept : List (IRhsSymbol T g.nt g.flag)} (hnullable : (A, f :: σ) ∈ g.NullableApprox n) (h : g.ApproxNullableRhsSublist n σ rhs kept) : g.ApproxNullableRhsSublist n σ (IRhsSymbol.nonterminal A (some f) :: rhs) kept
Instances For
Relative nullable summaries #
Nullability above an abstract suffix whose nullable nonterminals are given by base.
RelativeNullable g base α A means that A is nullable on α ++ σ for every suffix
σ whose nullable set is base.
- base {T : Type} {g : IndexedGrammar T} {base : Set g.nt} {A : g.nt} (hA : A ∈ base) : g.RelativeNullable base [] A
- empty_rule {T : Type} {g : IndexedGrammar T} {base : Set g.nt} {A : g.nt} {α : List g.flag} {r : IRule T g.nt g.flag} (hr : r ∈ g.rules) (hlhs : r.lhs = A) (hconsume : r.consume = none) (hrhs : r.rhs = []) : g.RelativeNullable base α A
- all_rule {T : Type} {g : IndexedGrammar T} {base : Set g.nt} {A : g.nt} {α : List g.flag} {r : IRule T g.nt g.flag} (hr : r ∈ g.rules) (hlhs : r.lhs = A) (hconsume : r.consume = none) (hrhs_ne : r.rhs ≠ []) (hterminal : ∀ (t : T), IRhsSymbol.terminal t ∉ r.rhs) (hall : ∀ (B : g.nt) (push : Option g.flag), IRhsSymbol.nonterminal B push ∈ r.rhs → g.RelativeNullable base (match push with | none => α | some f => f :: α) B) : g.RelativeNullable base α A
- pop_rule {T : Type} {g : IndexedGrammar T} {base : Set g.nt} {A B : g.nt} {f : g.flag} {α : List g.flag} {r : IRule T g.nt g.flag} (hr : r ∈ g.rules) (hlhs : r.lhs = A) (hconsume : r.consume = some f) (hrhs : r.rhs = [IRhsSymbol.nonterminal B none]) (hB : g.RelativeNullable base α B) : g.RelativeNullable base (f :: α) A
Instances For
Finite-summary ε-elimination skeleton #
Evaluate a finite stack summary. The transition step q f is the summary after
pushing flag f on top of a stack with summary q.
Equations
- IndexedGrammar.stackSummaryEval init step [] = init
- IndexedGrammar.stackSummaryEval init step (f :: σ) = step (IndexedGrammar.stackSummaryEval init step σ) f
Instances For
Annotate every stack flag with the summary of the suffix below it.
Equations
- IndexedGrammar.annotateStackWithSummary init step [] = []
- IndexedGrammar.annotateStackWithSummary init step (f :: σ) = (f, IndexedGrammar.stackSummaryEval init step σ) :: IndexedGrammar.annotateStackWithSummary init step σ
Instances For
A finite stack summary recognizes exactly the nullable stacks when nullable_sound and
nullable_complete are supplied later.
Instances For
Equations
Instances For
Equations
Instances For
A RHS symbol is droppable at summary state q when it is a nonterminal nullable at the
stack summary it receives.
Equations
- IndexedGrammar.SummaryDroppableRhsSymbol S q (IRhsSymbol.terminal a) = False
- IndexedGrammar.SummaryDroppableRhsSymbol S q (IRhsSymbol.nonterminal A none) = S.nullable A q
- IndexedGrammar.SummaryDroppableRhsSymbol S q (IRhsSymbol.nonterminal A (some f)) = S.nullable A (S.step q f)
Instances For
Equations
- One or more equations did not get rendered due to their size.
RHS sublist pruning justified by a finite stack summary.
- nil {T : Type} {g : IndexedGrammar T} {S : g.NullableStackSummary} {q : S.state} : SummaryNullableRhsSublist S q [] []
- keep {T : Type} {g : IndexedGrammar T} {S : g.NullableStackSummary} {q : S.state} (s : IRhsSymbol T g.nt g.flag) {rhs kept : List (IRhsSymbol T g.nt g.flag)} (h : SummaryNullableRhsSublist S q rhs kept) : SummaryNullableRhsSublist S q (s :: rhs) (s :: kept)
- drop {T : Type} {g : IndexedGrammar T} {S : g.NullableStackSummary} {q : S.state} {s : IRhsSymbol T g.nt g.flag} {rhs kept : List (IRhsSymbol T g.nt g.flag)} (hdrop : SummaryDroppableRhsSymbol S q s) (h : SummaryNullableRhsSublist S q rhs kept) : SummaryNullableRhsSublist S q (s :: rhs) kept
Instances For
Enumerate all summary-justified RHS prunings.
Equations
Instances For
Lift a kept RHS symbol into the summary grammar at current tail summary q. Pushed
flags are annotated with the summary below the pushed flag.
Equations
- IndexedGrammar.summaryLiftRhsSymbol S q (IRhsSymbol.terminal a) = IRhsSymbol.terminal a
- IndexedGrammar.summaryLiftRhsSymbol S q (IRhsSymbol.nonterminal A none) = IRhsSymbol.nonterminal (A, q) none
- IndexedGrammar.summaryLiftRhsSymbol S q (IRhsSymbol.nonterminal A (some f)) = IRhsSymbol.nonterminal (A, S.step q f) (some (f, q))
Instances For
Equations
- IndexedGrammar.summaryLiftRhs S q rhs = List.map (IndexedGrammar.summaryLiftRhsSymbol S q) rhs
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Instances For
Project an annotated-summary sentential symbol back to the original grammar.
Equations
Instances For
Equations
Instances For
Lift an original sentential symbol with the correct stack summary and annotated flags.
Equations
Instances For
Equations
Instances For
Semantic soundness of summary-justified RHS deletion at an actually matching stack summary.
Semantic completeness of summary-justified RHS deletion at an actually matching stack summary.
The annotated summary carried by a nonterminal agrees with the summary of its stack, and each stack flag remembers the summary of the suffix below it.
Equations
- IndexedGrammar.SummaryWellAnnotatedISym S (IndexedGrammar.ISym.terminal t) = True
- IndexedGrammar.SummaryWellAnnotatedISym S (IndexedGrammar.ISym.indexed A σ) = (A.2 = S.eval (List.map Prod.fst σ) ∧ σ = S.annotateStack (List.map Prod.fst σ))
Instances For
Equations
Instances For
Equations
- g.nullableSetAt σ = {A : g.nt | g.IsNullable A σ}
Instances For
Equations
- g.relativeNullableStepSet base f = {A : g.nt | g.RelativeNullable base [f] A}
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
A grammar is ε-free exactly when no stacked nonterminal is nullable.
If a grammar is already ε-free, it is an ε-free equivalent of itself.