{-# LINE 1 "templates/GLR_Lib.lhs" #-}
{-# LINE 1 "/tmp/ghc14613_0/ghc14613_0.lpp" #-}
{-# LINE 1 "<built-in>" #-}
{-# LINE 1 "<command-line>" #-}
{-# LINE 1 "/tmp/ghc14613_0/ghc14613_0.lpp" #-}
{-# LINE 1 "templates/GLR_Lib.lhs" #-}
 {-# LINE 1 "GLR_Lib.lhs" #-}






  {-
  Parser driver for the GLR parser.
  
  (c) University of Durham, Ben Medlock 2001
          -- initial code, for structure parsing
  (c) University of Durham, Paul Callaghan 2004-05
          -- extension to semantic rules
          -- shifting to chart data structure
          -- supporting hidden left recursion
          -- many optimisations
  -}






        -- probable, but might want to parametrise
            , doParse
            , TreeDecode(..), decode    -- only for tree decode
            , LabelDecode(..)           -- only for label decode

        -- standard exports
            , Tokens
            , GLRResult(..)
            , NodeMap
            , RootNode
            , ForestId
            , GSymbol(..)
            , Branch(..)
            , GSem(..)
            )
   where

 import Char
 import System


 import qualified Data.Map as Map







 import Monad (foldM)
 import Maybe (fromJust)
 import List (insertBy, nub, maximumBy, partition, find, groupBy, delete)






 {- these inserted by Happy -}

 fakeimport DATA



{-# LINE 94 "templates/GLR_Lib.lhs" #-}

{-# LINE 103 "templates/GLR_Lib.lhs" #-}



 doParse = glr_parse











 type Forest       = Map.Map ForestId [Branch]









 type NodeMap = [(ForestId, [Branch])]
 type RootNode = ForestId
 type Tokens = [[(Int, GSymbol)]]       -- list of ambiguous lexemes

 data GLRResult 
  = ParseOK     RootNode Forest    -- forest with root
  | ParseError  Tokens   Forest    -- partial forest with bad input
  | ParseEOF             Forest    -- partial forest (missing input)




 forestResult :: Int -> Forest -> GLRResult
 forestResult length f
  = case roots of
        []       -> ParseEOF f
        [r]      -> ParseOK r f
        rs@(_:_) -> error $ "multiple roots in forest, = " ++ show rs
                                                ++ unlines (map show ns_map)
    where

        ns_map = Map.toList f 



        roots = [ r | (r@(0,sz,sym),_) <- ns_map
                    , sz == length
                    , sym == top_symbol ]




 glr_parse :: [[UserDefTok]] -> GLRResult
 glr_parse toks 

  = case runST Map.empty [0..] (tp toks) of



     (f,Left ts)   -> ParseError ts f 
                                                -- Error within sentence
     (f,Right ss)  -> forestResult (length toks) f
                                                -- Either good parse or EOF
    where
        tp tss = doActions [initTS 0] 
               $ zipWith (\i ts -> [(i, t) | t <- ts]) [0..] 
               $ [ [ HappyTok {-j-} t | (j,t) <- zip [0..] ts ] | ts <- tss ]
                 ++ [[HappyEOF]]



 type PM a = ST Forest [Int] a
 type FStack = TStack ForestId





 doActions :: [FStack] -> Tokens -> PM (Either Tokens [FStack])

 doActions ss []                -- no more tokens (this is ok)
  = return (Right ss)           -- return the stacks (may be empty)

 doActions stks (tok:toks)
  = do
        stkss <- sequence [ do
                              stks' <- reduceAll [] tok_form stks 
                              shiftAll tok_form stks'
                          | tok_form <- tok ]
        let new_stks = merge $ concat stkss
        {- nothing -}

        case new_stks of            -- did this token kill stacks?
          [] -> case toks of
                  []  -> return $ Right []         -- ok if no more tokens
                  _:_ -> return $ Left (tok:toks)  -- not ok if some input left
          _  -> doActions new_stks toks

 reduceAll 
  :: [GSymbol] -> (Int, GSymbol) -> [FStack] -> PM [(FStack, Int)]
 reduceAll _ tok [] = return []
 reduceAll cyclic_names itok@(i,tok) (stk:stks)
  = do
      case action this_state tok of
        Accept      -> reduceAll [] itok stks
        Error       -> reduceAll [] itok stks
        Shift st rs -> do { ss <- redAll rs ; return $ (stk,st) : ss } 
        Reduce rs   -> redAll rs
  where 
   this_state = top stk
   redAll rs 
    = do 
        let reds = [ (bf fids,stk',m) 
                   | (m,n,bf) <- rs
                   , not (n == 0 && m `elem` cyclic_names)  -- remove done ones
                   , (fids,stk') <- pop n stk
                   ]
                   -- WARNING: incomplete if more than one Empty in a prod(!)
                   -- WARNING: can avoid by splitting emps/non-emps
        {- nothing -} 

        stks' <- foldM (pack i) stks reds       
        let new_cyclic = [ m | (m,0,_) <- rs
                             , (this_state ==  goto this_state m)
                             , m `notElem` cyclic_names ]
        reduceAll (cyclic_names ++ new_cyclic) itok $ merge stks' 

 shiftAll :: (Int, GSymbol) -> [(FStack, Int)] -> PM [FStack]
 shiftAll tok [] = return []
 shiftAll (j,tok) stks
  = do  
        let end = j + 1 
        let key = end `seq` (j,end,tok)
        newNode key
        let mss = [ (stk, st)
                  | ss@((_,st):_) <- groupBy (\a b -> snd a == snd b) stks
                  , stk <- merge $ map fst ss ]
        stks' <- sequence [ do { nid <- getID ; return (push key st nid stk) }
                          | (stk,(st)) <- mss ]
        return stks'


 pack 
  :: Int -> [FStack] -> (Branch, FStack, GSymbol) -> PM [FStack]

 pack e_i stks (fids,stk,m)
  | (st <  (0)) 
     = return stks
  | otherwise
     = do
        let s_i = endpoint stk
        let key = (s_i,e_i,m)
        {- nothing -}



 
        duplicate <- addBranch key fids
 
        let stack_matches = [ s | s <- stks
                                , (top s ==  st)
                                , let (k,s') = case ts_tail s of x:_ -> x
                                , stk == s'
                                , k == key
                                ]  -- look for first obvious packing site
        let appears_in = not $ null stack_matches
 
        {- nothing -}


        {- nothing -}





        if duplicate && appears_in
         then return stks       -- because already there
         else do
               nid <- getID
               case stack_matches of
                 []  -> return $ insertStack (push key st nid stk) stks
                                -- No prior stacks

                 s:_ -> return $ insertStack (push key st nid stk) (delete s stks)
                                -- pack into an existing stack
     where
        st = goto (top stk) m







 newNode :: ForestId -> PM ()
 newNode i

  = chgS $ \f -> ((), Map.insert i [] f)









 addBranch :: ForestId -> Branch -> PM Bool
 addBranch i b 
  = do
        f <- useS id

        case Map.lookup i f of 
          Nothing               -> chgS $ \f -> (False, Map.insert i [b] f)   
          Just bs | b `elem` bs -> return True
                  | otherwise   -> chgS $ \f -> (True,  Map.insert i (b:bs) f)









 getBranches ::  ForestId -> PM [Branch]
 getBranches i 

  = useS $ \s -> Map.findWithDefault no_such_node i s



    where
        no_such_node = error $ "No such node in Forest: " ++ show i








 (<>) x y = (x,y)  -- syntactic sugar








 data TStack a 
  = TS { top      :: Int           -- state
       , ts_id    :: Int           -- ID
       , stoup    :: !(Maybe a)         -- temp holding place, for left rec.
       , ts_tail  :: ![(a,TStack a)]    -- [(element on arc , child)] 
       }

 instance Show a => Show (TStack a) where
   show ts 
    = "St" ++ show ((top ts)) 












 instance Eq (TStack a) where
       s1 == s2 = (ts_id s1 ==  ts_id s2)








 insertStack :: TStack a -> [TStack a] -> [TStack a]
 insertStack = (:)



 initTS :: Int -> TStack a
 initTS (id) = TS (0) id Nothing []



 push :: ForestId -> Int -> Int -> TStack ForestId -> TStack ForestId
 push x@(s_i,e_i,m) st (id) stk 
  = TS st id stoup [(x,stk)] 
    where
        -- only fill stoup for cyclic states that don't consume input
        stoup | s_i == e_i && (st ==  goto st m) = Just x       
              | otherwise                        = Nothing



 pop :: Int -> TStack a -> [([a],TStack a)] 
 pop 0 ts = [([],ts)]
 pop 1 st@TS{stoup=Just x}
  = pop 1 st{stoup=Nothing} ++ [ ([x],st) ] 
 pop n ts = [ (xs ++ [x] , stk')
            | (x,stk) <- ts_tail ts
            , (xs,stk') <- pop (n-1) stk ] 



 popF :: TStack a -> TStack a 
 popF ts = case ts_tail ts of (_,c):_ -> c



 endpoint stk
  = case ts_tail stk of
      [] -> 0
      ((_,e_i,_),_):_ -> e_i





 merge :: (Eq a, Show a) => [TStack a] -> [TStack a]
 merge stks
  = [ TS st id ss (nub ch)
    | (st) <- nub (map (\s -> (top s)) stks)
    , let ch  = concat  [ x | TS st2 _ _ x <- stks, (st == st2) ]
          ss  = mkss    [ s | TS st2 _ s _ <- stks, (st == st2) ]
          (id) = head [ (i) | TS st2 i _ _ <- stks, (st == st2) ]
          -- reuse of id is ok, since merge discards old stacks
    ]
    where
         mkss s = case nub [ x | Just x <- s ] of
                    []  -> Nothing
                    [x] -> Just x
                    xs  -> error $ unlines $ ("Stoup merge: " ++ show xs) 
                                           : map show stks








 data ST s i a = MkST (s -> i -> (a,s,i))

 instance Functor (ST s i) where
  fmap f (MkST sf) 
   = MkST $ \s i -> case sf s i of (a,s',i') -> (f a,s',i')

 instance Monad (ST s i) where
  return a = MkST $ \s i -> (a,s,i)
  MkST sf >>= k
   = MkST $ \s i ->
        case sf s i of
         (a,s',i') -> let (MkST sf') = k a in  sf' s' i' 

 runST :: s -> i -> ST s i a -> (s,a)
 runST s i (MkST sf) = case sf s i of
                           (a,s,_) -> (s,a)

 chgS :: (s -> (a,s)) -> ST s i a
 chgS sf = MkST $ \s i -> let (a,s') = sf s in (a,s',i)

 useS :: (s -> b) -> ST s i b
 useS fn = MkST $ \s i -> (fn s,s,i)

 getID :: ST s [Int] Int
 getID = MkST $ \s (i:is) -> (i,s,is)

