{- |
Module      : Control.Lens.Grammar.Symbol
Description : terminal & nonterminal symbols
Copyright   : (C) 2026 - Eitan Chatav
License     : BSD-style (see the file LICENSE)
Maintainer  : Eitan Chatav <eitan.chatav@gmail.com>
Stability   : provisional
Portability : non-portable
-}

module Control.Lens.Grammar.Symbol
  ( -- * Symbol
    TerminalSymbol (..)
  , NonTerminalSymbol (..)
  ) where

import Control.Lens
import Control.Lens.PartialIso
import Control.Lens.Grammar.Token
import Data.Profunctor
import Data.Profunctor.Monoidal

-- | A `terminal` symbol in a grammar.
class TerminalSymbol token s | s -> token where
  terminal :: [token] -> s
  default terminal
    :: (p () () ~ s, Tokenized token (p token token), Monoidal p, Cochoice p)
    => [token] -> s
  terminal = (token -> s -> s) -> s -> [token] -> s
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\token
a s
p -> token -> Prism' token ()
forall a. Eq a => a -> Prism' a ()
only token
a (Market () () () (Identity ())
 -> Market () () token (Identity token))
-> p token token -> p () ()
forall (p :: * -> * -> *) b a t s.
Cochoice p =>
APrism b a t s -> p a b -> p s t
?< p token token
forall token p. Tokenized token p => p
anyToken p () () -> p () () -> p () ()
forall a b. p () a -> p () b -> p () b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> s
p () ()
p) s
p () ()
forall (p :: * -> * -> *). Monoidal p => p () ()
oneP

-- | A `nonTerminal` symbol in a grammar.
class NonTerminalSymbol s where
  nonTerminal :: String -> s