gigaparsec-0.3.0.0: Refreshed parsec-style library for compatibility with Scala parsley
LicenseBSD-3-Clause
MaintainerJamie Willis, Gigaparsec Maintainers
Stabilitystable
Safe HaskellTrustworthy
LanguageHaskell2010

Text.Gigaparsec

Description

This object contains the core combinators and parser type: all parsers will require something from within!

Since: 0.1.0.0

Synopsis

Documentation

data Parsec a Source #

This type represents parsers as a first-class value.

Values of this type are constructed using the library's combinators, to build up a final Parsec value that can be passed to parse or one of the similar functions. This is implemented internally similar to other libraries like parsec and gigaparsec.

Instances

Instances details
Alternative Parsec Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

empty :: Parsec a #

(<|>) :: Parsec a -> Parsec a -> Parsec a #

some :: Parsec a -> Parsec [a] #

many :: Parsec a -> Parsec [a] #

Applicative Parsec Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

pure :: a -> Parsec a #

(<*>) :: Parsec (a -> b) -> Parsec a -> Parsec b #

liftA2 :: (a -> b -> c) -> Parsec a -> Parsec b -> Parsec c #

(*>) :: Parsec a -> Parsec b -> Parsec b #

(<*) :: Parsec a -> Parsec b -> Parsec a #

Functor Parsec Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

fmap :: (a -> b) -> Parsec a -> Parsec b #

(<$) :: a -> Parsec b -> Parsec a #

Monad Parsec Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

(>>=) :: Parsec a -> (a -> Parsec b) -> Parsec b #

(>>) :: Parsec a -> Parsec b -> Parsec b #

return :: a -> Parsec a #

Selective Parsec Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

select :: Parsec (Either a b) -> Parsec (a -> b) -> Parsec b #

Monoid m => Monoid (Parsec m) Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

mempty :: Parsec m #

mappend :: Parsec m -> Parsec m -> Parsec m #

mconcat :: [Parsec m] -> Parsec m #

Semigroup m => Semigroup (Parsec m) Source # 
Instance details

Defined in Text.Gigaparsec.Internal

Methods

(<>) :: Parsec m -> Parsec m -> Parsec m #

sconcat :: NonEmpty (Parsec m) -> Parsec m #

stimes :: Integral b => b -> Parsec m -> Parsec m #

data Result e a Source #

Similar to Either, this type represents whether a parser has failed or not.

This is chosen instead of Either to be more specific about the naming.

Constructors

Success a 
Failure e 

Instances

Instances details
Generic (Result e a) Source # 
Instance details

Defined in Text.Gigaparsec

Associated Types

type Rep (Result e a) :: Type -> Type #

Methods

from :: Result e a -> Rep (Result e a) x #

to :: Rep (Result e a) x -> Result e a #

(Show a, Show e) => Show (Result e a) Source # 
Instance details

Defined in Text.Gigaparsec

Methods

showsPrec :: Int -> Result e a -> ShowS #

show :: Result e a -> String #

showList :: [Result e a] -> ShowS #

(Eq a, Eq e) => Eq (Result e a) Source # 
Instance details

Defined in Text.Gigaparsec

Methods

(==) :: Result e a -> Result e a -> Bool #

(/=) :: Result e a -> Result e a -> Bool #

type Rep (Result e a) Source # 
Instance details

Defined in Text.Gigaparsec

type Rep (Result e a) = D1 ('MetaData "Result" "Text.Gigaparsec" "gigaparsec-0.3.0.0-GaO4Nll1TTX65PTSWd6TtD" 'False) (C1 ('MetaCons "Success" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 a)) :+: C1 ('MetaCons "Failure" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 e)))

result :: (e -> b) -> (a -> b) -> Result e a -> b Source #

A fold for the Result type.

This functions like the either function does for Either.

Since: 0.2.0.0

parse Source #

Arguments

:: forall err a. ErrorBuilder err 
=> Parsec a

the parser to execute

-> String

the input to parse

-> Result err a

result of the parse, either an error or result

Runs a parser against some input.

Given a parser, some input, and a way of producing parse errors of a desired type (via ErrorBuilder), this function runs a parser to produce either a successful result or an error. Note that the err type parameter is first, which allows for parse @String to make use of the defaultly formated String error messages. This may not be required if it is clear from context. To make this process nicer within GHCi, consider using parseRepl.

parseFromFile Source #

Arguments

:: forall err a. ErrorBuilder err 
=> Parsec a

the parser to execute

-> FilePath

the file to source the input from

-> IO (Result err a)

the result of the parse, error or otherwise

