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 type for reduction trees output by the driver 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