------------------------------------------------------------------------
-- Unambiguity
------------------------------------------------------------------------

module StructurallyRecursiveDescentParsing.Unambiguity where

open import Coinduction
open import Data.Bool
open import Data.List hiding (map)
open import Relation.Binary.PropositionalEquality
open import Relation.Binary.PropositionalEquality1 using (refl)

open import StructurallyRecursiveDescentParsing.Coinduction
open import StructurallyRecursiveDescentParsing.Parser
open import StructurallyRecursiveDescentParsing.Parser.Semantics
  hiding (sound; complete)

------------------------------------------------------------------------
-- Definition

-- A parser is unambiguous if it can yield at most one result for any
-- given input.
--
-- Note that this definition is a bit more general than the following
-- definition of unambiguity: "A grammar is unambiguous if there is at
-- most one parse tree which flattens to any given string."
--
-- Note also that this definition uses propositional equality, both
-- for the return values (x₁ and x₂) and for the input string (s). In
-- some cases other choices may be more useful.

Unambiguous :  {Tok R xs}  Parser Tok R xs  Set1
Unambiguous p =  {x₁ x₂ s}  x₁  p · s  x₂  p · s  x₁  x₂

------------------------------------------------------------------------
-- A more concrete characterisation of unambiguity

-- Note that this definition is inductive.

data Unambiguous′ {Tok} :  {R xs}  Parser Tok R xs  Set1 where
  return   :  {R} {x : R}  Unambiguous′ (return x)
  fail     :  {R}  Unambiguous′ (fail {R = R})
  token    : Unambiguous′ token
  choice   :  {R xs₁ xs₂} {p₁ : Parser Tok R xs₁} {p₂ : Parser Tok R xs₂}
             (u₁ : Unambiguous′ p₁) (u₂ : Unambiguous′ p₂) 
             (u :  {x₁ x₂ s}  x₁  p₁ · s  x₂  p₂ · s  x₁  x₂) 
             Unambiguous′ (p₁  p₂)
  map      :  {R₁ R₂ xs} {f : R₁  R₂} {p : Parser Tok R₁ xs}
             (u :  {x₁ x₂ s}  x₁  p · s  x₂  p · s  f x₁  f x₂) 
             Unambiguous′ (f <$> p)
  app      :  {R₁ R₂ fs} xs
               {p₁ : ∞? (Parser Tok (R₁  R₂) fs) xs}
               {p₂ : ∞? (Parser Tok R₁        xs) fs}
             (u :  {f₁ f₂ x₁ x₂ s s₁ s₂ s₃ s₄} 
                f₁  ♭? p₁ · s₁  x₁  ♭? p₂ · s₂  s₁ ++ s₂  s 
                f₂  ♭? p₁ · s₃  x₂  ♭? p₂ · s₄  s₃ ++ s₄  s 
                f₁ x₁  f₂ x₂) 
             Unambiguous′ (p₁  p₂)
  bind     :  {R₁ R₂ xs} {f : R₁  List R₂}
               {p₁ : Parser Tok R₁ xs}
               {p₂ : (x : R₁)  ∞? (Parser Tok R₂ (f x)) xs}
             (u :  {x₁ x₂ y₁ y₂ s s₁ s₂ s₃ s₄} 
                x₁  p₁ · s₁  y₁  ♭? (p₂ x₁) · s₂  s₁ ++ s₂  s 
                x₂  p₁ · s₃  y₂  ♭? (p₂ x₂) · s₄  s₃ ++ s₄  s 
                y₁  y₂) 
             Unambiguous′ (p₁ >>= p₂)
  bind′    :  {R₁ R₂ xs}
               {p₁ : ∞₁ (Parser Tok R₁ xs)}
               {p₂ : R₁  ∞? (Parser Tok R₂ []) xs}
             (u :  {x₁ x₂ y₁ y₂ s s₁ s₂ s₃ s₄} 
                x₁  ♭₁ p₁ · s₁  y₁  ♭? (p₂ x₁) · s₂  s₁ ++ s₂  s 
                x₂  ♭₁ p₁ · s₃  y₂  ♭? (p₂ x₂) · s₄  s₃ ++ s₄  s 
                y₁  y₂) 
             Unambiguous′ (p₁ >>=! p₂)
  nonempty :  {R xs} {p : Parser Tok R xs}
             (u :  {x₁ x₂ t s} 
                  x₁  p · t  s  x₂  p · t  s  x₁  x₂) 
             Unambiguous′ (nonempty p)
  cast     :  {R xs₁ xs₂} {eq : xs₁  xs₂} {p : Parser Tok R xs₁}
             (u : Unambiguous′ p)  Unambiguous′ (cast eq p)

-- The two definitions are equivalent.

sound :  {Tok R xs} {p : Parser Tok R xs} 
        Unambiguous′ p  Unambiguous p