Runs a parser against some input obtained from a given file.

Given a parser, a filename, and a way of producing parse errors of a desired type (via ErrorBuilder), this function runs a parser to produce either a successful result or an error. First, input is collected by reading the file, and then the result is returned within IO; the filename is forwarded on to the ErrorBuilder, which may mean it forms part of the generated error messages.

Note that the err type parameter is first, which allows for parseFromFile @String to make use of the defaultly formated String error messages. This may not be required if it is clear from context.

Since: 0.2.1.0

parseRepl Source #

Arguments

:: Show a 
=> Parsec a

the parser to execute

-> String

the input to parse

-> IO () 

Runs a parser against some input, pretty-printing the result to the terminal.

Compared, with parse, this function will always generate error messages as strings and will print them nicely to the terminal (on multiple lines). If the parser succeeds, the result will also be printed to the terminal. This is useful for playing around with parsers in GHCi, seeing the results more clearly.

Since: 0.2.0.0

Primitive Combinators

These combinators are specific to parser combinators. In one way or another, they influence how a parser consumes input, or under what conditions a parser does or does not fail. These are really important for most practical parsing considerations, although lookAhead is much less well used.

atomic Source #

Arguments

:: Parsec a

the parser, p, to execute, if it fails, it will not have consumed input.

-> Parsec a

a parser that tries p, but never consumes input if it fails.

This combinator parses its argument p, but rolls back any consumed input on failure.

If the parser p succeeds, then atomic p has no effect. However, if p failed, then any input that it consumed is rolled back. This has two uses: it ensures that the parser p is all-or-nothing when consuming input, and it allows for parsers that consume input to backtrack when they fail (with (<|>)). It should be used for the latter purpose sparingly, however, since excessive backtracking in a parser can result in much lower efficiency.

Examples

Expand
>>> parse (string "abc" <|> string "abd") "abd"
Failure .. -- first parser consumed a, so no backtrack
>>> parse (atomic (string "abc") <|> string "abd") "abd"
Success "abd" -- first parser does not consume input on failure now

Since: 0.1.0.0

lookAhead Source #

Arguments

:: Parsec a

the parser, p, to execute

-> Parsec a

a parser that parses p and never consumes input if it succeeds.

This combinator parses its argument p, but does not consume input if it succeeds.

If the parser p succeeds, then lookAhead p will roll back any input consumed whilst parsing p. If p fails, however, then the whole combinator fails and any input consumed remains consumed. If this behaviour is not desirable, consider pairing lookAhead with atomic.

Examples

