License | BSD-3-Clause |
---|---|
Maintainer | Jamie Willis, Gigaparsec Maintainers |
Stability | experimental |
Safe Haskell | Safe |
Language | Haskell2010 |
This module contains various functionality relating to the parsing of expressions.
It also includes functionality for constructing larger precedence tables, which may even vary the type of each layer in the table, allowing for strongly-typed expression parsing.
Synopsis
- infixl1 :: (a -> b) -> Parsec a -> Parsec (b -> a -> b) -> Parsec b
- infixr1 :: (a -> b) -> Parsec a -> Parsec (a -> b -> b) -> Parsec b
- infixn1 :: (a -> b) -> Parsec a -> Parsec (a -> a -> b) -> Parsec b
- prefix :: (a -> b) -> Parsec (b -> b) -> Parsec a -> Parsec b
- postfix :: (a -> b) -> Parsec a -> Parsec (b -> b) -> Parsec b
- precedence :: Prec a -> Parsec a
- precedence' :: Parsec a -> [Op a a] -> Parsec a
- ops :: Fixity a a sig -> [Parsec sig] -> Op a a
- sops :: Subtype a b => Fixity a b sig -> [Parsec sig] -> Op a b
- gops :: Fixity a b sig -> (a -> b) -> [Parsec sig] -> Op a b
- data Fixity a b sig where
- data Op a b = Op (Fixity a b sig) (a -> b) (Parsec sig)
- data Prec a where
- (>+) :: Prec a -> Op a b -> Prec b
- (+<) :: Op a b -> Prec a -> Prec b
- data Prec a where
- data Fixity a b sig where
- data Op a b = Op (Fixity a b sig) (a -> b) (Parsec sig)
- precedence :: Prec a -> Parsec a
- precedence' :: Parsec a -> [Op a a] -> Parsec a
- ops :: Fixity a a sig -> [Parsec sig] -> Op a a
- sops :: Subtype a b => Fixity a b sig -> [Parsec sig] -> Op a b
- gops :: Fixity a b sig -> (a -> b) -> [Parsec sig] -> Op a b
- (>+) :: Prec a -> Op a b -> Prec b
- (+<) :: Op a b -> Prec a -> Prec b
Infix combinators
These are standalone Infix combinators. They are useful for parsing the application of operators to values in many different configurations, including: prefix, postfix, infix (left and right associated), and mixed fixity.
Although these combinators do have their uses,
they are overshadowed by the precedence
combinator,
which allows for the combining of multiple levels of infix-chaining in a clean and concise way.
See Text.Gigaparsec.Expr.Infix and Text.Gigaparsec.Expr.Chain for more information on chaining combinators.
Binary Operator Chains
These combinators allow for the chaining together of values and binary operators in either left-, right- or non-associative application.
:: (a -> b) | a function converting the value type |
-> Parsec a |
|
-> Parsec (b -> a -> b) |
|
-> Parsec b | a parser that parses alternating |
This combinator handles left-associative parsing, and the application of, zero or more binary operators between one or more values.
First parse p
, then parse op
followed by a p
repeatedly.
The results of the p
s, x₁
through xₙ
, are combined with the results of the op
s,
f₁
through fₙ₋₁
, with left-associative application:
fₙ₋₁ (fₙ₋₂ (..(f₁ x₁ x₂)..) xₙ₋₁) xₙ.
This application is then returned as the result of the combinator.
If p
or op
fails having consumed input at any point, the whole combinator fails.
Compared with chainl1
,
this combinator allows the types of the operators to more accurately encode their associativity in their types.
However, chainl1
, in which a
and b
must match,
allows for more flexibility to change the associativity.
:: (a -> b) | a function converting the value type |
-> Parsec a |
|
-> Parsec (a -> b -> b) |
|
-> Parsec b | a parser that parses alternating |
This combinator handles right-associative parsing, and the application of, zero or more binary operators between one or more values.
First parse p
, then parse op
followed by a p
repeatedly.
The results of the p
s, x₁
through xₙ
, are combined with the results of the op
s,
f₁
through fₙ
, with right-associative application:
f₁ x₁ (f₂ x₂ (...(fₙ₋₁ xₙ₋₁ xₙ)...))
.
This application is then returned as the result of the combinator.
If p
or op
fails having consumed input at any point, the whole combinator fails.
Compared with chainr1
,
this combinator allows the types of the operators to more accurately encode their associativity in their types.
However, chainr1
, in which a
and b
must match,
allows for more flexibility to change the associativity.
:: (a -> b) | a function converting the value type |
-> Parsec a |
|
-> Parsec (a -> a -> b) |
|
-> Parsec b | a parser that parses |
This combinator handles non-associative parsing, and the application of, zero or one binary operators between one or two values.
First parse p
.
Then:
- If this not is followed by an
op
, simply returnp
. - Otherwise, parse this
op
followed by a singlep
. Then ensure that this is not followed by a furtherop
, to enforce non-associativity. The results of thep
s,x
andy
, are combined with the result ofop
,f
with the applicationf x y
. This application is then returned as the result of the combinator.
If p
or op
fails having consumed input at any point, the whole combinator fails.
This combinator also fails if the second p
is followed by another op
.
Unary Operator Chains
These combinators allow for the chaining together, and application, of multiple prefix or postfix unary operators to a single value.
:: (a -> b) |
|
-> Parsec (b -> b) |
|
-> Parsec a |
|
-> Parsec b | a parser that parses many |
This combinator handles right-assocative parsing, and application of, zero or more prefix unary operators to a single value.
First parse many repeated op
s.
When there are no more op
s left to parse, parse a single p
.
The result of p
, x
, is applied first to wrap
, and then to each of the results of the op
s, f₁
through fₙ
,
such that fₙ
is applied first and f₁
last: f₁ (f₂ (..(fₙ (wrap x))..))
.
This application is then returned as the result of the combinator.
If p
or op
fails having consumed input at any point, the whole combinator fails.
:: (a -> b) | a function converting the value type |
-> Parsec a |
|
-> Parsec (b -> b) |
|
-> Parsec b | a parser that parses many |
This combinator handles left-assocative parsing, and application of, zero or more postfix unary operators to a single value.
First parse a single p
.
Then, parse many repeated op
s.
The result of p
, x
, is applied first to wrap
, and then to each of the results of the op
s, f₁
through fₙ
,
such that f₁
is applied first and fₙ
last: fₙ( fₙ₋₁(..f₁ (wrap x)..))
.
This application is then returned as the result of the combinator.
If p
or op
fails having consumed input at any point, the whole combinator fails.
Precedence Combinators
These combinators represent each of the different "shapes" of precedence combinator, which takes a description of the precedence relations between various operators and constructs a parser for them.
:: Prec a | the description of the heterogeneous table, where each level can vary in output and input types. |
-> Parsec a | an expression parser for the described precedence table. |
Constructs a precedence parser.
This combinator builds an expression parser given a heterogeneous precedence table.
An expression parser will be formed by collapsing the given precedence table layer-by-layer. Since this table is heterogeneous, each level of the table produces a difference type, which is then consumed by the next level above.
:: Parsec a | The atom at the base of the table. |
-> [Op a a] | The levels of operators, oredered tightest-to-weakest. |
-> Parsec a | An expression parser for the constructed precedence table. |
This combinator builds an expression parser given a collection of homogeneous atoms and operators.
An expression parser will be formed by treating the given parser as the base Atom
,
then each successive layer in the given list as another Level
in a tightest-to-weakest binding.
This means the last element of the given list will be at the top of the precedence table.
Each level must consume and produce the same type.
Precedence Layer Builders
These are used to construct an individual layer of a precedence table.
They all allow for the tying of a Fixity
to the parsers that inhabit the level,
which will have type
for some Op
a ba
(the type of the layer below) and b
(the type of this layer).
Op
uses existential types, so that the types of the parsers are only known when fixity itself is known.
The different objects represent different inter-layer relationships:
:: Fixity a a sig | The fixity of the layer to add. |
-> [Parsec sig] | The parsers that can be run in this layer. |
-> Op a a | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators in the precedence tree.
:: Subtype a b | |
=> Fixity a b sig | The fixity of the layer to add. |
-> [Parsec sig] | The parsers that can be run in this layer. |
-> Op a b | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators in the precedence tree for values of Op a b
, where a
is a Subtype
of b
.
This provides support for subtyped heterogeneous precedence parsing.
:: Fixity a b sig | the fixity of the operators described. |
-> (a -> b) | the function that will convert |
-> [Parsec sig] | The operators themselves, provided variadically. |
-> Op a b | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators Op a b
, supporting fully heterogeneous precedence parsing.
This function builds an Ops object representing many operators found at the same precedence level, with a given fixity.
The operators found on the level constructed by this function are heterogeneous: the type of the level below may vary from the types of the values produced at this level. To make this work, a function must be provided that can transform the values from the layer below into the types generated by this layer.
The fixity describes the shape of the operators expected.
Fixity Description
These all describe the fixities and associativities of operators at a given level of the precedence table.
They are special because they each encode an Op
type,
which directs the type of the operators that are legal at the level (using existential types).
data Fixity a b sig where Source #
Denotes the fixity and associativity of an operator.
Importantly, it also specifies the types of the operations themselves.
InfixL :: forall a b. Fixity a b (b -> a -> b) | A left-associative binary Operator. |
InfixR :: forall a b. Fixity a b (a -> b -> b) | A right-associative binary Operator. |
InfixN :: forall a b. Fixity a b (a -> a -> b) | A non-associative binary Operators. |
Prefix :: forall a b. Fixity a b (b -> b) | A Unary prefix operator. |
Postfix :: forall a b. Fixity a b (b -> b) | A Unary postfix operator. |
Precedence Table Datatypes
These are the parts that make up a precedence table (in particular, they are used for heterogeneous expression parsing, with the types of each layer of the table vary from one another).
These are (mostly) not constructed directly, but are instead constructed via the use of the Ops builders or the :+ and +: methods.
Describes a single layer of operators in the precedence tree.
The parameters are:
a
: the base tyep consumed by the operators.b
: the type produced/consumed by the operators.
The base type for precedence tables.
The parameter a
is the type of structure produced by the list of levels.
For more complex expression parser types, Prec
describes the precedence table whilst preserving the intermediate structure between each level.
The base of the table will always be an Atom
, and each layer built on top of the last using the Level
constructor.
Level :: forall a1 a. Prec a1 -> Op a1 a -> Prec a | Adds a new layer to this precedence table on the left, in a weakest-to-tightest ordering. This method associates to the left, so left-most applications are tighter binding (closer to the atoms) than those to the right. It should not be mixed with |
Atom :: forall a. Parsec a -> Prec a | The base of a precedence table. Forms the base of a precedence table, requiring at least one atom to be provided. This first atom will be parsed first. |
:: Prec a | the lower precedence table. |
-> Op a b | the operators that make up the new level on the table. |
-> Prec b | a new table that incorporates the operators and atoms in the given table, along with extra ops. |
Adds a new layer to this precedence table on the left, in a weakest-to-tightest ordering.
This is an alias for Level
.
This method associates to the left, so left-most applications are tighter binding (closer to the atoms) than those to the right.
It should not be mixed with (+<)
, as this can be create a confusing and less predictable precedence table.
:: Op a b | the lower precedence table. |
-> Prec a | the operators that make up the new level on the table. |
-> Prec b | a new table that incorporates the operators and atoms in the given table, along with extra ops. |
Adds a new layer to this precedence table on the right, in a tightest-to-weakest ordering.
This method associates to the right (with this table on the right!), so right-most applications are tighter binding (closer to the atoms) than those to the left.
It should not be mixed with (>+)
, as this can be create a confusing and less predictable precedence table.
Module Re-export
This should be removed at some point.
The base type for precedence tables.
The parameter a
is the type of structure produced by the list of levels.
For more complex expression parser types, Prec
describes the precedence table whilst preserving the intermediate structure between each level.
The base of the table will always be an Atom
, and each layer built on top of the last using the Level
constructor.
Level :: forall a1 a. Prec a1 -> Op a1 a -> Prec a | Adds a new layer to this precedence table on the left, in a weakest-to-tightest ordering. This method associates to the left, so left-most applications are tighter binding (closer to the atoms) than those to the right. It should not be mixed with |
Atom :: forall a. Parsec a -> Prec a | The base of a precedence table. Forms the base of a precedence table, requiring at least one atom to be provided. This first atom will be parsed first. |
data Fixity a b sig where Source #
Denotes the fixity and associativity of an operator.
Importantly, it also specifies the types of the operations themselves.
InfixL :: forall a b. Fixity a b (b -> a -> b) | A left-associative binary Operator. |
InfixR :: forall a b. Fixity a b (a -> b -> b) | A right-associative binary Operator. |
InfixN :: forall a b. Fixity a b (a -> a -> b) | A non-associative binary Operators. |
Prefix :: forall a b. Fixity a b (b -> b) | A Unary prefix operator. |
Postfix :: forall a b. Fixity a b (b -> b) | A Unary postfix operator. |
Describes a single layer of operators in the precedence tree.
The parameters are:
a
: the base tyep consumed by the operators.b
: the type produced/consumed by the operators.
:: Prec a | the description of the heterogeneous table, where each level can vary in output and input types. |
-> Parsec a | an expression parser for the described precedence table. |
Constructs a precedence parser.
This combinator builds an expression parser given a heterogeneous precedence table.
An expression parser will be formed by collapsing the given precedence table layer-by-layer. Since this table is heterogeneous, each level of the table produces a difference type, which is then consumed by the next level above.
:: Parsec a | The atom at the base of the table. |
-> [Op a a] | The levels of operators, oredered tightest-to-weakest. |
-> Parsec a | An expression parser for the constructed precedence table. |
This combinator builds an expression parser given a collection of homogeneous atoms and operators.
An expression parser will be formed by treating the given parser as the base Atom
,
then each successive layer in the given list as another Level
in a tightest-to-weakest binding.
This means the last element of the given list will be at the top of the precedence table.
Each level must consume and produce the same type.
:: Fixity a a sig | The fixity of the layer to add. |
-> [Parsec sig] | The parsers that can be run in this layer. |
-> Op a a | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators in the precedence tree.
:: Subtype a b | |
=> Fixity a b sig | The fixity of the layer to add. |
-> [Parsec sig] | The parsers that can be run in this layer. |
-> Op a b | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators in the precedence tree for values of Op a b
, where a
is a Subtype
of b
.
This provides support for subtyped heterogeneous precedence parsing.
:: Fixity a b sig | the fixity of the operators described. |
-> (a -> b) | the function that will convert |
-> [Parsec sig] | The operators themselves, provided variadically. |
-> Op a b | A layer in the precedence table, containing the given parsers. |
Constructs a single layer of operators Op a b
, supporting fully heterogeneous precedence parsing.
This function builds an Ops object representing many operators found at the same precedence level, with a given fixity.
The operators found on the level constructed by this function are heterogeneous: the type of the level below may vary from the types of the values produced at this level. To make this work, a function must be provided that can transform the values from the layer below into the types generated by this layer.
The fixity describes the shape of the operators expected.
:: Prec a | the lower precedence table. |
-> Op a b | the operators that make up the new level on the table. |
-> Prec b | a new table that incorporates the operators and atoms in the given table, along with extra ops. |
Adds a new layer to this precedence table on the left, in a weakest-to-tightest ordering.
This is an alias for Level
.
This method associates to the left, so left-most applications are tighter binding (closer to the atoms) than those to the right.
It should not be mixed with (+<)
, as this can be create a confusing and less predictable precedence table.
:: Op a b | the lower precedence table. |
-> Prec a | the operators that make up the new level on the table. |
-> Prec b | a new table that incorporates the operators and atoms in the given table, along with extra ops. |
Adds a new layer to this precedence table on the right, in a tightest-to-weakest ordering.
This method associates to the right (with this table on the right!), so right-most applications are tighter binding (closer to the atoms) than those to the left.
It should not be mixed with (>+)
, as this can be create a confusing and less predictable precedence table.