module Data.Parser.Grempa.Parser.Driver
( driver
, resultDriver
, ReductionTree
) where
import Control.Applicative
import Data.Dynamic
import Data.List
import Data.Maybe
import Data.Parser.Grempa.Parser.Result
import Data.Parser.Grempa.Parser.Table
import qualified Data.Parser.Grempa.Grammar.Typed as T
import Data.Parser.Grempa.Grammar.Token
data ReductionTree s
= RTReduce RuleI ProdI [ReductionTree s]
| RTTerm s
deriving Show
rtToTyped :: Token s => (s' -> s) -> ProdFunFun -> ReductionTree s' -> Dynamic
rtToTyped unc _ (RTTerm s) = toDyn (unc s)
rtToTyped unc funs (RTReduce r p tree) = applDynFun fun l
where
l = map (rtToTyped unc funs) tree
fun = funs r p
driver :: Token s => (ActionFun s, GotoFun s, StateI) -> [s]
-> ParseResult s (ReductionTree s)
driver (actionf, gotof, start) input =
driver' [start] (map Tok input ++ [EOF]) [] [] (0 :: Integer)
where
driver' stack@(s:_) (a:rest) rt ests pos =
case actionf s a of
Shift t -> driver' (t : stack) rest (RTTerm (unTok a) : rt) [] (pos + 1)
Reduce rule prod len es -> driver' (got : stack') (a : rest) rt' (es ++ ests) pos
where
stack'@(t:_) = drop len stack
got = gotof t rule
rt' = RTReduce rule prod (reverse $ take len rt) : drop len rt
Accept -> Right $ head rt
Error es -> Left $ ParseError (nub $ es ++ ests) pos
driver' _ _ _ _ pos = Left $ InternalParserError pos
type RTParseResult s = ParseResult s (ReductionTree s)
resultDriver :: (Token s, Typeable a)
=> (s' -> s) -> ProdFunTable -> T.Grammar s a -> RTParseResult s' -> ParseResult s a
resultDriver unc funs _ rt = fromJust
<$> fromDynamic
<$> rtToTyped unc (prodFunToFun funs)
<$> either (Left . fmap unc) Right rt