<commit_before>{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Control.Monad.Trans.Parse (
  -- * The 'Parse' monad
  Parse, runParse, evalParse,
  -- * The 'ParseT' monad transformer
  ParseT(..), runParseT, evalParseT,
  -- * 'ParseT' operations
  parseWithM, parseWith,
  atEOF, parseToken, parseCharTokenLookahead,
  -- * Lower-level
  parseChar, parseChars, peekChar
) where

import Data.Functor.Identity
import Control.Applicative
import Control.Monad
import Control.Monad.Fix
import Control.Monad.State
import Control.Monad.Except
import HsToCoq.Util.Function

import Data.Text (Text)
import qualified Data.Text as T

newtype ParseT m a = ParseT { getParseT :: StateT Text (ExceptT String m) a }
                   deriving ( Functor, Applicative, Monad
                            , Alternative, MonadPlus
                            , MonadFix, MonadError String )

type Parse = ParseT Identity

runParseT :: ParseT m a -> Text -> m (Either String (a, Text))
runParseT (ParseT act) = runExceptT . runStateT act 

runParse :: Parse a -> Text -> Either String (a, Text)
runParse = runIdentity .: runParseT

evalParseT :: Monad m => ParseT m a -> Text -> m (Either String a)
evalParseT (ParseT act) t = runExceptT $ do
  (res, t') <- runStateT act t
  if T.null t'
  then pure res
  else throwError "unused input"

evalParse :: Parse a -> Text -> Either String a
evalParse = runIdentity .: evalParseT

--------------------------------------------------------------------------------

parseWithM :: Applicative f => (Text -> Either String (a, Text)) -> ParseT f a
parseWithM f = ParseT . StateT $ ExceptT . pure . f
<commit_msg>[minor] Add `MonadIO` instance for `ParseT`<commit_after>{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Control.Monad.Trans.Parse (
  -- * The 'Parse' monad
  Parse, runParse, evalParse,
  -- * The 'ParseT' monad transformer
  ParseT(..), runParseT, evalParseT,
  -- * 'ParseT' operations
  parseWithM, parseWith,
  atEOF, parseToken, parseCharTokenLookahead,
  -- * Lower-level
  parseChar, parseChars, peekChar
) where

import Data.Functor.Identity
import Control.Applicative
import Control.Monad
import Control.Monad.Fix
import Control.Monad.State
import Control.Monad.Except
import HsToCoq.Util.Function

import Data.Text (Text)
import qualified Data.Text as T

newtype ParseT m a = ParseT { getParseT :: StateT Text (ExceptT String m) a }
                   deriving ( Functor, Applicative, Monad
                            , Alternative, MonadPlus
                            , MonadFix, MonadError String, MonadIO )

type Parse = ParseT Identity

runParseT :: ParseT m a -> Text -> m (Either String (a, Text))
runParseT (ParseT act) = runExceptT . runStateT act 

runParse :: Parse a -> Text -> Either String (a, Text)
runParse = runIdentity .: runParseT

evalParseT :: Monad m => ParseT m a -> Text -> m (Either String a)
evalParseT (ParseT act) t = runExceptT $ do
  (res, t') <- runStateT act t
  if T.null t'
  then pure res
  else throwError "unused input"

evalParse :: Parse a -> Text -> Either String a
evalParse = runIdentity .: evalParseT

--------------------------------------------------------------------------------

parseWithM :: Applicative f => (Text -> Either String (a, Text)) -> ParseT f a
parseWithM f = ParseT . StateT $ ExceptT . pure . f

{'fraction_non_alphanumeric': 0.14699667974645336, 'fraction_numerical': 0.0, 'mean_word_length': 2.598262757871878, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7240893', 'n_tokens_mistral': 1034, 'n_tokens_neox': 1001, 'n_words': 334}