Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
A simple text parser with decent errors
Synopsis
- data Span a = Span {}
- type LineColLookup = Vector (Int, Int)
- calculateLineCol :: Text -> LineColLookup
- lookupLineCol :: Int -> LineColLookup -> (Int, Int)
- newtype Label = Label {}
- textSpan :: Text -> Span Int
- data Reason e r
- = ReasonCustom !e
- | ReasonExpect !Text !Text
- | ReasonDemand !Int !Int
- | ReasonLeftover !Int
- | ReasonAlt !(Seq (AltPhase, r))
- | ReasonInfix !(Seq (Int, InfixPhase, r))
- | ReasonFail !Text
- | ReasonLabeled !Label r
- | ReasonLook r
- | ReasonTakeNone
- | ReasonEmpty
- | ReasonExplained !Text !HideError r
- data ErrF e r = ErrF {}
- newtype Err e = Err {}
- errSpan :: Err e -> Span Int
- errReason :: Err e -> Reason e (Err e)
- data AltPhase
- data InfixPhase
- data ParserT e m a
- type Parser e = ParserT e Identity
- parseT :: Monad m => ParserT e m a -> Text -> m (Either (Err e) a)
- parse :: Parser e a -> Text -> Either (Err e) a
- parseI :: HasErrMessage e => Parser e a -> Text -> IO (Either (Err e) a)
- spanP :: Monad m => ParserT e m (Span Int)
- spanAroundP :: Monad m => (Span Int -> a -> b) -> ParserT e m a -> ParserT e m b
- throwP :: Monad m => e -> ParserT e m a
- altP :: (Monad m, Foldable f) => f (ParserT e m a) -> ParserT e m a
- emptyP :: Monad m => ParserT e m a
- explainP :: Monad m => (Reason e (Err e) -> Maybe (Text, Bool)) -> ParserT e m a -> ParserT e m a
- endP :: Monad m => ParserT e m ()
- optP :: Monad m => ParserT e m a -> ParserT e m (Maybe a)
- lookP :: Monad m => ParserT e m a -> ParserT e m a
- branchP :: (Monad m, Foldable f) => f (ParserT e m (), ParserT e m a) -> ParserT e m a
- commitP :: (Monad m, Foldable f) => f (ParserT e m (), ParserT e m a) -> ParserT e m a
- labelP :: Monad m => Label -> ParserT e m a -> ParserT e m a
- textP :: Monad m => Text -> ParserT e m Text
- textP_ :: Monad m => Text -> ParserT e m ()
- charP :: Monad m => Char -> ParserT e m Char
- charP_ :: Monad m => Char -> ParserT e m ()
- breakP :: Monad m => Text -> ParserT e m a -> ParserT e m a
- someBreakP :: Monad m => Text -> ParserT e m a -> ParserT e m a
- splitP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- split1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- split2P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- leadP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- lead1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- trailP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- trail1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a)
- infixRP :: Monad m => Text -> ParserT e m a -> ParserT e m b -> ParserT e m (a, b)
- someInfixRP :: Monad m => Text -> ParserT e m a -> ParserT e m b -> ParserT e m (a, b)
- takeP :: Monad m => Int -> ParserT e m Text
- dropP :: Monad m => Int -> ParserT e m Int
- takeExactP :: Monad m => Int -> ParserT e m Text
- dropExactP :: Monad m => Int -> ParserT e m ()
- takeWhileP :: Monad m => (Char -> Bool) -> ParserT e m Text
- dropWhileP :: Monad m => (Char -> Bool) -> ParserT e m Int
- takeWhile1P :: Monad m => (Char -> Bool) -> ParserT e m Text
- dropWhile1P :: Monad m => (Char -> Bool) -> ParserT e m Int
- takeAllP :: Monad m => ParserT e m Text
- dropAllP :: Monad m => ParserT e m Int
- takeAll1P :: Monad m => ParserT e m Text
- dropAll1P :: Monad m => ParserT e m Int
- betweenP :: ParserT e m x -> ParserT e m y -> ParserT e m a -> ParserT e m a
- repeatP :: Monad m => ParserT e m a -> ParserT e m (Seq a)
- repeat1P :: Monad m => ParserT e m a -> ParserT e m (Seq a)
- sepByP :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a)
- sepBy1P :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a)
- sepBy2P :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a)
- spaceP :: Monad m => ParserT e m ()
- stripP :: Monad m => ParserT e m a -> ParserT e m a
- stripStartP :: Monad m => ParserT e m a -> ParserT e m a
- stripEndP :: Monad m => ParserT e m a -> ParserT e m a
- measureP :: Monad m => ParserT e m a -> ParserT e m (a, Int)
- unconsP :: Monad m => ParserT e m (Maybe Char)
- headP :: Monad m => ParserT e m Char
- signedWithP :: Monad m => (a -> a) -> ParserT e m a -> ParserT e m a
- signedP :: (Monad m, Num a) => ParserT e m a -> ParserT e m a
- intP :: Monad m => ParserT e m Integer
- uintP :: Monad m => ParserT e m Integer
- decP :: Monad m => ParserT e m Rational
- udecP :: Monad m => ParserT e m Rational
- sciP :: Monad m => ParserT e m Scientific
- usciP :: Monad m => ParserT e m Scientific
- numP :: Monad m => ParserT e m (Either Integer Scientific)
- unumP :: Monad m => ParserT e m (Either Integer Scientific)
- space1P :: Monad m => ParserT e m ()
- strip1P :: Monad m => ParserT e m a -> ParserT e m a
- stripStart1P :: Monad m => ParserT e m a -> ParserT e m a
- stripEnd1P :: Monad m => ParserT e m a -> ParserT e m a
- transP :: (MonadTrans t, Monad m) => (forall a. t m a -> m a) -> ParserT e (t m) b -> ParserT e m b
- scopeP :: Monad m => s -> ParserT e (StateT s m) a -> ParserT e m a
- iterP :: ParserT e m (Maybe a) -> ParserT e m a
- strP :: Monad m => Char -> ParserT e m Text
- doubleStrP :: Monad m => ParserT e m Text
- singleStrP :: Monad m => ParserT e m Text
- class HasErrMessage e where
- getErrMessage :: (Int -> Text) -> e -> [Text]
- errataE :: HasErrMessage e => FilePath -> (Int -> (Line, Column)) -> Err e -> [Errata]
- renderE :: HasErrMessage e => FilePath -> Text -> Err e -> Text
- printE :: HasErrMessage e => FilePath -> Text -> Err e -> IO ()
Documentation
A generic span, used for tracking ranges of offsets or (line, col)
Instances
Foldable Span Source # | |
Defined in Looksee fold :: Monoid m => Span m -> m # foldMap :: Monoid m => (a -> m) -> Span a -> m # foldMap' :: Monoid m => (a -> m) -> Span a -> m # foldr :: (a -> b -> b) -> b -> Span a -> b # foldr' :: (a -> b -> b) -> b -> Span a -> b # foldl :: (b -> a -> b) -> b -> Span a -> b # foldl' :: (b -> a -> b) -> b -> Span a -> b # foldr1 :: (a -> a -> a) -> Span a -> a # foldl1 :: (a -> a -> a) -> Span a -> a # elem :: Eq a => a -> Span a -> Bool # maximum :: Ord a => Span a -> a # | |
Traversable Span Source # | |
Functor Span Source # | |
Show a => Show (Span a) Source # | |
Eq a => Eq (Span a) Source # | |
Ord a => Ord (Span a) Source # | |
type LineColLookup = Vector (Int, Int) Source #
Auxiliary data structure to translate offsets to (line, col)
calculateLineCol :: Text -> LineColLookup Source #
Construct an offset lookup from a document
lookupLineCol :: Int -> LineColLookup -> (Int, Int) Source #
Returns 0-based (line, col) for the given offset. Clamps to the valid range of offsets, returning (0, 0) for empty text. Note that the valid range is from before the first character to before the last, so a 3 character string has three valid offsets (0, 1, and 2).
A parser label (for error reporting)
Reason for parse failure
ReasonCustom !e | |
ReasonExpect !Text !Text | |
ReasonDemand !Int !Int | |
ReasonLeftover !Int | |
ReasonAlt !(Seq (AltPhase, r)) | |
ReasonInfix !(Seq (Int, InfixPhase, r)) | |
ReasonFail !Text | |
ReasonLabeled !Label r | |
ReasonLook r | |
ReasonTakeNone | |
ReasonEmpty | |
ReasonExplained !Text !HideError r |
Instances
Bifoldable Reason Source # | |
Bifunctor Reason Source # | |
Bitraversable Reason Source # | |
Defined in Looksee bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> Reason a b -> f (Reason c d) # | |
Foldable (Reason e) Source # | |
Defined in Looksee fold :: Monoid m => Reason e m -> m # foldMap :: Monoid m => (a -> m) -> Reason e a -> m # foldMap' :: Monoid m => (a -> m) -> Reason e a -> m # foldr :: (a -> b -> b) -> b -> Reason e a -> b # foldr' :: (a -> b -> b) -> b -> Reason e a -> b # foldl :: (b -> a -> b) -> b -> Reason e a -> b # foldl' :: (b -> a -> b) -> b -> Reason e a -> b # foldr1 :: (a -> a -> a) -> Reason e a -> a # foldl1 :: (a -> a -> a) -> Reason e a -> a # elem :: Eq a => a -> Reason e a -> Bool # maximum :: Ord a => Reason e a -> a # minimum :: Ord a => Reason e a -> a # | |
Traversable (Reason e) Source # | |
Functor (Reason e) Source # | |
(Show e, Show r) => Show (Reason e r) Source # | |
(Eq e, Eq r) => Eq (Reason e r) Source # | |
(Ord e, Ord r) => Ord (Reason e r) Source # | |
Base functor for Err
containing the range and reason for the error
Instances
Bifoldable ErrF Source # | |
Bifunctor ErrF Source # | |
Bitraversable ErrF Source # | |
Defined in Looksee bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> ErrF a b -> f (ErrF c d) # | |
Foldable (ErrF e) Source # | |
Defined in Looksee fold :: Monoid m => ErrF e m -> m # foldMap :: Monoid m => (a -> m) -> ErrF e a -> m # foldMap' :: Monoid m => (a -> m) -> ErrF e a -> m # foldr :: (a -> b -> b) -> b -> ErrF e a -> b # foldr' :: (a -> b -> b) -> b -> ErrF e a -> b # foldl :: (b -> a -> b) -> b -> ErrF e a -> b # foldl' :: (b -> a -> b) -> b -> ErrF e a -> b # foldr1 :: (a -> a -> a) -> ErrF e a -> a # foldl1 :: (a -> a -> a) -> ErrF e a -> a # elem :: Eq a => a -> ErrF e a -> Bool # maximum :: Ord a => ErrF e a -> a # minimum :: Ord a => ErrF e a -> a # | |
Traversable (ErrF e) Source # | |
Functor (ErrF e) Source # | |
(Show e, Show r) => Show (ErrF e r) Source # | |
(Eq e, Eq r) => Eq (ErrF e r) Source # | |
(Ord e, Ord r) => Ord (ErrF e r) Source # | |
A parse error, which may contain multiple sub-errors
Instances
Foldable Err Source # | |
Defined in Looksee fold :: Monoid m => Err m -> m # foldMap :: Monoid m => (a -> m) -> Err a -> m # foldMap' :: Monoid m => (a -> m) -> Err a -> m # foldr :: (a -> b -> b) -> b -> Err a -> b # foldr' :: (a -> b -> b) -> b -> Err a -> b # foldl :: (b -> a -> b) -> b -> Err a -> b # foldl' :: (b -> a -> b) -> b -> Err a -> b # foldr1 :: (a -> a -> a) -> Err a -> a # foldl1 :: (a -> a -> a) -> Err a -> a # elem :: Eq a => a -> Err a -> Bool # maximum :: Ord a => Err a -> a # | |
Traversable Err Source # | |
Functor Err Source # | |
(Typeable e, Show e) => Exception (Err e) Source # | |
Defined in Looksee toException :: Err e -> SomeException # fromException :: SomeException -> Maybe (Err e) # displayException :: Err e -> String # | |
Show e => Show (Err e) Source # | |
Eq e => Eq (Err e) Source # | |
Ord e => Ord (Err e) Source # | |
HasErrMessage e => HasErrMessage (Err e) Source # | |
Corecursive (Err e) Source # | |
Defined in Looksee embed :: Base (Err e) (Err e) -> Err e # ana :: (a -> Base (Err e) a) -> a -> Err e # apo :: (a -> Base (Err e) (Either (Err e) a)) -> a -> Err e # postpro :: Recursive (Err e) => (forall b. Base (Err e) b -> Base (Err e) b) -> (a -> Base (Err e) a) -> a -> Err e # gpostpro :: (Recursive (Err e), Monad m) => (forall b. m (Base (Err e) b) -> Base (Err e) (m b)) -> (forall c. Base (Err e) c -> Base (Err e) c) -> (a -> Base (Err e) (m a)) -> a -> Err e # | |
Recursive (Err e) Source # | |
Defined in Looksee project :: Err e -> Base (Err e) (Err e) # cata :: (Base (Err e) a -> a) -> Err e -> a # para :: (Base (Err e) (Err e, a) -> a) -> Err e -> a # gpara :: (Corecursive (Err e), Comonad w) => (forall b. Base (Err e) (w b) -> w (Base (Err e) b)) -> (Base (Err e) (EnvT (Err e) w a) -> a) -> Err e -> a # prepro :: Corecursive (Err e) => (forall b. Base (Err e) b -> Base (Err e) b) -> (Base (Err e) a -> a) -> Err e -> a # gprepro :: (Corecursive (Err e), Comonad w) => (forall b. Base (Err e) (w b) -> w (Base (Err e) b)) -> (forall c. Base (Err e) c -> Base (Err e) c) -> (Base (Err e) (w a) -> a) -> Err e -> a # | |
type Base (Err e) Source # | |
Phase of alternative parsing (for error reporting)
Instances
Bounded AltPhase Source # | |
Enum AltPhase Source # | |
Show AltPhase Source # | |
Eq AltPhase Source # | |
Ord AltPhase Source # | |
data InfixPhase Source #
Phase of infix/split parsing (for error reporting)
Instances
The parser monad transformer
Instances
MonadReader r m => MonadReader r (ParserT e m) Source # | |
MonadState s m => MonadState s (ParserT e m) Source # | |
MonadTrans (ParserT e) Source # | |
Monad m => MonadFail (ParserT e m) Source # | |
MonadIO m => MonadIO (ParserT e m) Source # | |
Monad m => Alternative (ParserT e m) Source # | |
Applicative (ParserT e m) Source # | |
Defined in Looksee | |
Functor (ParserT e m) Source # | |
Monad (ParserT e m) Source # | |
Monoid a => Monoid (ParserT e m a) Source # | |
Semigroup a => Semigroup (ParserT e m a) Source # | |
parseT :: Monad m => ParserT e m a -> Text -> m (Either (Err e) a) Source #
Run a parser transformer. You must consume all input or this will error!
If you really don't care about the rest of the input, you can always
discard it with dropAllP
.
parseI :: HasErrMessage e => Parser e a -> Text -> IO (Either (Err e) a) Source #
Run a parser and print any errors that occur
spanP :: Monad m => ParserT e m (Span Int) Source #
Get the span (in character offset) at the current point representing
the entire parseable range. At the start of parsing this will be `Span 0 n` for
an n
-character document. The start offset will increase as input is consumed,
and the end offset will decrease as lookahead delimits the range. To evaluate
the "real" range of characters consumed by a parser, construct a span with the
starting offsets before and after executing a subparser (or use spanAroundP
).
spanAroundP :: Monad m => (Span Int -> a -> b) -> ParserT e m a -> ParserT e m b Source #
Incorporate span information into a parsed object.
altP :: (Monad m, Foldable f) => f (ParserT e m a) -> ParserT e m a Source #
Parse with many possible branches
explainP :: Monad m => (Reason e (Err e) -> Maybe (Text, Bool)) -> ParserT e m a -> ParserT e m a Source #
If things fail and you can give a good message explaining why, this combinator will
annotate the error with your explanation. Returning True
with message will hide
the original error message in textual rendering.
lookP :: Monad m => ParserT e m a -> ParserT e m a Source #
Lookahead - rewinds state if the parser succeeds, otherwise throws error
branchP :: (Monad m, Foldable f) => f (ParserT e m (), ParserT e m a) -> ParserT e m a Source #
Branches guarded by lookahead. Use this for more concise errors.
altP
will happily tell you about each of the errors it encountered in
every branch, but this will quietly prune non-matching branches.
Tries until first success (in order), so you can tack on a fallthrough case even if
you tried a branch earlier.
commitP :: (Monad m, Foldable f) => f (ParserT e m (), ParserT e m a) -> ParserT e m a Source #
An alternative to branchP
that does not backtrack after committing to a branch.
textP :: Monad m => Text -> ParserT e m Text Source #
Expect the given text at the start of the range
charP :: Monad m => Char -> ParserT e m Char Source #
Expect the given character at the start of the range
breakP :: Monad m => Text -> ParserT e m a -> ParserT e m a Source #
Split once on the delimiter (first argument), parsing everything before it with a narrowed range.
Chooses first split from START to END of range (see infixRP
).
someBreakP :: Monad m => Text -> ParserT e m a -> ParserT e m a Source #
Split once on the delimiter (first argument), parsing everything before it with a narrowed range.
Chooses splits from START to END of range (see someInfixRP
).
splitP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Split on the delimiter, parsing segments with a narrowed range, until parsing fails. Returns the sequence of successes with state at the delimiter preceding the failure (or end of input), Note that this will always succeed, sometimes consuming no input and yielding empty results.
split1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like splitP
but ensures the sequence is at least length 1.
split2P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like splitP
but ensures the sequence is at least length 2.
(This ensures there is at least one delimiter included.)
leadP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like splitP
but ensures a leading delimiter
lead1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like split1P
but ensures a leading delimiter
trailP :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like splitP
but ensures a trailing delimiter
trail1P :: Monad m => Text -> ParserT e m a -> ParserT e m (Seq a) Source #
Like split1P
but ensures a trailing delimiter
infixRP :: Monad m => Text -> ParserT e m a -> ParserT e m b -> ParserT e m (a, b) Source #
Right-associative infix parsing. Searches for the operator from START to END of range, trying only the first break point.
someInfixRP :: Monad m => Text -> ParserT e m a -> ParserT e m b -> ParserT e m (a, b) Source #
Right-associative infix parsing. Searches for the operator from START to END of range, trying subsequent break points until success.
takeP :: Monad m => Int -> ParserT e m Text Source #
Take the given number of characters from the start of the range, or fewer if empty
dropP :: Monad m => Int -> ParserT e m Int Source #
Drop the given number of characters from the start of the range, or fewer if empty
takeExactP :: Monad m => Int -> ParserT e m Text Source #
Take exactly the given number of characters from the start of the range, or error
dropExactP :: Monad m => Int -> ParserT e m () Source #
Drop exactly the given number of characters from the start of the range, or error
takeWhileP :: Monad m => (Char -> Bool) -> ParserT e m Text Source #
Take characters from the start of the range satisfying the predicate
dropWhileP :: Monad m => (Char -> Bool) -> ParserT e m Int Source #
Drop characters from the start of the range satisfying the predicate
takeWhile1P :: Monad m => (Char -> Bool) -> ParserT e m Text Source #
Like takeWhileP
but ensures at least 1 character has been taken
dropWhile1P :: Monad m => (Char -> Bool) -> ParserT e m Int Source #
Like dropWhileP
but ensures at least 1 character has been dropped
takeAll1P :: Monad m => ParserT e m Text Source #
Like takeAllP
but ensures at least 1 character has been taken
dropAll1P :: Monad m => ParserT e m Int Source #
Like dropAllP
but ensures at least 1 character has been dropped
betweenP :: ParserT e m x -> ParserT e m y -> ParserT e m a -> ParserT e m a Source #
Parse between an opening delimiter (first parser) and a closing delimited (second parser)
repeatP :: Monad m => ParserT e m a -> ParserT e m (Seq a) Source #
Repeat a parser until it fails, collecting the results.
repeat1P :: Monad m => ParserT e m a -> ParserT e m (Seq a) Source #
Like repeatP
but ensures at least one result.
sepByP :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a) Source #
Parse a sequence of items delimited by the first parser
sepBy1P :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a) Source #
Like sepByP
but ensures at least one result.
sepBy2P :: Monad m => ParserT e m () -> ParserT e m a -> ParserT e m (Seq a) Source #
Like sepByP
but ensures at least two results (and at least one delimiter).
measureP :: Monad m => ParserT e m a -> ParserT e m (a, Int) Source #
Parses and returns the length of the consumed input along with the result
unconsP :: Monad m => ParserT e m (Maybe Char) Source #
Takes exactly 1 character from the start of the range, returning Nothing if at end of input
headP :: Monad m => ParserT e m Char Source #
Takes exactly 1 character from the start of the range, throwing error if at end of input
signedWithP :: Monad m => (a -> a) -> ParserT e m a -> ParserT e m a Source #
Add signed-ness to any parser with a negate function
signedP :: (Monad m, Num a) => ParserT e m a -> ParserT e m a Source #
Add signed-ness to any numeric parser
numP :: Monad m => ParserT e m (Either Integer Scientific) Source #
Parse a signed integer/scientific number, defaulting to integer if possible.
unumP :: Monad m => ParserT e m (Either Integer Scientific) Source #
Parse an unsigned integer/scientific number, defaulting to integer if possible.
strip1P :: Monad m => ParserT e m a -> ParserT e m a Source #
Like stripP
but ensures at least 1 space removed
stripStart1P :: Monad m => ParserT e m a -> ParserT e m a Source #
Like stripStartP
but ensures at least 1 space removed
stripEnd1P :: Monad m => ParserT e m a -> ParserT e m a Source #
Like stripEndP
but ensures at least 1 space removed
transP :: (MonadTrans t, Monad m) => (forall a. t m a -> m a) -> ParserT e (t m) b -> ParserT e m b Source #
Unwrap a monad transformer layer (see scopeP
for use)
scopeP :: Monad m => s -> ParserT e (StateT s m) a -> ParserT e m a Source #
Parse with some local state
iterP :: ParserT e m (Maybe a) -> ParserT e m a Source #
Repeats the parser until it returns a Just
value
strP :: Monad m => Char -> ParserT e m Text Source #
Parse a string with a custom quote character. Supports backslash-escaping.
class HasErrMessage e where Source #
Implement this to format custom errors. The list will be indented and joined with unlines
.
Instances
HasErrMessage Void Source # | |
HasErrMessage e => HasErrMessage (Err e) Source # | |
errataE :: HasErrMessage e => FilePath -> (Int -> (Line, Column)) -> Err e -> [Errata] Source #
Create Errata
formatting a parse error