Expand
>>> parse (lookAhead (string "aaa") *> string "aaa") "aaa"
Success "aaa"
>>> parse (lookAhead (string "abc") <|> string "abd" "abd"
Failure .. -- lookAhead does not roll back input consumed on failure

Since: 0.1.0.0

notFollowedBy Source #

Arguments

:: Parsec a

the parser, p, to execute, it must fail in order for this combinator to succeed.

-> Parsec ()

a parser which fails when p succeeds and succeeds otherwise, never consuming input.

This combinator parses its argument p, and succeeds when p fails and vice-versa, never consuming input.

If the parser p succeeds, then notFollowedBy p will fail, consuming no input. Otherwise, should p fail, then notFollowedBy p will succeed, consuming no input and returning ().

Examples

Expand

One use for this combinator is to allow for "longest-match" behaviour. For instance, keywords are normally only considered keywords if they are not part of some larger valid identifier (i.e. the keyword "if" should not parse successfully given "ifp"). This can be accomplished as follows:

keyword :: String -> Parsec ()
keyword kw = atomic $ string kw *> notFollowedBy letterOrDigit

Since: 0.1.0.0

eof :: Parsec () Source #

This parser only succeeds at the end of the input.

Equivalent to `notFollowedBy(item)`.

Examples

Expand
>>> parse eof "a"
Failure ..
>>> parse eof ""
Success ()

Since: 0.1.0.0

Consumptionless Parsers

These combinators and parsers do not consume input: they are the most primitive ways of producing successes and failures with the minimal possible effect on the parse. They are, however, reasonably useful; in particular, pure and unit can be put to good use in injecting results into a parser without needing to consume anything, or mapping another parser.

unit :: Parsec () Source #

This parser produces () without having any other effect.

When this parser is ran, no input is required, nor consumed, and the given value will always be successfully returned. It has no other effect on the state of the parser.

Since: 0.1.0.0

Re-exported from Control.Applicative

pure :: Applicative f => a -> f a #

Lift a value.

empty :: Alternative f => f a #

The identity of <|>

Result Changing Combinators

These combinators change the result of the parser they are called on into a value of a different type. This new result value may or may not be derived from the previous result.

($>) :: Parsec a -> b -> Parsec b infixl 4 Source #

This combinator, pronounced "as", replaces the result of this parser, ignoring the old result.

Similar to ($), except the old result of this parser is not required to compute the new result. This is useful when the result is a constant value (or function!). Functionally the same as p *> pure x or const x $ p.

In parsley, this combinator is known as #> or as.

Examples

Expand
>>> parse (string "true" $> true) "true"
Success true

Re-exported from Data.Functor

(<$>) :: Functor f => (a -> b) -> f a -> f b infixl 4 #

An infix synonym for fmap.

The name of this operator is an allusion to $. Note the similarities between their types:

 ($)  ::              (a -> b) ->   a ->   b
(<$>) :: Functor f => (a -> b) -> f a -> f b

Whereas $ is function application, <$> is function application lifted over a Functor.

Examples

Expand

Convert from a Maybe Int to a Maybe String using show:

>>> show <$> Nothing
Nothing
>>> show <$> Just 3
Just "3"

Convert from an Either Int Int to an Either Int String using show:

>>> show <$> Left 17
Left 17
>>> show <$> Right 17
Right "17"

Double each element of a list:

>>> (*2) <$> [1,2,3]
[2,4,6]

Apply even to the second element of a pair:

>>> even <$> (2,2)
(2,True)

(<$) :: Functor f => a -> f b -> f a infixl 4 #

Replace all locations in the input with the same value. The default definition is fmap . const, but this may be overridden with a more efficient version.

Examples

Expand

Perform a computation with Maybe and replace the result with a constant value if it is Just:

>>> 'a' <$ Just 2
Just 'a'
>>> 'a' <$ Nothing
Nothing

void :: Functor f => f a -> f () #

void value discards or ignores the result of evaluation, such as the return value of an IO action.

Examples

Expand

Replace the contents of a Maybe Int with unit:

>>> void Nothing
Nothing
>>> void (Just 3)
Just ()

Replace the contents of an Either Int Int with unit, resulting in an Either Int ():

>>> void (Left 8675309)
Left 8675309
>>> void (Right 8675309)
Right ()

Replace every element of a list with unit:

>>> void [1,2,3]
[(),(),()]

Replace the second element of a pair with unit:

>>> void (1,2)
(1,())

Discard the result of an IO action:

>>> mapM print [1,2]
1
2
[(),()]
>>> void $ mapM print [1,2]
1
2

Sequencing Combinators

These combinators all combine two parsers in sequence. The first argument of the combinator will be executed first, then the second argument second. The results of both parsers are combined in some way (depending on the individual combinator). If one of the parsers fails, the combinator as a whole fails.

(<~>) :: Parsec a -> Parsec b -> Parsec (a, b) infixl 4 Source #

This combinator, pronounced "zip", first parses this parser then parses q: if both succeed the result of this parser is paired with the result of q.

First, this parser is ran, yielding x on success, then q is ran, yielding y on success. If both are successful then (x, y) is returned. If either fail then the entire combinator fails.

Examples

Expand
>>> p = char 'a' <~> char 'b'
>>> parse p "ab"
Success ('a', 'b')
>>> parse p "b"
Failure ..
>>> parse p "a"
Failure ..

(<:>) :: Parsec a -> Parsec [a] -> Parsec [a] infixl 4 Source #

This combinator, pronounced "cons", first parses this parser then parses ps: if both succeed the result of this parser is prepended onto the result of ps.

First, this parser is ran, yielding x on success, then ps is ran, yielding xs on success. If both are successful then x : xs is returned. If either fail then the entire combinator fails.

Examples

Expand
some p = p <:> many(p)

Re-exported from Control.Applicative

(<*>) :: Applicative f => f (a -> b) -> f a -> f b infixl 4 #

Sequential application.

A few functors support an implementation of <*> that is more efficient than the default one.

Example

Expand

Used in combination with (<$>), (<*>) can be used to build a record.

>>> data MyState = MyState {arg1 :: Foo, arg2 :: Bar, arg3 :: Baz}
>>> produceFoo :: Applicative f => f Foo
>>> produceBar :: Applicative f => f Bar
>>> produceBaz :: Applicative f => f Baz
>>> mkState :: Applicative f => f MyState
>>> mkState = MyState <$> produceFoo <*> produceBar <*> produceBaz

liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c #

Lift a binary function to actions.

Some functors support an implementation of liftA2 that is more efficient than the default one. In particular, if fmap is an expensive operation, it is likely better to use liftA2 than to fmap over the structure and then use <*>.

This became a typeclass method in 4.10.0.0. Prior to that, it was a function defined in terms of <*> and fmap.

Example

Expand
>>> liftA2 (,) (Just 3) (Just 5)
Just (3,5)

(*>) :: Applicative f => f a -> f b -> f b infixl 4 #

Sequence actions, discarding the value of the first argument.

Examples

Expand

If used in conjunction with the Applicative instance for Maybe, you can chain Maybe computations, with a possible "early return" in case of Nothing.

>>> Just 2 *> Just 3
Just 3
>>> Nothing *> Just 3
Nothing

Of course a more interesting use case would be to have effectful computations instead of just returning pure values.

>>> import Data.Char
>>> import Text.ParserCombinators.ReadP
>>> let p = string "my name is " *> munch1 isAlpha <* eof
>>> readP_to_S p "my name is Simon"
[("Simon","")]

(<*) :: Applicative f => f a -> f b -> f a infixl 4 #

Sequence actions, discarding the value of the second argument.

(<**>) :: Applicative f => f a -> f (a -> b) -> f b infixl 4 #

A variant of <*> with the arguments reversed.

Branching Combinators

These combinators allow for parsing one alternative or another. All of these combinators are left-biased, which means that the left-hand side of the combinator is tried first: the right-hand side of the combinator will only be tried when the left-hand one failed (and did not consume input in the process).

(<+>) :: Parsec a -> Parsec b -> Parsec (Either a b) infixl 3 Source #

This combinator, pronounced "sum", wraps this parser's result in Left if it succeeds, and parses q if it failed without consuming input, wrapping the result in Right.

If this parser is successful, then its result is wrapped up using Left and no further action is taken. Otherwise, if this parser fails without consuming input, then q is parsed instead and its result is wrapped up using Right. If this parser fails having consumed input, this combinator fails. This is functionally equivalent to Left $ p | Right $ q.

The reason for this behaviour is that it prevents space leaks and improves error messages. If this behaviour is not desired, use atomic p to rollback any input consumed on failure.

Examples

Expand
>>> p = string "abc" <+> char "xyz"
>>> parse p "abc"
Success (Left "abc")
>>> parse p "xyz"
Success (Right "xyz")
>>> parse p "ab"
Failure .. -- first parser consumed an 'a'!

Re-exported from Control.Applicative

(<|>) :: Alternative f => f a -> f a -> f a infixl 3 #

An associative binary operation

Selective Combinators

These combinators will decide which branch to take next based on the result of another parser. This differs from combinators like (<|>) which make decisions based on the success/failure of a parser: here the result of a successful parse will direct which option is done.

Re-exported from Control.Selective

select :: Selective f => f (Either a b) -> f (a -> b) -> f b #

branch :: Selective f => f (Either a b) -> f (a -> c) -> f (b -> c) -> f c #

The branch function is a natural generalisation of select: instead of skipping an unnecessary effect, it chooses which of the two given effectful functions to apply to a given argument; the other effect is unnecessary. It is possible to implement branch in terms of select, which is a good puzzle (give it a try!).

We can also implement select via branch:

selectB :: Selective f => f (Either a b) -> f (a -> b) -> f b
selectB x y = branch x y (pure id)

Filtering Combinators

These combinators perform filtering on the results of a parser. This means that, given the result of a parser, they will perform some function on that result, and the success of that function effects whether or not the parser fails.

filterS Source #

Arguments

:: (a -> Bool)

the predicate that is tested against the parser result.

-> Parsec a

the parser to filter, p.

-> Parsec a

a parser that returns the result of p if it passes the predicate.

This combinator filters the result of this parser using a given predicate, succeeding only if the predicate returns True.

First, parse this parser. If it succeeds then take its result x and apply it to the predicate pred. If pred x is true, then return x. Otherwise, the combinator fails.

Examples

Expand
>>> keywords = Set.fromList ["if", "then", "else"]
>>> identifier = filterS (\v -> not (Set.member v keywords)) (some letter)
>>> parse identifier "hello"
Success "hello"
>>> parse identifier "if"
Failure ..

Since: 0.2.2.0

mapMaybeS Source #

Arguments

:: (a -> Maybe b)

the function used to both filter the result of this parser and transform it.

-> Parsec a

the parser to filter, p.

-> Parsec b

a parser that returns the result of p applied to f, if it yields a value.

This combinator applies a function f to the result of this parser: if it returns a Just y, y is returned, otherwise the parser fails.

First, parse this parser. If it succeeds, apply the function f to the result x. If f x returns Just y, return y. If f x returns Nothing, or this parser failed then this combinator fails. Is a more efficient way of performing a filterS and fmap at the same time.

Examples

Expand
>>> int = ...
>>> safeDiv = mapMaybeS (\(x, y) -> if y /= 0 then Just (div x y) else Nothing) (int <~> (char ' ' *> int))
>>> parse safeDiv "7 0"
Failure .. -- y cannot be 0!
>>> parse safeDiv "10 2"
Success 5

Since: 0.2.2.0

Folding Combinators

These combinators repeatedly execute a parser (at least zero or one times depending on the specific combinator) until it fails. The results of the successes are then combined together using a folding function. An initial value for the accumulation may be given (for the folds), or the first successful result is the initial accumulator (for the reduces). These are implemented efficiently and do not need to construct any intermediate list with which to store the results.

many :: Alternative f => f a -> f [a] #

Zero or more.

some :: Alternative f => f a -> f [a] #

One or more.

manyl Source #

Arguments

:: (b -> a -> b)

function to apply to each value produced by this parser, starting at the left.

-> b

the initial value to feed into the reduction

-> Parsec a 
-> Parsec b

a parser which parses this parser many times and folds the results together with f and k left-associatively.

This combinator will parse this parser zero or more times combining the results with the function f and base value k from the left.

This parser will continue to be parsed until it fails having not consumed input. All of the results generated by the successful parses are then combined in a left-to-right fashion using the function f: the left-most value provided to f is the value k. If this parser does fail at any point having consumed input, this combinator will fail.

manyr Source #

Arguments

:: (a -> b -> b)

function to apply to each value produced by this parser, starting at the right.

-> b

value to use when this parser no longer succeeds.

-> Parsec a 
-> Parsec b

a parser which parses this parser many times and folds the results together with f and k right-associatively.

This combinator will parse this parser zero or more times combining the results with the function f and base value k from the right.

This parser will continue to be parsed until it fails having not consumed input. All of the results generated by the successful parses are then combined in a right-to-left fashion using the function f: the right-most value provided to f is the value k. If this parser does fail at any point having consumed input, this combinator will fail.

Examples

Expand
many = manyr (:) []

somel Source #

Arguments

:: (b -> a -> b)

function to apply to each value produced by this parser, starting at the left.

-> b

the initial value to feed into the reduction

-> Parsec a 
-> Parsec b

a parser which parses this parser some times and folds the results together with f and k left-associatively.

This combinator will parse this parser one or more times combining the results with the function f and base value k from the left.

This parser will continue to be parsed until it fails having not consumed input. All of the results generated by the successful parses are then combined in a left-to-right fashion using the function f: the left-most value provided to f is the value k. If this parser does fail at any point having consumed input, this combinator will fail.

Examples

Expand
natural = somel (\x d -> x * 10 + digitToInt d) 0 digit

somer Source #

Arguments

:: (a -> b -> b)

function to apply to each value produced by this parser, starting at the right.

-> b

value to use when this parser no longer succeeds.

-> Parsec a 
-> Parsec b

a parser which parses this parser some times and folds the results together with f and k right-associatively.

This combinator will parse this parser one or more times combining the results with the function f and base value k from the right.

This parser will continue to be parsed until it fails having not consumed input. All of the results generated by the successful parses are then combined in a right-to-left fashion using the function f: the right-most value provided to f is the value k. If this parser does fail at any point having consumed input, this combinator will fail.

Examples

Expand
some = somer (:) []

manyMap :: Monoid m => (a -> m) -> Parsec a -> Parsec m Source #

This combinator acts like the foldMap function but with a parser.

The parser manyMap f p, will parse p zero or more times, then adapt each result with the function f to produce a bunch of values in some Monoid m. These values are then combined together to form a single value; if p could not be parsed, it will return the mempty for m.

Examples

Expand
>>> parse (manyMap Set.singleton item) "aaaab"
Success (Set.fromList ['a', 'b'])

Since: 0.2.2.0

someMap :: Semigroup s => (a -> s) -> Parsec a -> Parsec s Source #

This combinator acts like the foldMap function but with a parser.

The parser manyMap f p, will parse p one or more times, then adapt each result with the function f to produce a bunch of values in some Semigroup s. These values are then combined together to form a single value.

Examples

Expand
>>> parse (someMap Max item) "bdcjb"
Success (Max 'j')
>>> parse (someMap Min item) "bdcjb"
Success (Max 'b')

Since: 0.2.2.0