pub struct Expression<I, O, ParseOperand, Pre, Post, Pix, E>{
precedence_level: i64,
parse_operand: ParseOperand,
parse_prefix: Pre,
parse_postfix: Post,
parse_infix: Pix,
i: PhantomData<I>,
o: PhantomData<O>,
e: PhantomData<E>,
}Expand description
A helper struct for expression().
Holds the configuration for the Pratt parser, including the operator and operand parsers. A precedence level can also be set, which is useful to disambiguate parse trees based on the parent operator’s precedence.
Implements Parser. When parsing an input, it applies
the Pratt parser.
Fields§
§precedence_level: i64§parse_operand: ParseOperand§parse_prefix: Pre§parse_postfix: Post§parse_infix: Pix§i: PhantomData<I>§o: PhantomData<O>§e: PhantomData<E>Implementations§
Source§impl<I, O, ParseOperand, Pre, Post, Pix, E> Expression<I, O, ParseOperand, Pre, Post, Pix, E>
impl<I, O, ParseOperand, Pre, Post, Pix, E> Expression<I, O, ParseOperand, Pre, Post, Pix, E>
Sourcepub fn prefix<NewParsePrefix>(
self,
parser: NewParsePrefix,
) -> Expression<I, O, ParseOperand, NewParsePrefix, Post, Pix, E>
pub fn prefix<NewParsePrefix>( self, parser: NewParsePrefix, ) -> Expression<I, O, ParseOperand, NewParsePrefix, Post, Pix, E>
Sets the prefix operator parser.
The parser should parse the input to a Prefix,
which contains the operator’s binding power and
a fold function which applies the operator to its
operands.
Sourcepub fn postfix<NewParsePostfix>(
self,
parser: NewParsePostfix,
) -> Expression<I, O, ParseOperand, Pre, NewParsePostfix, Pix, E>
pub fn postfix<NewParsePostfix>( self, parser: NewParsePostfix, ) -> Expression<I, O, ParseOperand, Pre, NewParsePostfix, Pix, E>
Sets the prefix operator parser.
The parser should parse the input to a Postfix,
which contains the operator’s binding power and
a fold function which applies the operator to its
operands.
Sourcepub fn infix<NewParseInfix>(
self,
parser: NewParseInfix,
) -> Expression<I, O, ParseOperand, Pre, Post, NewParseInfix, E>
pub fn infix<NewParseInfix>( self, parser: NewParseInfix, ) -> Expression<I, O, ParseOperand, Pre, Post, NewParseInfix, E>
Sets the prefix operator parser.
The parser should parse the input to a Infix,
which contains the operator’s binding power and
a fold function which applies the operator to its
operands.
Sourcepub fn current_precedence_level(
self,
level: i64,
) -> Expression<I, O, ParseOperand, Pre, Post, Pix, E>
pub fn current_precedence_level( self, level: i64, ) -> Expression<I, O, ParseOperand, Pre, Post, Pix, E>
Sets the precedence level for the current instance of the parser.
It defaults to 0, which is traditionally treated as the “lowest” possible precedence when parsing an expression.
This is useful to disambiguate grammars based on the parent operator’s precedence. This comes up primarily when parsing recursive expressions.
The parsing machinery underpinning Expression assumes that a “more
tightly binding” operator is numerically large, while a “more loosely
binding” operator is numerically small. For example, 13 is a higher
precedence level than 1 because 13 > 1.
Other ways of describing this relationship:
13has a higher precedence compared to113has a higher binding power compared to1
Note: Binding power and precedence both refer to the same concept and may be used interchangeably.
§Motivation
If you don’t understand why this is useful to have, this section tries to explain in more detail.
The [C-style Expressions][crate::_topic::arithmetic#c-style-expression] example has source code for parsing the expression described below, and can provide a clearer usage example.
Consider the following expression in the C language:
int x = (1 == 1 ? 0 : 1, -123); // <-- let's parse this
printf("%d\n", x); // -123Let’s look at the right-hand side of the expression on the first line, and replace some of the sub-expressions with symbols:
(1 == 1 ? 0 : 1, -123) // rhs
(a ? b : c, d ) // symbolic
(a ? b : c, d) // remove whitespace
(, (? a b c) d) // prefix notationWritten symbolically:
ais the condition, like1 == 1bis the value when the condition is truecis the value when the condition is falsedis a secondary expression unrelated to the ternary
In prefix notation, it’s easier to see the specific operators and what they bind to:
- COMMA (
,) binds to(? a b c)andd - TERNARY (
?) binds toa,b, andc
§Parsing c and d
Let’s focus on parsing the sub-expressions c and d, as that
motivates why a parser precedence level is necessary.
To parse c, we would really like to re-use the parser produced by
expression(), because c is really any valid expression that
can be parsed by expression() already.
However, we can’t re-use the parser naively. When parsing c, we need
to “escape” from the inner parser when encountering the comma separating
c from d.
The reason we have to “escape” is because of how operator precedence is
defined in the C language: the comma operator has the lowest precedence
among all the operators. When we’re parsing c, we’re in the context of
the ternary operator. We don’t want to parse any valid expression! Just
what the ternary operator captures.
That’s where the precedence level comes in: you specify the minimum precedence this parser is willing to accept. If you come across an expression in the top-level with a lower binding power than the starting precedence, you know to stop parsing.
The parsing machinery inside of Expression handles most of this for
you, but it can’t determine what the precedence level should be for a
given expression. That’s a language-specific detail, and it depends on
what you want to parse.
Trait Implementations§
Source§impl<I, O, Pop, Pre, Post, Pix, E> Parser<I, O, E> for Expression<I, O, Pop, Pre, Post, Pix, E>where
I: Stream + StreamIsPartial,
Pop: Parser<I, O, E>,
Pix: Parser<I, Infix<I, O, E>, E>,
Pre: Parser<I, Prefix<I, O, E>, E>,
Post: Parser<I, Postfix<I, O, E>, E>,
E: ParserError<I>,
impl<I, O, Pop, Pre, Post, Pix, E> Parser<I, O, E> for Expression<I, O, Pop, Pre, Post, Pix, E>where
I: Stream + StreamIsPartial,
Pop: Parser<I, O, E>,
Pix: Parser<I, Infix<I, O, E>, E>,
Pre: Parser<I, Prefix<I, O, E>, E>,
Post: Parser<I, Postfix<I, O, E>, E>,
E: ParserError<I>,
Source§fn parse_next(&mut self, input: &mut I) -> Result<O, E>
fn parse_next(&mut self, input: &mut I) -> Result<O, E>
Source§fn parse(
&mut self,
input: I,
) -> Result<O, ParseError<I, <E as ParserError<I>>::Inner>>where
Self: Sized,
I: Stream + StreamIsPartial,
E: ParserError<I>,
<E as ParserError<I>>::Inner: ParserError<I>,
fn parse(
&mut self,
input: I,
) -> Result<O, ParseError<I, <E as ParserError<I>>::Inner>>where
Self: Sized,
I: Stream + StreamIsPartial,
E: ParserError<I>,
<E as ParserError<I>>::Inner: ParserError<I>,
Source§fn parse_peek(&mut self, input: I) -> Result<(I, O), E>
fn parse_peek(&mut self, input: I) -> Result<(I, O), E>
Source§fn by_ref(&mut self) -> ByRef<'_, Self, I, O, E>where
Self: Sized,
fn by_ref(&mut self) -> ByRef<'_, Self, I, O, E>where
Self: Sized,
&mut Self as a parser Read moreSource§fn default_value<O2>(self) -> DefaultValue<Self, I, O, O2, E>
fn default_value<O2>(self) -> DefaultValue<Self, I, O, O2, E>
Source§fn void(self) -> Void<Self, I, O, E>where
Self: Sized,
fn void(self) -> Void<Self, I, O, E>where
Self: Sized,
Parser Read moreSource§fn output_into<O2>(self) -> OutputInto<Self, I, O, O2, E>
fn output_into<O2>(self) -> OutputInto<Self, I, O, O2, E>
std::convert::From Read moreSource§fn with_taken(self) -> WithTaken<Self, I, O, E>
fn with_taken(self) -> WithTaken<Self, I, O, E>
Source§fn span(self) -> Span<Self, I, O, E>
fn span(self) -> Span<Self, I, O, E>
Source§fn with_span(self) -> WithSpan<Self, I, O, E>
fn with_span(self) -> WithSpan<Self, I, O, E>
Source§fn map<G, O2>(self, map: G) -> Map<Self, G, I, O, O2, E>
fn map<G, O2>(self, map: G) -> Map<Self, G, I, O, O2, E>
Source§fn try_map<G, O2, E2>(self, map: G) -> TryMap<Self, G, I, O, O2, E, E2>where
Self: Sized,
G: FnMut(O) -> Result<O2, E2>,
I: Stream,
E: FromExternalError<I, E2> + ParserError<I>,
fn try_map<G, O2, E2>(self, map: G) -> TryMap<Self, G, I, O, O2, E, E2>where
Self: Sized,
G: FnMut(O) -> Result<O2, E2>,
I: Stream,
E: FromExternalError<I, E2> + ParserError<I>,
Result over the output of a parser. Read moreSource§fn verify_map<G, O2>(self, map: G) -> VerifyMap<Self, G, I, O, O2, E>
fn verify_map<G, O2>(self, map: G) -> VerifyMap<Self, G, I, O, O2, E>
Source§fn flat_map<G, H, O2>(self, map: G) -> FlatMap<Self, G, H, I, O, O2, E>
fn flat_map<G, H, O2>(self, map: G) -> FlatMap<Self, G, H, I, O, O2, E>
Source§fn and_then<G, O2>(self, inner: G) -> AndThen<Self, G, I, O, O2, E>
fn and_then<G, O2>(self, inner: G) -> AndThen<Self, G, I, O, O2, E>
Source§fn parse_to<O2>(self) -> ParseTo<Self, I, O, O2, E>
fn parse_to<O2>(self) -> ParseTo<Self, I, O, O2, E>
std::str::FromStr to the output of the parser Read more