module GardGround.Utils.SteParser.List (
  takeWhile,
  tryOne,
) where

import Prelude hiding (takeWhile)
import Control.Monad.State.Strict (MonadState(..))
import GardGround.Utils.SteParser

-- | take a prefix out of the current context, while keeping the rest in the parser
takeWhile :: (a -> Bool) -> Parser [a] e [a]
takeWhile f =
  -- tw' --> (selected, rest)
  -- state lifts (s -> m (a, s))
  let tw' = \env -> case env of
              [] -> ([], [])
              x:xs | f x -> let (sel, rest) = tw' xs in (x:sel, rest)
                   | otherwise -> ([], x:xs)
  in state tw'

-- | try to parse the first element as something
tryOne :: (a -> Maybe b) -> Parser [a] e (Maybe b)
tryOne f =
  let to' = \env -> case env of
              []   -> (Nothing, [])
              x:xs -> case f x of
                Nothing -> (Nothing, x:xs)
                Just y  -> (Just y,    xs)
  in state to'