Skip to content

Commit

Permalink
Merge pull request #66 from natefaubion/fix-try
Browse files Browse the repository at this point in the history
Add tryRethrow
  • Loading branch information
garyb authored Jul 26, 2017
2 parents 82f4d33 + 92c6b50 commit 0be7c39
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 9 deletions.
16 changes: 12 additions & 4 deletions src/Text/Parsing/Parser.purs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Text.Parsing.Parser
( ParseError
( ParseError(..)
, parseErrorMessage
, parseErrorPosition
, ParseState(..)
Expand All @@ -10,7 +10,9 @@ module Text.Parsing.Parser
, hoistParserT
, mapParserT
, consume
, position
, fail
, failWithPosition
) where

import Prelude
Expand Down Expand Up @@ -123,8 +125,14 @@ consume :: forall s m. Monad m => ParserT s m Unit
consume = modify \(ParseState input position _) ->
ParseState input position true

-- | Returns the current position in the stream.
position :: forall s m. Monad m => ParserT s m Position
position = gets \(ParseState _ pos _) -> pos

-- | Fail with a message.
fail :: forall m s a. Monad m => String -> ParserT s m a
fail message = do
position <- gets \(ParseState _ pos _) -> pos
throwError (ParseError message position)
fail message = failWithPosition message =<< position

-- | Fail with a message and a position.
failWithPosition :: forall m s a. Monad m => String -> Position -> ParserT s m a
failWithPosition message position = throwError (ParseError message position)
10 changes: 9 additions & 1 deletion src/Text/Parsing/Parser/Combinators.purs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import Data.List (List(..), (:), many, some, singleton)
import Data.Maybe (Maybe(..))
import Data.Newtype (unwrap)
import Data.Tuple (Tuple(..))
import Text.Parsing.Parser (ParseState(..), ParserT(..), fail)
import Text.Parsing.Parser (ParseState(..), ParserT(..), ParseError(..), fail)

-- | Provide an error message in the case of failure.
withErrorMessage :: forall m s a. Monad m => ParserT s m a -> String -> ParserT s m a
Expand Down Expand Up @@ -74,6 +74,14 @@ try p = (ParserT <<< ExceptT <<< StateT) \(s@(ParseState _ _ consumed)) -> do
Left _ -> pure (Tuple e (ParseState input position consumed))
_ -> pure (Tuple e s')

-- | Like `try`, but will reannotate the error location to the `try` point.
tryRethrow :: forall m s a. Monad m => ParserT s m a -> ParserT s m a
tryRethrow p = (ParserT <<< ExceptT <<< StateT) \(s@(ParseState _ position consumed)) -> do
Tuple e s'@(ParseState input' position' _) <- runStateT (runExceptT (unwrap p)) s
case e of
Left (ParseError err _) -> pure (Tuple (Left (ParseError err position)) (ParseState input' position' consumed))
_ -> pure (Tuple e s')

-- | Parse a phrase, without modifying the consumed state or stream position.
lookAhead :: forall s a m. Monad m => ParserT s m a -> ParserT s m a
lookAhead p = (ParserT <<< ExceptT <<< StateT) \s -> do
Expand Down
4 changes: 2 additions & 2 deletions src/Text/Parsing/Parser/String.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Data.Maybe (Maybe(..))
import Data.Newtype (wrap)
import Data.String (Pattern, fromCharArray, length, singleton)
import Text.Parsing.Parser (ParseState(..), ParserT, fail)
import Text.Parsing.Parser.Combinators (try, (<?>))
import Text.Parsing.Parser.Combinators (tryRethrow, (<?>))
import Text.Parsing.Parser.Pos (updatePosString)
import Prelude hiding (between)

Expand Down Expand Up @@ -62,7 +62,7 @@ anyChar = do

-- | Match a character satisfying the specified predicate.
satisfy :: forall s m. StringLike s => Monad m => (Char -> Boolean) -> ParserT s m Char
satisfy f = try do
satisfy f = tryRethrow do
c <- anyChar
if f c then pure c
else fail $ "Character '" <> singleton c <> "' did not satisfy predicate"
Expand Down
4 changes: 2 additions & 2 deletions src/Text/Parsing/Parser/Token.purs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import Data.String (toCharArray, null, toLower, fromCharArray, singleton, uncons
import Data.Tuple (Tuple(..))
import Math (pow)
import Text.Parsing.Parser (ParseState(..), ParserT, fail)
import Text.Parsing.Parser.Combinators (skipMany1, try, skipMany, notFollowedBy, option, choice, between, sepBy1, sepBy, (<?>), (<??>))
import Text.Parsing.Parser.Combinators (skipMany1, try, tryRethrow, skipMany, notFollowedBy, option, choice, between, sepBy1, sepBy, (<?>), (<??>))
import Text.Parsing.Parser.Pos (Position)
import Text.Parsing.Parser.String (satisfy, oneOf, noneOf, string, char)
import Prelude hiding (when,between)
Expand All @@ -57,7 +57,7 @@ token tokpos = do

-- | Create a parser which matches any token satisfying the predicate.
when :: forall m a. Monad m => (a -> Position) -> (a -> Boolean) -> ParserT (List a) m a
when tokpos f = try $ do
when tokpos f = tryRethrow do
a <- token tokpos
guard $ f a
pure a
Expand Down
5 changes: 5 additions & 0 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ main = do
"foo"
(Position { column: 2, line: 1 })

parseErrorTestPosition
(satisfy (_ == '?'))
"foo"
(Position { column: 1, line: 1 })

parseTest
"foo"
Nil
Expand Down

0 comments on commit 0be7c39

Please sign in to comment.