module TotalRecognisers.LeftRecursion.Lib (Tok : Set) where
open import Codata.Musical.Notation
open import Data.Bool hiding (_∧_; _≤_)
open import Data.Bool.Properties
open import Function hiding (_∋_)
open import Data.List
open import Data.Nat using (ℕ; zero; suc)
open import Data.Product as Prod
open import Relation.Binary
open import Relation.Binary.PropositionalEquality hiding ([_])
open import Relation.Nullary.Decidable
import TotalRecognisers.LeftRecursion
open TotalRecognisers.LeftRecursion Tok
infixr 5 _∷_
infix 4 _∈[_]⋆
data _∈[_]⋆ {n} : List Tok → P n → Set where
[] : ∀ {p} → [] ∈[ p ]⋆
_∷_ : ∀ {s₁ s₂ p} → s₁ ∈ p → s₂ ∈[ p ]⋆ → s₁ ++ s₂ ∈[ p ]⋆
module KleeneStar₁ where
infix 15 _⋆ _+
mutual
_⋆ : P false → P true
p ⋆ = empty ∣ p +
_+ : P false → P false
p + = p · ♯ (p ⋆)
⋆-sound : ∀ {s p} → s ∈ p ⋆ → s ∈[ p ]⋆
⋆-sound (∣-left empty) = []
⋆-sound (∣-right (pr₁ · pr₂)) = pr₁ ∷ ⋆-sound pr₂
⋆-complete : ∀ {s p} → s ∈[ p ]⋆ → s ∈ p ⋆
⋆-complete [] = ∣-left empty
⋆-complete (_∷_ {[]} pr₁ pr₂) = ⋆-complete pr₂
⋆-complete (_∷_ {_ ∷ _} pr₁ pr₂) =
∣-right {n₁ = true} (pr₁ · ⋆-complete pr₂)
module KleeneStar₂ where
infix 15 _⋆
_⋆ : ∀ {n} → P n → P true
_⋆ = KleeneStar₁._⋆ ∘ nonempty
⋆-sound : ∀ {s n} {p : P n} → s ∈ p ⋆ → s ∈[ p ]⋆
⋆-sound (∣-left empty) = []
⋆-sound (∣-right (nonempty pr₁ · pr₂)) = pr₁ ∷ ⋆-sound pr₂
⋆-complete : ∀ {s n} {p : P n} → s ∈[ p ]⋆ → s ∈ p ⋆
⋆-complete [] = ∣-left empty
⋆-complete (_∷_ {[]} pr₁ pr₂) = ⋆-complete pr₂
⋆-complete (_∷_ {_ ∷ _} pr₁ pr₂) =
∣-right {n₁ = true} (nonempty pr₁ · ⋆-complete pr₂)
infixl 10 _⊙_
_⊙_ : ∀ {n₁ n₂} → P n₁ → P n₂ → P (n₁ ∧ n₂)
_⊙_ {n₁ = n₁} p₁ p₂ = ♯? p₁ · ♯? {b = n₁} p₂
module ⊙ where
complete : ∀ {n₁ n₂ s₁ s₂} {p₁ : P n₁} {p₂ : P n₂} →
s₁ ∈ p₁ → s₂ ∈ p₂ → s₁ ++ s₂ ∈ p₁ ⊙ p₂
complete {n₁} {n₂} s₁∈p₁ s₂∈p₂ = add-♭♯ n₂ s₁∈p₁ · add-♭♯ n₁ s₂∈p₂
infixl 10 _⊙′_
infix 4 _⊙_∋_
data _⊙_∋_ {n₁ n₂} (p₁ : P n₁) (p₂ : P n₂) : List Tok → Set where
_⊙′_ : ∀ {s₁ s₂} (s₁∈p₁ : s₁ ∈ p₁) (s₂∈p₂ : s₂ ∈ p₂) →
p₁ ⊙ p₂ ∋ s₁ ++ s₂
sound : ∀ {n₁} n₂ {s} {p₁ : P n₁} {p₂ : P n₂} →
s ∈ p₁ ⊙ p₂ → p₁ ⊙ p₂ ∋ s
sound {n₁} n₂ (s₁∈p₁ · s₂∈p₂) = drop-♭♯ n₂ s₁∈p₁ ⊙′ drop-♭♯ n₁ s₂∈p₂
⟨_^_⟩-nullable : Bool → ℕ → Bool
⟨ n ^ zero ⟩-nullable = true
⟨ n ^ suc i ⟩-nullable = n ∧ ⟨ n ^ i ⟩-nullable
infixl 15 _^_
_^_ : ∀ {n} → P n → (i : ℕ) → P ⟨ n ^ i ⟩-nullable
p ^ 0 = empty
p ^ suc i = p ⊙ p ^ i
open KleeneStar₂
^≤⋆ : ∀ {n} {p : P n} i → p ^ i ≤ p ⋆
^≤⋆ {n} {p} i s∈ = ⋆-complete $ helper i s∈
where
helper : ∀ i {s} → s ∈ p ^ i → s ∈[ p ]⋆
helper zero empty = []
helper (suc i) (s₁∈p · s₂∈pⁱ) =
drop-♭♯ ⟨ n ^ i ⟩-nullable s₁∈p ∷ helper i (drop-♭♯ n s₂∈pⁱ)
⋆≤^ : ∀ {n} {p : P n} {s} → s ∈ p ⋆ → ∃ λ i → s ∈ p ^ i
⋆≤^ {n} {p} s∈p⋆ = helper (⋆-sound s∈p⋆)
where
helper : ∀ {s} → s ∈[ p ]⋆ → ∃ λ i → s ∈ p ^ i
helper [] = (0 , empty)
helper (s₁∈p ∷ s₂∈p⋆) =
Prod.map suc (λ {i} s₂∈pⁱ → add-♭♯ ⟨ n ^ i ⟩-nullable s₁∈p ·
add-♭♯ n s₂∈pⁱ)
(helper s₂∈p⋆)
module Tok (dec : Decidable (_≡_ {A = Tok})) where
tok : Tok → P false
tok t = sat (⌊_⌋ ∘ dec t)
sound : ∀ {s t} → s ∈ tok t → s ≡ [ t ]
sound (sat ok) = cong [_] $ sym $ toWitness ok
complete : ∀ {t} → [ t ] ∈ tok t
complete = sat (fromWitness refl)
accept-if-true : ∀ b → P b
accept-if-true true = empty
accept-if-true false = fail
module AcceptIfTrue where
sound : ∀ b {s} → s ∈ accept-if-true b → s ≡ [] × T b
sound true empty = (refl , _)
sound false ()
complete : ∀ {b} → T b → [] ∈ accept-if-true b
complete ok with Equivalence.to T-≡ ok
... | refl = empty