\begin{code}
{-# LANGUAGE NoImplicitPrelude          #-}

module Text.RE.ZeInternals.Tools.Lex
  ( alex
  , alex'
  ) where

import           Prelude.Compat
import           Text.RE.Replace
import           Text.RE.ZeInternals.Types.IsRegex
\end{code}


\begin{code}
-- | a simple regex-based scanner interpretter for prototyping
-- scanners
alex :: IsRegex re s => [(re,Match s->Maybe t)] -> t -> s -> [t]
alex :: [(re, Match s -> Maybe t)] -> t -> s -> [t]
alex = (re -> s -> Match s) -> [(re, Match s -> Maybe t)] -> t -> s -> [t]
forall s re t.
Replace s =>
(re -> s -> Match s) -> [(re, Match s -> Maybe t)] -> t -> s -> [t]
alex' re -> s -> Match s
forall re s. IsRegex re s => re -> s -> Match s
matchOnce

-- | a higher order version of 'alex' parameterised over the @matchOnce@
-- function
alex' :: Replace s
      => (re->s->Match s)
      -> [(re,Match s->Maybe t)]
      -> t
      -> s
      -> [t]
alex' :: (re -> s -> Match s) -> [(re, Match s -> Maybe t)] -> t -> s -> [t]
alex' re -> s -> Match s
mo [(re, Match s -> Maybe t)]
al t
t_err = s -> [t]
loop
  where
    loop :: s -> [t]
loop s
s = case s -> Int
forall a. Replace a => a -> Int
lengthR s
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 of
      Bool
True  -> []
      Bool
False -> [(re, Match s -> Maybe t)] -> s -> [t]
choose [(re, Match s -> Maybe t)]
al s
s

    choose :: [(re, Match s -> Maybe t)] -> s -> [t]
choose []           s
_ = [t
t_err]
    choose ((re
re,Match s -> Maybe t
f):[(re, Match s -> Maybe t)]
al') s
s = case Maybe (s, t)
mb_p of
        Just (s
s',t
t) -> t
t t -> [t] -> [t]
forall a. a -> [a] -> [a]
: s -> [t]
loop s
s'
        Maybe (s, t)
_           -> [(re, Match s -> Maybe t)] -> s -> [t]
choose [(re, Match s -> Maybe t)]
al' s
s
      where
        mb_p :: Maybe (s, t)
mb_p = do
          Capture s
cap <- Match s -> Maybe (Capture s)
forall a. Match a -> Maybe (Capture a)
matchCapture Match s
mtch
          case Capture s -> Int
forall a. Capture a -> Int
captureOffset Capture s
cap Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 of
            Bool
True  -> (,) (Capture s -> s
forall a. Extract a => Capture a -> a
captureSuffix Capture s
cap) (t -> (s, t)) -> Maybe t -> Maybe (s, t)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Match s -> Maybe t
f Match s
mtch
            Bool
False -> Maybe (s, t)
forall a. Maybe a
Nothing

        mtch :: Match s
mtch = re -> s -> Match s
mo re
re s
s
\end{code}