module PP.Templates.Lr
( LrContext
, context
) where
import Data.Char
import Data.Data
import qualified Data.List as L
import qualified Data.Map.Strict as Map
import Data.Maybe
import Data.Typeable
import PP.Builder
import PP.Rule
import PP.Template
import Text.StringTemplate
import Text.StringTemplate.GenericStandard
data LrContext = LrContext
{ states :: [LrContextState]
, terms :: [LrContextTerm]
, nonTerms :: [LrContextNonTerm]
, table :: LrContextTable
} deriving (Data, Typeable, Eq)
data LrContextState = LrContextState
{ id :: Int
, alt :: LrContextNonTerm
} deriving (Data, Typeable, Eq)
data LrContextTerm = LrContextTerm
{ symbol :: Char
, isEmpty :: Bool
} deriving (Data, Typeable, Eq)
data LrContextNonTerm = LrContextNonTerm
{ name :: String
, length :: Int
} deriving (Data, Typeable, Eq)
data LrContextTable = LrContextTable
{ rows :: [LrContextTableRow]
, total :: Int
} deriving (Data, Typeable, Eq)
data LrContextTableRow = LrContextTableRow
{ state :: LrContextState
, isTerm :: Bool
, term :: LrContextTerm
, nonTerm :: LrContextNonTerm
, action :: LrContextAction
} deriving (Data, Typeable, Eq)
data LrContextAction = LrContextAction
{ isReduce :: Bool
, isShift :: Bool
, isGoto :: Bool
, isError :: Bool
, isAccept :: Bool
, shift :: Int
, goto :: Int
, reduce :: LrContextNonTerm
} deriving (Data, Typeable, Eq)
context :: LrTable -> LrContext
context t = LrContext states' terms' nonTerms' table'
where
states' = L.nub [LrContextState i (nonTerm' Empty) | ((i, _), _) <- list']
terms' = term' Empty : L.nub [term' r | ((_, r), _) <- list', isTerm' r]
nonTerms' = L.nub [nonTerm' r | ((_, r), _) <- list', isNonTerm' r]
table' = LrContextTable rows'
(L.length states' * (L.length terms' + L.length nonTerms'))
rows' = [LrContextTableRow (LrContextState i (nonTerm' Empty))
(isTermOrEmpty' r)
(term' r)
(nonTerm' r)
(action' a)
| ((i, r), a) <- list']
term' (Term x) = LrContextTerm x False
term' Empty = LrContextTerm (chr 0) True
term' _ = LrContextTerm (chr 0) False
nonTerm' (NonTerm n) = LrContextNonTerm n (1)
nonTerm' _ = LrContextNonTerm "" (1)
action' (LrReduce (Rule n xs)) =
LrContextAction True False False False False (1) (1)
(LrContextNonTerm n (L.length xs 1))
action' (LrShift s) =
LrContextAction False True False False False s (1) (nonTerm' Empty)
action' (LrGoto s) =
LrContextAction False False True False False (1) s (nonTerm' Empty)
action' LrError =
LrContextAction False False False True False (1) (1) (nonTerm' Empty)
action' LrAccept =
LrContextAction False False False False True (1) (1) (nonTerm' Empty)
list' = Map.toList t
isTerm' (Term _) = True
isTerm' _ = False
isTermOrEmpty' (Term _) = True
isTermOrEmpty' Empty = True
isTermOrEmpty' _ = False
isNonTerm' (NonTerm _) = True
isNonTerm' _ = False
isReduce' (LrReduce _) = True
isReduce' _ = False
instance Template LrContext where
attributes = setAttribute "lr"