module PP.Parsers.Lr
( LrConfig(..)
, LrAst(..)
, prettyAst
) where
import PP.Builder (LrAction (..), LrTable (..), action, action')
import PP.Lexer (OToken (..))
import PP.Parser (LrParser (..))
import PP.Rule (Rule (..))
data LrAst
= LrAstRoot [LrAst]
| LrAstTerm [OToken]
| LrAstNonTerm String [LrAst]
deriving (Eq, Show)
data LrConfig = LrConfig
{ lrCount :: Int
, lrStack :: [Int]
, lrAction :: LrAction
, lrInput :: [OToken]
, lrAst :: LrAst
} deriving (Eq, Show)
instance LrParser LrConfig where
config t i = LrConfig 0 [0] (action' t 0 i) i (LrAstRoot [])
next t (LrConfig c ss (LrShift s) (i:is) a) =
LrConfig (c + 1) (s : ss) (action' t s is) is (shift a i)
next t (LrConfig c ss (LrReduce (Rule r xs)) i a) =
LrConfig (c + 1) sr (action t m $ NonTerm r) i (reduce a r $ length xs 1)
where
sr@(m:_) = drop (length xs 1) ss
next t (LrConfig c ss (LrGoto s) i a) =
LrConfig (c + 1) (s : ss) (action' t s i) i a
next _ c = c
hasNext _ (LrConfig _ _ LrError _ _) = False
hasNext _ (LrConfig _ _ LrAccept _ _) = False
hasNext _ _ = True
shift :: LrAst -> OToken -> LrAst
shift (LrAstRoot xs) i = LrAstRoot $ xs ++ [LrAstTerm [i]]
reduce :: LrAst -> String -> Int -> LrAst
reduce (LrAstRoot xs) r l = LrAstRoot $ a ++ [LrAstNonTerm r b]
where
(a, b) = splitAt pos xs
pos = length xs l
prettyAst :: LrAst -> String
prettyAst (LrAstRoot a) = concatMap (prettyAst' 0) a
where
prettyAst' d (LrAstTerm t) = tab d ++ show t ++ "\n"
prettyAst' d (LrAstNonTerm r xs) =
tab d ++ r ++ "\n" ++ concatMap (prettyAst' $ d + 2) xs
tab d = replicate d ' ' ++ "|"