Skip to content

region docs, inContext example #213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ New features:

Other improvements:

- Better error messages for `manyIndex` (#211 by @jamesbrock)
- Better error messages for `manyIndex` (#211 by @jamesdbrock)
- Docs for `region` (#213 by @jamesdbrock)

## [v10.0.0](https://github.com/purescript-contrib/purescript-parsing/releases/tag/v9.1.0) - 2022-07-18

Expand Down
26 changes: 26 additions & 0 deletions src/Parsing.purs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,32 @@ failWithPosition message pos = throwError (ParseError message pos)
-- | Contextualize parsing failures inside a region. If a parsing failure
-- | occurs, then the `ParseError` will be transformed by each containing
-- | `region` as the parser backs out the call stack.
-- |
-- | For example, here’s a helper function `inContext` which uses `region` to
-- | add some string context to the error messages.
-- |
-- | ```
-- | let
-- | inContext :: forall s m a. (String -> String) -> ParserT s m a -> ParserT s m a
-- | inContext context = region \(ParseError message pos) ->
-- | ParseError (context message) pos
-- |
-- | input = "Tokyo thirty-nine million"
-- |
-- | lmap (parseErrorHuman input 30) $ runParser input do
-- | inContext ("Megacity list: " <> _) do
-- | cityname <- inContext ("city name: " <> _) do
-- | fst <$> match (skipMany letter)
-- | skipSpaces
-- | population <- inContext ("population: " <> _) intDecimal
-- | pure $ Tuple cityname population
-- | ```
-- | ---
-- | ```
-- | Megacity list: population: Expected Int at position index:6 (line:1, column:7)
-- | ▼
-- | Tokyo thirty-nine million
-- | ```
region :: forall m s a. (ParseError -> ParseError) -> ParserT s m a -> ParserT s m a
region context p = catchError p $ \err -> throwError $ context err

Expand Down
17 changes: 17 additions & 0 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Effect.Unsafe (unsafePerformEffect)
import Node.Process (lookupEnv)
import Parsing (ParseError(..), ParseState(..), Parser, ParserT, Position(..), consume, fail, getParserT, initialPos, parseErrorMessage, parseErrorPosition, position, region, runParser)
import Parsing.Combinators (advance, between, chainl, chainl1, chainr, chainr1, choice, empty, endBy, endBy1, lookAhead, many, many1, many1Till, many1Till_, manyIndex, manyTill, manyTill_, notFollowedBy, optionMaybe, replicateA, sepBy, sepBy1, sepEndBy, sepEndBy1, skipMany, skipMany1, try, (<?>), (<??>), (<~?>))
import Parsing.Combinators as Combinators
import Parsing.Combinators.Array as Combinators.Array
import Parsing.Expr (Assoc(..), Operator(..), buildExprParser)
import Parsing.Language (haskellDef, haskellStyle, javaStyle)
Expand Down Expand Up @@ -702,6 +703,22 @@ main = do
, expected: Right false
}

do
let
inContext :: forall s m a. (String -> String) -> ParserT s m a -> ParserT s m a
inContext context = region \(ParseError message pos) -> ParseError (context message) pos
input = "Tokyo thirty-nine million"
assertEqual' "region 1"
{ actual: runParser input do
inContext ("Megacity list: " <> _) do
cityname <- inContext ("city name: " <> _) do
fst <$> match (Combinators.skipMany letter)
skipSpaces
population <- inContext ("population: " <> _) intDecimal
pure $ Tuple cityname population
, expected: (Left (ParseError "Megacity list: population: Expected Int" (Position { column: 7, index: 6, line: 1 })))
}

log "\nTESTS number\n"

-- assert' "Number.fromString" $ Just infinity == Data.Number.fromString "Infinity"
Expand Down