{-# LANGUAGE AllowAmbiguousTypes #-} -- For grammar
{-# LANGUAGE ConstraintKinds #-} -- For Grammarable
module Symantic.Parser.Grammar
  ( module Symantic.Parser.Grammar
  , module Symantic.Parser.Grammar.Combinators
  , module Symantic.Parser.Grammar.Optimize
  , module Symantic.Parser.Grammar.ObserveSharing
  , module Symantic.Parser.Grammar.Production
  , module Symantic.Parser.Grammar.Write
  , module Symantic.Parser.Grammar.View
  , Referenceable(..)
  , Letsable(..)
  ) where
import Symantic.Parser.Grammar.Combinators
import Symantic.Parser.Grammar.ObserveSharing
import Symantic.Parser.Grammar.Optimize
import Symantic.Parser.Grammar.Production
import Symantic.Parser.Grammar.View
import Symantic.Parser.Grammar.Write

import Control.DeepSeq (NFData)
import Data.Eq (Eq)
import Data.Ord (Ord)
import Data.Function ((.))
import Data.String (String)
import Data.Typeable (Typeable)
import Text.Show (Show(..))
import Language.Haskell.TH.HideName
import qualified Language.Haskell.TH.Syntax as TH

-- * Type 'Grammar'
type Grammar repr = ObserveSharing TH.Name (OptimizeGrammar repr)

-- ** Class 'Grammarable'
type Grammarable tok repr =
  ( CombAlternable repr
  , CombApplicable repr
  , CombFoldable repr
  , Referenceable TH.Name repr
  , Letsable TH.Name repr
  , CombLookable repr
  , CombMatchable repr
  , CombSatisfiable tok repr
  , CombSelectable repr
  --, CombRegisterable repr
  , CombRegisterableUnscoped repr
  , Eq tok
  , Ord tok
  , TH.Lift tok
  , NFData tok
  , Show tok
  , Typeable tok
  )

-- | A usual pipeline to interpret 'Comb'inators:
-- 'observeSharing' then 'optimizeGrammar' then a polymorphic @(repr)@.
grammar :: Grammarable tok repr => Grammar repr a -> repr a
grammar = optimizeGrammar . observeSharing

-- | An usual pipeline to show 'Comb'inators:
-- 'observeSharing' then 'optimizeGrammar' then 'viewGrammar' then 'show'.
showGrammar :: forall showName a tok.
  HideableName showName =>
  Grammarable tok (Grammar (ViewGrammar showName)) =>
  Grammar (ViewGrammar showName) a -> String
showGrammar = show . viewGrammar . grammar @tok