{-# LANGUAGE ScopedTypeVariables, DeriveAnyClass, DeriveGeneric
           , FlexibleContexts, UndecidableInstances, StandaloneDeriving
           , OverloadedStrings #-}
{-|
  Module      : Text.ANTLR.Allstar.ATN
  Description : Augmented recursive transition network algorithms
  Copyright   : (c) Karl Cronburg, 2018
  License     : BSD3
  Maintainer  : karl@cs.tufts.edu
  Stability   : experimental
  Portability : POSIX

-}
module Text.ANTLR.Allstar.ATN where
-- Augmented recursive Transition Network
import Text.ANTLR.Grammar
--import Text.ANTLR.Allstar.GSS hiding (Edge, Node)
import Text.ANTLR.Allstar.Stacks
import Text.ANTLR.Set (Set(..), empty, fromList, toList, Hashable, Generic)
import Text.ANTLR.Pretty

-- | Graph-structured stack over ATN states.
type Gamma nt = Stacks (ATNState nt)

-- | An ATN defining some language we wish to parse
data ATN s nt t = ATN
  {  :: Set (Transition s nt t) -- ^ The transition function
  } deriving (Eq, Ord, Show)

instance (Prettify s, Prettify nt, Prettify t, Hashable nt, Hashable t, Eq nt, Eq t) => Prettify (ATN s nt t) where
  prettify atn = do
    pLine "_Δ:"
    incrIndent 4
    prettify $  atn
    incrIndent (-4)

-- | Tuple corresponding to a distinct transition in the ATN:
type Transition s nt t = (ATNState nt, Edge s nt t, ATNState nt)

-- | The possible subscripts from Figure 8 of the ALL(*) paper
data ATNState nt  = Start  nt
                  | Middle nt Int Int
                  | Accept nt
  deriving (Eq, Generic, Hashable, Ord, Show)

-- | LaTeX style ATN states. TODO: check length of NT printed and put curly braces
-- around it if more than one character.
instance (Prettify nt) => Prettify (ATNState nt) where
  prettify (Start nt)  = pStr "p_"  >> prettify nt
  prettify (Accept nt) = pStr "p'_" >> prettify nt
  prettify (Middle nt i j) = do
    pStr "p_{"
    prettify i
    pStr ","
    prettify j
    pStr "}"

-- | An edge in an ATN.
data Edge s nt t =
    NTE nt              -- ^ Nonterminal edge
  | TE  t               -- ^ Terminal edge
  | PE  (Predicate ())  -- ^ Predicated edge with no state
  | ME  (Mutator   ())  -- ^ Mutator edge with no state
  | Epsilon             -- ^ Nondeterministic edge parsing nothing
  deriving (Eq, Generic, Hashable, Ord, Show)

instance (Prettify s, Prettify nt, Prettify t) => Prettify (Edge s nt t) where
  prettify x = do
    pStr "--"
    case x of
      NTE nt -> prettify nt
      TE   t -> prettify t
      PE   p -> prettify p
      ME   m -> prettify m
      Epsilon -> pStr "ε"
    pStr "-->"

-- | Convert a G4 grammar into an ATN for parsing with ALL(*)
atnOf
  :: forall nt t s. (Eq nt, Eq t, Hashable nt, Hashable t)
  => Grammar s nt t -> ATN s nt t
atnOf g = let

   :: Int -> Production s nt t -> [Transition s nt t]
   i (Production lhs rhs) = let
  --(Prod _α)) = let

    -- Construct an internal production state from the given ATN identifier
    st :: nt -> Int -> Int -> ATNState nt
    st = Middle

    -- Create the transition for the k^th production element in the i^th
    -- production:
    _Δ' :: Int -> ProdElem nt t -> Transition s nt t
    _Δ' k (NT nt) = (st lhs i (k - 1), NTE nt, st lhs i k)
    _Δ' k (T  t)  = (st lhs i (k - 1), TE  t,  st lhs i k)

    -- The epsilon (or mu) transition for the accepting / final state:
        = (Start lhs, Epsilon, Middle lhs i 0)
      = (Middle lhs i (length ), Epsilon, Accept lhs)

    sem_state  = Middle lhs i (length  + 1)
    sϵ_sem   = [(Start lhs, Epsilon, sem_state ), (sem_state , PE , Middle lhs i 0)]
    fϵ_sem       = 

    sϵ_mut    = 
    fϵ_mut  = (Middle lhs i 0, ME , Accept lhs)

    in  (case rhs of
          (Prod Pass )        -> [,  ]                 ++ zipWith _Δ' [1..(length )] 
          (Prod (Sem ) )    -> sϵ_sem   ++ [fϵ_sem ] ++ zipWith _Δ' [1..(length )] 
          (Prod (Action ) _)  -> [sϵ_mut, fϵ_mut ]
        )

  in ATN
    {  = fromList $ concat $ zipWith  [0..length (ps g)] $ ps g
    }