Langlib

Langlib.Grammars.LR.Equivalence.CanonicalParser

Correctness of the canonical LR table #

This file gives a small grammar-symbol-stack semantics for the canonical table. It separates the mathematical handle-pruning proof from the later finite-control/buffer simulation by the concrete DPDA.

Instances For
    Equations
    Instances For
      inductive CF_grammar.LRk.CanonicalParser.Step {T : Type} [Fintype T] (G : CF_grammar T) (k : ) :
      Config T GConfig T GProp

      One trusted table step. The suffix equation in the reduction constructor is not an extra parser test: on reachable kernels it follows from semantic item validity. Recording it here makes the handle-pruning invariant explicit.

      Instances For
        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          Equations
          • One or more equations did not get rendered due to their size.
          Instances For
            @[simp]
            theorem CF_grammar.LRk.CanonicalParser.lookaheadHead_observe_cons {T : Type} [Fintype T] (k : ) (hk : 0 < k) (a : T) (w : List T) :
            lookaheadHead k (observe k (a :: w)) = some a

            A convenient completed item naming a rule occurrence.

            Equations
            Instances For

              Fresh augmentation never inserts the fresh start symbol into an embedded right-hand side.

              No augmented production has the fresh start nonterminal in its right-hand side.

              A surviving occurrence of the fresh initial nonterminal can only be the untouched root configuration.

              A displayed rightmost prehandle exposes its production as a reduction in the canonical state at the completed handle boundary.

              Before a later displayed handle boundary, LR(k) conflict freedom forces the total table's default shift.

              theorem CF_grammar.LRk.CanonicalParser.shifts_to_handle {T : Type} [Fintype T] (G : CF_grammar T) (k : ) (hk : 0 < k) (hLR : G.IsLRk k) {r : RuleIndex G.augment} {p gamma : List (symbol T G.augment.nt)} {s x : List T} (hpre : G.augment.DerivesRightmost [symbol.nonterminal G.augment.initial] (p ++ [symbol.nonterminal (ruleAt G.augment r).1] ++ List.map symbol.terminal s)) (hboundary : p ++ (ruleAt G.augment r).2 = gamma ++ List.map symbol.terminal x) :
              Reaches G k { stack := gamma, input := x ++ s } { stack := p ++ (ruleAt G.augment r).2, input := s }

              A block of terminals before a displayed handle can be shifted without the table skipping an earlier reduction.

              theorem CF_grammar.LRk.CanonicalParser.split_at_handle_boundary {T : Type} [Fintype T] {N : Type} {gamma B : List (symbol T N)} {input s : List T} (hend : gamma = [] ∃ (p : List (symbol T N)) (A : N), gamma = p ++ [symbol.nonterminal A]) (heq : gamma ++ List.map symbol.terminal input = B ++ List.map symbol.terminal s) :
              ∃ (x : List T), B = gamma ++ List.map symbol.terminal x input = x ++ s

              Prefix/terminal-suffix comparison at a rightmost handle boundary.

              theorem CF_grammar.LRk.CanonicalParser.split_fresh_root {T : Type} [Fintype T] (G : CF_grammar T) {gamma : List (symbol T (Option G.nt))} {input : List T} (hend : gamma = [] ∃ (p : List (symbol T (Option G.nt))) (A : Option G.nt), gamma = p ++ [symbol.nonterminal A]) (heq : gamma ++ List.map symbol.terminal input = [symbol.nonterminal none]) :

              The only terminal-suffix split of the one-symbol fresh root whose prefix is empty or ends in a nonterminal is the root itself with empty suffix.

              Result of pruning a counted rightmost derivation: either the table has accepted, or the degenerate zero-step derivation has reached the fresh root.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                theorem CF_grammar.LRk.CanonicalParser.parses_back_of_derivesRightmostIn {T : Type} [Fintype T] (G : CF_grammar T) (k : ) (hk : 0 < k) (hLR : G.IsLRk k) {n : } {gamma : List (symbol T G.augment.nt)} {input : List T} (h : G.augment.DerivesRightmostIn n [symbol.nonterminal G.augment.initial] (gamma ++ List.map symbol.terminal input)) (hend : gamma = [] ∃ (p : List (symbol T G.augment.nt)) (A : G.augment.nt), gamma = p ++ [symbol.nonterminal A]) :
                BackOutcome G k { stack := gamma, input := input }

                Reverse a counted rightmost derivation by shifting up to each displayed handle and then taking the unique LR(k) reduction.

                The parser stack never contains the fresh augmented start nonterminal. That symbol is recognized by the accept action rather than pushed by a reduction.

                Equations
                Instances For
                  theorem CF_grammar.LRk.CanonicalParser.Step.freshFree {T : Type} [Fintype T] {G : CF_grammar T} {k : } {c d : Config T G} (h : Step G k c d) (hc : FreshFree c) :
                  theorem CF_grammar.LRk.CanonicalParser.Reaches.freshFree {T : Type} [Fintype T] {G : CF_grammar T} {k : } {c d : Config T G} (h : Reaches G k c d) (hc : FreshFree c) :
                  theorem CF_grammar.LRk.CanonicalParser.accepts_complete {T : Type} [Fintype T] (G : CF_grammar T) (k : ) (hk : 0 < k) (hLR : G.IsLRk k) {w : List T} (hw : w CF_language G) :
                  Accepts G k w

                  Every word generated by an LR(k) grammar is accepted by its canonical table (for positive lookahead).