module GLL.Combinators.Visit.Sem where
import GLL.Combinators.Options
import GLL.Types.Grammar
import GLL.Types.Derivations
import Control.Monad (forM)
import qualified Data.Array as A
import qualified Data.IntMap as IM
import qualified Data.Set as S
type Sem_Symb t a = PCOptions -> Ancestors t
-> SPPF t -> A.Array Int t -> Int -> Int -> IO [a]
type Sem_Alt t a = PCOptions -> (Prod t,Int) -> Ancestors t
-> SPPF t -> A.Array Int t -> Int -> Int -> IO [(Int,a)]
sem_nterm :: Bool -> Bool -> Nt -> [Prod t] -> [Sem_Alt t a] -> Sem_Symb t a
sem_nterm use_ctx left_biased x alts ps opts ctx sppf arr l r =
let ctx' = ctx `toAncestors` (x,l,r)
sems = zip alts ps
seq (alt@(Prod _ rhs), va3) =
va3 opts (alt,length rhs) ctx' sppf arr l r
in if use_ctx && ctx `inAncestors` (Nt x, l, r)
then return []
else do ass <- forM sems seq
let choices = case (pivot_select_nt opts, pivot_select opts) of
(True,Just compare) -> maintainWith compare ass
_ -> ass
return (concatChoice left_biased opts (map (map snd) choices))
where
concatChoice :: Bool -> PCOptions -> [[a]] -> [a]
concatChoice left_biased opts ress =
if left_biased || left_biased_choice opts
then firstRes ress
else concat ress
where firstRes [] = []
firstRes ([]:ress) = firstRes ress
firstRes (res:_) = res
sem_apply :: Ord t => (a -> b) -> Sem_Symb t a -> Sem_Alt t b
sem_apply f p opts (alt,j) ctx sppf arr l r =
let op f a = (r,f a)
in do as <- p opts ctx sppf arr l r
return (maybe [] (const (map (op f) as)) $ sppf `pNodeLookup` ((alt,1),l,r))
sem_seq :: Ord t => CombinatorOptions -> Sem_Alt t (a -> b) -> Sem_Symb t a -> Sem_Alt t b
sem_seq local_opts p q opts (alt@(Prod x rhs),j) ctx sppf arr l r =
let ks = maybe [] id $ sppf `pNodeLookup` ((alt,j), l, r)
choices = case pivot_select (runOptionsOn opts local_opts) of
Nothing -> ks
Just compare -> maximumsWith compare ks
seq k = do as <- q opts ctx' sppf arr k r
a2bs <- p opts (alt,j-1) ctx'' sppf arr l k
return [ (k,a2b a) | (_,a2b) <- a2bs, a <- as ]
where ctx' | k > l = emptyAncestors
| otherwise = ctx
ctx'' | k < r = emptyAncestors
| otherwise = ctx
in do ass <- forM choices seq
return (concat ass)
type Ancestors t = S.Set Nt
emptyAncestors :: Ancestors t
emptyAncestors = S.empty
inAncestors :: Ancestors t -> (Symbol t, Int, Int) -> Bool
inAncestors ctx (Term _, _, _) = False
inAncestors ctx (Nt x, l, r) = S.member x ctx
toAncestors :: Ancestors t -> (Nt, Int, Int) -> Ancestors t
toAncestors ctx (x, l, r) = S.insert x ctx