{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module Replace.Megaparsec.Internal.Text
(
sepCapText
, anyTillText
)
where
import Control.Monad
import qualified Data.Text as T
import Data.Text.Internal (Text(..))
import Text.Megaparsec
{-# INLINE [1] sepCapText #-}
sepCapText
:: forall e s m a. (MonadParsec e s m, s ~ T.Text)
=> m a
-> m [Either (Tokens s) a]
sepCapText sep = getInput >>= go
where
go restBegin@(Text tarray beginIndx beginLen) = do
(<|>)
( do
(Text _ _ thisLen) <- getInput
thisiter <- (<|>)
( do
x <- try sep
restAfter@(Text _ _ afterLen) <- getInput
when (afterLen >= thisLen) empty
pure $ Just (x, restAfter)
)
(anySingle >> pure Nothing)
case thisiter of
(Just (x, restAfter)) | thisLen < beginLen -> do
let unmatched = Text tarray beginIndx (beginLen - thisLen)
(Left unmatched:) <$> (Right x:) <$> go restAfter
(Just (x, restAfter)) -> do
(Right x:) <$> go restAfter
Nothing -> go restBegin
)
( do
if beginLen > 0 then
pure [Left restBegin]
else pure []
)
{-# INLINE [1] anyTillText #-}
anyTillText
:: forall e s m a. (MonadParsec e s m, s ~ T.Text)
=> m a
-> m (Tokens s, a)
anyTillText sep = do
(Text tarray beginIndx beginLen) <- getInput
(thisLen, x) <- go
pure (Text tarray beginIndx (beginLen - thisLen), x)
where
go = do
(Text _ _ thisLen) <- getInput
r <- optional $ try sep
case r of
Nothing -> anySingle >> go
Just x -> pure (thisLen, x)