module GLL.Combinators.Combinators (
parse,
parseString,
char,
epsilon,
(<$>),
(<$),
(<*>),
(<*),
(<::=>)
) where
import Prelude hiding ((<*>),(<*),(<$>),(<$))
import GLL.Common
import GLL.Types.Grammar hiding (epsilon)
import GLL.Types.Abstract
import GLL.Machines.RGLL (gllSPPF, pNodeLookup)
import Control.Monad
import qualified Data.IntMap as IM
import qualified Data.Map as M
import qualified Data.Set as S
type SymbVisit1 b = Symbol
type SymbVisit2 b = M.Map Nt [Alt] -> M.Map Nt [Alt]
type SymbVisit3 b = Int -> ParseContext -> SPPF -> Int -> Int -> [b]
type IMVisit1 b = [Symbol]
type IMVisit2 b = M.Map Nt [Alt] -> M.Map Nt [Alt]
type IMVisit3 b = Int -> ParseContext -> SPPF -> (Alt,Int) -> Int -> Int -> [b]
type ParseContext = IM.IntMap (IM.IntMap (S.Set Nt))
type SymbParser b = (SymbVisit1 b,SymbVisit2 b, SymbVisit3 b)
type IMParser b = (IMVisit1 b, IMVisit2 b, IMVisit3 b)
parseString :: (Show a) => SymbParser a -> String -> [a]
parseString p = parse p . map Char
parse :: (Show a) => SymbParser a -> [Token] -> [a]
parse (vpa1,vpa2,vpa3) input =
let snode = (start, 0, m)
m = length input
start = vpa1
rules = vpa2 M.empty
as = vpa3 (length input) IM.empty sppf 0 m
grammar = case start of
Nt x -> Grammar x [] [ Rule x alts [] | (x, alts) <- M.assocs rules ]
Term t -> Grammar "S" [] [Rule "S" [Alt "S" [start]] []]
Error _ _ -> error "can not parse error"
sppf = gllSPPF grammar input
in as
inParseContext :: ParseContext -> (Symbol, Int, Int) -> Bool
inParseContext ctx (Nt x, l, r) = maybe False inner $ IM.lookup l ctx
where inner = maybe False (S.member x) . IM.lookup r
toParseContext :: ParseContext -> (Nt, Int, Int) -> ParseContext
toParseContext ctx (x, l, r) = IM.alter inner l ctx
where inner mm = case mm of
Nothing -> Just $ singleRX
Just m -> Just $ IM.insertWith (S.union) r singleX m
singleRX = IM.singleton r singleX
singleX = S.singleton x
memoParser :: SymbParser a -> SymbParser a
memoParser (v1,v2,v3) = (v1,v2,v3')
where v3' m pctx sppf l r = (table IM.! l) IM.! r
where table = IM.fromAscList
[ (l', rMap) | l' <- [0..m]
, let rMap = IM.fromAscList [ (r',v) | r' <- [0..m]
, let v = v3 m pctx sppf l' r' ]]
mkParser :: String -> [IMParser a] -> SymbParser a
mkParser x altPs =
let vas1 = [ va1 | va1 <- map (\(f,_,_) -> f) altPs ]
alts = map (Alt x) vas1
in (Nt x
,\rules ->
if x `M.member` rules
then rules
else foldr ($) (M.insert x alts rules) $ (map (\(_,s,_) -> s) altPs)
,\m ctx sppf l r ->
let ctx' = ctx `toParseContext` (x,l,r)
vas2 = [ va3 m ctx' sppf (alt,length rhs) l r
| (alt@(Alt _ rhs), va3) <- zip alts (map (\(_,_,t) -> t) altPs) ]
in if ctx `inParseContext` (Nt x, l, r)
then []
else concat vas2
)
infix 5 <::=>
(<::=>) = mkParser
infixl 4 <*>
(<*>) :: IMParser (a -> b) -> SymbParser a -> IMParser b
(vimp1,vimp2,vimp3) <*> (vpa1,vpa2,vpa3) =
(vimp1++[vpa1]
,\rules ->
let rules1 = vpa2 rules
rules2 = vimp2 rules1
in rules2
,\m ctx sppf (alt@(Alt x rhs),j) l r ->
let ks = maybe [] id $ sppf `pNodeLookup` ((alt,j), l, r)
in [ a2b a | k <- ks, a <- vpa3 m ctx sppf k r, a2b <- vimp3 m ctx sppf (alt,j1) l k ]
)
infixl 4 <*
(<*) :: IMParser b -> SymbParser a -> IMParser b
(vimp1,vimp2,vimp3) <* (vpa1,vpa2,vpa3) =
(vimp1++[vpa1]
,\rules ->
let rules1 = vpa2 rules
rules2 = vimp2 rules1
in rules2
,\m ctx sppf (alt@(Alt x rhs),j) l r ->
let ks = maybe [] id $ sppf `pNodeLookup` ((alt,j), l, r)
in [ b | k <- ks, a <- vpa3 m ctx sppf k r, b <- vimp3 m ctx sppf (alt,j1) l k ]
)
infixl 4 <$>
(<$>) :: (a -> b) -> SymbParser a -> IMParser b
f <$> (vpa1,vpa2,vpa3) =
([vpa1]
,\rules ->
vpa2 rules
,\m ctx sppf (alt,j) l r ->
let a = vpa3 m ctx sppf l r
in maybe [] (const (map f a)) $ sppf `pNodeLookup` ((alt,1),l,r)
)
infixl 4 <$
(<$) :: b -> SymbParser a -> IMParser b
f <$ (vpa1,vpa2,vpa3) =
([vpa1]
,\rules ->
vpa2 rules
,\m ctx sppf (alt,j) l r ->
let a = vpa3 m ctx sppf l r
in maybe [] (const (map (const f) a)) $ sppf `pNodeLookup` ((alt,1),l,r)
)
char :: Char -> SymbParser Char
char c = (charT c, id,\_ _ _ _ _ -> [c])
epsilon :: SymbParser ()
epsilon = (Term Epsilon, id ,\_ _ _ _ _ -> [()])