sound return           return      return       = refl
sound fail             ()          ()
sound token            token       token        = refl
sound (choice u₁ u₂ u) (∣ˡ   x∈p₁) (∣ˡ    y∈p₁) =      sound u₁ x∈p₁ y∈p₁
sound (choice u₁ u₂ u) (∣ˡ   x∈p₁) (∣ʳ _  y∈p₂) =      u        x∈p₁ y∈p₂
sound (choice u₁ u₂ u) (∣ʳ _ x∈p₂) (∣ˡ    y∈p₁) = sym (u        y∈p₁ x∈p₂)
sound (choice u₁ u₂ u) (∣ʳ _ x∈p₂) (∣ʳ ._ y∈p₂) =      sound u₂ x∈p₂ y∈p₂
sound (map u)          (<$> x∈p)   (<$> y∈p)    = u x∈p y∈p
sound (app xs {p₁ = p₁} {p₂} u) x∈p y∈p = helper x∈p y∈p refl
  where
  helper :  {fx₁ fx₂ s₁ s₂} 
           fx₁  p₁  p₂ · s₁  fx₂  p₁  p₂ · s₂ 
           s₁  s₂  fx₁  fx₂
  helper (f∈p₁  x∈p₂) (f′∈p₁  x′∈p₂) eq =
    u f∈p₁ x∈p₂ eq f′∈p₁ x′∈p₂ refl
sound (bind   {p₁ = p₁} {p₂} u) x∈p y∈p = helper x∈p y∈p refl
  where
  helper :  {x₁ x₂ s₁ s₂} 
           x₁  p₁ >>= p₂ · s₁  x₂  p₁ >>= p₂ · s₂ 
           s₁  s₂  x₁  x₂
  helper (x∈p₁ >>= y∈p₂x) (x′∈p₁ >>= y′∈p₂x′) eq =
    u x∈p₁ y∈p₂x eq x′∈p₁ y′∈p₂x′ refl
sound (bind′  {p₁ = p₁} {p₂} u) x∈p y∈p = helper x∈p y∈p refl
  where
  helper :  {x₁ x₂ s₁ s₂} 
           x₁  p₁ >>=! p₂ · s₁  x₂  p₁ >>=! p₂ · s₂ 
           s₁  s₂  x₁  x₂
  helper (x∈p₁ >>=! y∈p₂x) (x′∈p₁ >>=! y′∈p₂x′) eq =
    u x∈p₁ y∈p₂x eq x′∈p₁ y′∈p₂x′ refl
sound (nonempty u) (nonempty x∈p) (nonempty y∈p) = u x∈p y∈p
sound (cast u)     (cast x∈p)     (cast y∈p)     = sound u x∈p y∈p

complete :  {Tok R xs} (p : Parser Tok R xs) 
           Unambiguous p  Unambiguous′ p
complete (return x)              _ = return
complete fail                    _ = fail
complete token                   _ = token
complete (_∣_ {xs₁ = xs₁} p₁ p₂) u = choice (complete p₁  x₁∈ x₂∈  u (∣ˡ     x₁∈) (∣ˡ     x₂∈)))
                                            (complete p₂  x₁∈ x₂∈  u (∣ʳ xs₁ x₁∈) (∣ʳ xs₁ x₂∈)))
                                             x₁∈ x₂∈  u (∣ˡ x₁∈) (∣ʳ xs₁ x₂∈))
complete (f <$> p)               u = map  x₁∈ x₂∈  u (<$> x₁∈) (<$> x₂∈))
complete (_⊛_ {xs = xs} p₁ p₂)   u = app xs  f₁∈ x₁∈ eq₁ f₂∈ x₂∈ eq₂ 
                                               u (cast∈ refl refl eq₁ (f₁∈  x₁∈))
                                                 (cast∈ refl refl eq₂ (f₂∈  x₂∈)))
complete (p₁ >>= p₂)             u = bind  x₁∈ y₁∈ eq₁ x₂∈ y₂∈ eq₂ 
                                             u (cast∈ refl refl eq₁ (_>>=_ {p₁ = p₁} x₁∈ y₁∈))
                                               (cast∈ refl refl eq₂ (_>>=_           x₂∈ y₂∈)))
complete (p₁ >>=! p₂)            u = bind′  x₁∈ y₁∈ eq₁ x₂∈ y₂∈ eq₂ 
                                              u (cast∈ refl refl eq₁ (_>>=!_ {p₁ = p₁} x₁∈ y₁∈))
                                                (cast∈ refl refl eq₂ (_>>=!_           x₂∈ y₂∈)))
complete (nonempty p)            u = nonempty  x₁∈ x₂∈  u (nonempty x₁∈) (nonempty x₂∈))
complete (cast refl p)           u = cast (complete p  x₁∈ x₂∈  u (cast x₁∈) (cast x₂∈)))