{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}

module Yi.IncrementalParse (recoverWith, symbol, eof, lookNext, testNext,
                            State, P, Parser(..), AlexState (..), scanner) where

import           Parser.Incremental (Parser (..), Process, eof, evalL, evalR,
                                     lookNext, mkProcess, pushEof, pushSyms,
                                     recoverWith, symbol, testNext)

import           Yi.Lexer.Alex      (AlexState (..))
import           Yi.Syntax          (Scanner (..))

type P s a = Parser s a

type State st token result = (st, Process token result)

scanner :: forall st token result. Parser token result -> Scanner st token -> Scanner (State st token result) result
scanner :: forall st token result.
Parser token result
-> Scanner st token -> Scanner (State st token result) result
scanner Parser token result
parser Scanner st token
input = Scanner
    {
      scanInit :: (st, Process token result)
scanInit = (Scanner st token -> st
forall st a. Scanner st a -> st
scanInit Scanner st token
input, Parser token result -> Process token result
forall s a. Parser s a -> Process s a
mkProcess Parser token result
parser),
      scanLooked :: (st, Process token result) -> Point
scanLooked = Scanner st token -> st -> Point
forall st a. Scanner st a -> st -> Point
scanLooked Scanner st token
input (st -> Point)
-> ((st, Process token result) -> st)
-> (st, Process token result)
-> Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (st, Process token result) -> st
forall a b. (a, b) -> a
fst,
      scanRun :: (st, Process token result)
-> [((st, Process token result), result)]
scanRun = (st, Process token result)
-> [((st, Process token result), result)]
run,
      scanEmpty :: result
scanEmpty = (result, [String]) -> result
forall a b. (a, b) -> a
fst ((result, [String]) -> result) -> (result, [String]) -> result
forall a b. (a -> b) -> a -> b
$ Process token result -> (result, [String])
forall token a rest. Zip token (a :< rest) -> (a, [String])
evalR (Process token result -> (result, [String]))
-> Process token result -> (result, [String])
forall a b. (a -> b) -> a -> b
$ Process token result -> Process token result
forall s r. Zip s r -> Zip s r
pushEof (Process token result -> Process token result)
-> Process token result -> Process token result
forall a b. (a -> b) -> a -> b
$ Parser token result -> Process token result
forall s a. Parser s a -> Process s a
mkProcess Parser token result
parser
    }
    where
        run :: State st token result -> [(State st token result, result)]
        run :: (st, Process token result)
-> [((st, Process token result), result)]
run (st
st,Process token result
process) = Process token result
-> [(st, token)] -> [((st, Process token result), result)]
updateState0 Process token result
process ([(st, token)] -> [((st, Process token result), result)])
-> [(st, token)] -> [((st, Process token result), result)]
forall a b. (a -> b) -> a -> b
$ Scanner st token -> st -> [(st, token)]
forall st a. Scanner st a -> st -> [(st, a)]
scanRun Scanner st token
input st
st


        updateState0 :: Process token result -> [(st,token)] -> [(State st token result, result)]
        updateState0 :: Process token result
-> [(st, token)] -> [((st, Process token result), result)]
updateState0 Process token result
_        [] = []
        updateState0 Process token result
curState toks :: [(st, token)]
toks@((st
st,token
tok):[(st, token)]
rest) = ((st
st, Process token result
curState), result
result) ((st, Process token result), result)
-> [((st, Process token result), result)]
-> [((st, Process token result), result)]
forall a. a -> [a] -> [a]
: Process token result
-> [(st, token)] -> [((st, Process token result), result)]
updateState0 Process token result
nextState [(st, token)]
rest
            where !nextState :: Process token result
nextState =       Process token result -> Process token result
forall s r. Zip s r -> Zip s r
evalL (Process token result -> Process token result)
-> Process token result -> Process token result
forall a b. (a -> b) -> a -> b
$           [token] -> Process token result -> Process token result
forall s r. [s] -> Zip s r -> Zip s r
pushSyms [token
tok]           Process token result
curState
                  result :: result
result    = (result, [String]) -> result
forall a b. (a, b) -> a
fst ((result, [String]) -> result) -> (result, [String]) -> result
forall a b. (a -> b) -> a -> b
$ Process token result -> (result, [String])
forall token a rest. Zip token (a :< rest) -> (a, [String])
evalR (Process token result -> (result, [String]))
-> Process token result -> (result, [String])
forall a b. (a -> b) -> a -> b
$ Process token result -> Process token result
forall s r. Zip s r -> Zip s r
pushEof (Process token result -> Process token result)
-> Process token result -> Process token result
forall a b. (a -> b) -> a -> b
$ [token] -> Process token result -> Process token result
forall s r. [s] -> Zip s r -> Zip s r
pushSyms (((st, token) -> token) -> [(st, token)] -> [token]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (st, token) -> token
forall a b. (a, b) -> b
snd [(st, token)]
toks) Process token result
curState