module GLL.Parser (
gllSPPF
, charS, charT, nT, epsilon
, pNodeLookup, ParseResult(..)
) where
import Data.Foldable hiding (forM_, toList, sum)
import Prelude hiding (lookup, foldr, fmap, foldl, elem)
import Control.Monad
import Control.Applicative hiding (empty)
import Data.Map (Map(..), empty, insertWith, (!), toList, lookup)
import Data.Set (member, Set(..))
import qualified Data.IntMap as IM
import qualified Data.Map as M
import qualified Data.Array as A
import qualified Data.Set as S
import qualified Data.IntSet as IS
import GLL.Types.Abstract
import GLL.Types.Grammar
type Input = A.Array Int Token
type LhsParams = (Nt , Int , GSSNode)
type RhsParams = (Slot , Int , GSSNode)
type Rcal = [(RhsParams,SPPFNode)]
type Ucal = IM.IntMap (IM.IntMap (S.Set (Slot, GSlot)))
type GSS = IM.IntMap (M.Map GSlot [GSSEdge])
type GSSEdge = (GSSNode, SPPFNode)
type GSSNode = (GSlot, Int)
data GSlot = GSlot Slot
| U0
deriving (Ord, Eq)
type Pcal = IM.IntMap (Map GSlot [Int])
type Mutable = (SPPF,Rcal, Ucal, GSS, Pcal)
data GLL a = GLL (Mutable -> (a, Mutable))
addDescr :: SPPFNode -> RhsParams -> GLL ()
getDescr :: GLL (Maybe (RhsParams,SPPFNode))
addSPPFEdge :: SPPFNode -> SPPFNode -> GLL ()
addPop :: GSSNode -> Int -> GLL ()
getChildren :: GSSNode -> GLL [GSSEdge]
addGSSEdge :: GSSNode -> GSSEdge -> GLL ()
getPops :: GSSNode -> GLL [Int]
joinSPPFs :: Slot -> SPPFNode -> Int -> Int -> Int
-> GLL SPPFNode
runGLL :: GLL a -> Mutable -> Mutable
runGLL (GLL f) p = snd $ f p
addSPPFEdge f t = GLL $ \(sppf,r,u,gss,p) ->
((),
(
pMapInsert f t $
sppf
,r,u,gss,p))
addDescr sppf alt@(slot,i,(gs,l)) = GLL $ \(dv,r,u,gss,p) ->
let new = maybe True inner $ IM.lookup i u
where inner m = maybe True (not . ((slot,gs) `S.member`)) $ IM.lookup l m
newU = IM.alter inner i u
where inner mm = case mm of
Nothing -> Just $ IM.singleton l single
Just m -> Just $ IM.insertWith (S.union) l single m
single = S.singleton (slot,gs)
in if new then ((), (dv, (alt,sppf):r, newU, gss , p))
else ((), (dv, r, u, gss, p))
getDescr = GLL $ \(dv,r,u,gss,p) ->
case r of
[] -> (Nothing, (dv,r,u,gss,p))
(next@(alt,sppf):rest) ->
let res = (Just next, (dv,rest,u,gss,p))
in res
addPop (gs,l) i = GLL $ \(dv,r,u,gss,p) ->
let newP = IM.alter inner l p
where inner mm = case mm of
Nothing -> Just $ M.singleton gs [i]
Just m -> Just $ M.insertWith (++) gs [i] m
in ((), (dv,r,u,gss,newP))
getChildren (gs,l) = GLL $ \(dv,r,u,gss,p) ->
let res = maybe [] inner $ IM.lookup l gss
where inner m = maybe [] id $ M.lookup gs m
in (res, (dv,r,u,gss,p))
addGSSEdge f@(gs,i) t = GLL $ \(dv,r,u,gss,p) ->
let newGSS = IM.alter inner i gss
where inner mm = case mm of
Nothing -> Just $ M.singleton gs [t]
Just m -> Just $ M.insertWith (++) gs [t] m
in ((), (dv,r,u,newGSS,p))
getPops (gs,l) = GLL $ \ctx@(dv,r,u,gss,p) ->
let res = maybe [] inner $ IM.lookup l p
where inner = maybe [] id . M.lookup gs
in (res, ctx)
instance Show GSlot where
show (U0) = "u0"
show (GSlot gn) = show gn
instance Show SPPFNode where
show (SNode (s, l, r)) = "(s: " ++ show s ++ ", " ++ show l ++ ", " ++ show r ++ ")"
show (INode (s, l, r)) = "(i: " ++ show s ++ ", " ++ show l ++ ", " ++ show r ++ ")"
show (PNode (p, l, k, r)) = "(p: " ++ show p ++ ", " ++ show l ++ ", " ++ show k ++ ", " ++ show r ++ ")"
show Dummy = "$"
instance Applicative GLL where
(<*>) = ap
pure = return
instance Functor GLL where
fmap = liftM
instance Monad GLL where
return a = GLL $ \p -> (a, p)
(GLL m) >>= f = GLL $ \p -> let (a, p') = m p
(GLL m') = f a
in m' p'
gllSPPF :: Grammar -> [Token] -> ParseResult
gllSPPF grammar@(Grammar start _ _ ) input =
let (mutable,_,_,_) = gll m False grammar input
m = length input
in resultFromMutable mutable (Nt start, 0, m)
gll :: Int -> Bool -> Grammar -> [Token] -> (Mutable, [Alt], SelectMap, FollowMap)
gll m debug (Grammar start _ rules) input' =
(runGLL (pLhs (start, 0, (U0,0))) context, prs, selects, follows)
where
prs = [ alt | Rule _ alts <- rules, alt <- (reverse alts) ]
context = (emptySPPF, [], IM.empty, IM.empty, IM.empty)
input = A.array (0,m) $ zip [0..] $ input' ++ [EOS]
dispatch :: GLL ()
pLhs :: LhsParams -> GLL ()
pRhs :: RhsParams -> SPPFNode -> GLL ()
dispatch = do
mnext <- getDescr
case mnext of
Nothing -> return ()
Just (next,sppf) -> pRhs next sppf
pLhs (bigx, i, gn) = do
let alts = [ (Slot bigx [] beta, i, gn) | (Alt bigx beta) <- altsOf bigx
, select (input A.! i) beta bigx
]
forM_ alts (addDescr Dummy)
dispatch
pRhs (Slot bigx [] [Term Epsilon], i, (gs,l)) _ = do
root <- joinSPPFs slot Dummy l i i
pRhs (slot, i, (gs,l)) root
where slot = Slot bigx [Term Epsilon] []
pRhs (Slot bigx alpha ((Term tau):beta), i, (gs,l)) sppf =
if (input A.! i == tau)
then do
root <- joinSPPFs slot sppf l i (i+1)
pRhs (slot, i+1, (gs,l)) root
else
dispatch
where slot = Slot bigx (alpha++[Term tau]) beta
pRhs (Slot bigx alpha ((Nt bigy):beta), i, (gs, l)) sppf =
if (select (input A.! i) ((Nt bigy):beta) bigx)
then do
addGSSEdge ret ((gs,l), sppf)
rs <- getPops ret
forM_ rs $ \r -> do
root <- joinSPPFs slot sppf l i r
addDescr root (slot, r, (gs,l))
pLhs (bigy, i, ret)
else
dispatch
where ret = (GSlot slot, i)
slot = Slot bigx (alpha++[Nt bigy]) beta
pRhs (Slot bigy alpha [], i, (U0,0)) sppf = dispatch
pRhs (Slot bigy alpha [], i, gn@(GSlot slot,l)) ynode = do
addPop gn i
returns <- getChildren gn
forM_ returns $ \((gs',l'),sppf) -> do
root <- joinSPPFs slot sppf l' l i
addDescr root (slot, i, (gs',l'))
dispatch
(prodMap,_,_,follows,selects) = fixedMaps start prs
follow x = follows ! x
select t rhs x = t `member` (selects ! (x,rhs))
altsOf x = prodMap ! x
merge m1 m2 = IM.unionWith inner m1 m2
where inner = IM.unionWith S.union
joinSPPFs (Slot bigx alpha beta) sppf l k r =
case (sppf, beta) of
(Dummy, []) -> do addSPPFEdge xnode pnode
addSPPFEdge pnode snode
return xnode
(_, []) -> do addSPPFEdge xnode pnode
addSPPFEdge pnode sppf
addSPPFEdge pnode snode
return xnode
_ -> do addSPPFEdge inode pnode
addSPPFEdge pnode sppf
addSPPFEdge pnode snode
return inode
where x = last alpha
snode = SNode (x, k, r)
xnode = SNode (Nt bigx, l, r)
inode = INode ((Slot bigx alpha beta), l, r)
pnode = PNode ((Slot bigx alpha beta), l, k, r)
data ParseResult = ParseResult { sppf_result :: SPPF
, success :: Bool
, nr_descriptors :: Int
, nr_sppf_edges :: Int
, nr_gss_nodes :: Int
}
resultFromMutable :: Mutable -> SNode -> ParseResult
resultFromMutable (sppf@(_,_,_,eMap,_),_,u,gss,_) s_node =
ParseResult sppf success usize sppf_edges gsssize
where success = sppf `sNodeLookup` s_node
usize = sum [ S.size s | (l, r2s) <- IM.assocs u
, (r,s) <- IM.assocs r2s ]
sppf_edges = sum [ S.size ts | (_, ts) <- M.assocs eMap ]
gsssize = 1 + sum [ length $ M.keys x2s| (l,x2s) <- IM.assocs gss]
instance Show ParseResult where
show res = unlines $
[ "Success: " ++ show (success res)
, "Descriptors: " ++ show (nr_descriptors res)
, "SPPFEdges: " ++ show (nr_sppf_edges res)
, "GSSNodes: " ++ show (nr_gss_nodes res)
]