@@ -8,6 +8,59 @@ use crate::{
88} ;
99
1010/// Parses an expression based on operator precedence.
11+ ///
12+ /// It uses a Pratt parsing algorithm, where operators are
13+ /// associated with a binding power. The higher the power,
14+ /// the more tightly an operator will bind to its operands.
15+ ///
16+ /// This method returns an [`Expression`], which configures
17+ /// the Pratt parser.
18+ ///
19+ /// Each operator type is configured with [`Prefix`], [`Postfix`],
20+ /// and [`Infix`]. These describe the operator's binding power,
21+ /// a function that applies the operator to its operand, and the
22+ /// operator's associativity (infix only).
23+ ///
24+ /// # Example
25+ ///
26+ /// Parsing a simple arithmetic expression without parenthesis.
27+ ///
28+ /// ```rust
29+ /// # use winnow::prelude::*;
30+ /// # use winnow::error::ContextError;
31+ /// # use winnow::ascii::digit1;
32+ /// # use winnow::combinator::{dispatch, fail};
33+ /// # use winnow::token::any;
34+ /// use winnow::combinator::expression;
35+ /// use winnow::combinator::{Prefix, Postfix, Infix};
36+ ///
37+ /// fn parser<'i>() -> impl Parser<&'i str, i32, ContextError> {
38+ /// move |i: &mut &str| {
39+ /// use Infix::*;
40+ /// expression(digit1.parse_to::<i32>()) // operands are 32-bit integers
41+ /// .prefix(dispatch! {any;
42+ /// '-' => Prefix(12, |_, a: i32| Ok(-a)),
43+ /// _ => fail,
44+ /// })
45+ /// .infix(dispatch! {any;
46+ /// '+' => Left(5, |_, a, b| Ok(a + b)),
47+ /// '-' => Left(5, |_, a, b| Ok(a - b)),
48+ /// '*' => Left(7, |_, a, b| Ok(a * b)),
49+ /// '/' => Left(7, |_, a: i32, b| Ok(a.checked_div(b).unwrap_or_default())),
50+ /// _ => fail,
51+ /// })
52+ /// .postfix(dispatch! {any;
53+ /// '!' => Postfix(15, |_, a| if a < 1 { Ok(1) } else { Ok((1..=a).fold(1, |acc, a| acc*a)) }),
54+ /// _ => fail,
55+ /// })
56+ /// .parse_next(i)
57+ /// }
58+ /// }
59+ ///
60+ /// assert_eq!(parser().parse("1+1"), Ok(2));
61+ /// assert_eq!(parser().parse("0!"), Ok(1));
62+ /// assert_eq!(parser().parse("-1*5*2*10+30/3!"), Ok(-95));
63+ /// ```
1164#[ doc( alias = "pratt" ) ]
1265#[ doc( alias = "separated" ) ]
1366#[ doc( alias = "shunting_yard" ) ]
4194 }
4295}
4396
97+ /// A helper struct for [`expression()`].
98+ ///
99+ /// Holds the configuration for the Pratt parser, including
100+ /// the operator and operand parsers. A precedence level can
101+ /// also be set, which is useful to disambiguate parse trees
102+ /// based on the parent operator's precedence.
103+ ///
104+ /// Implements [`Parser`]. When parsing an input, it applies
105+ /// the Pratt parser.
44106pub struct Expression < I , O , ParseOperand , Pre , Post , Pix , E >
45107where
46108 I : Stream + StreamIsPartial ,
@@ -63,6 +125,12 @@ where
63125 I : Stream + StreamIsPartial ,
64126 E : ParserError < I > ,
65127{
128+ /// Sets the prefix operator parser.
129+ ///
130+ /// The parser should parse the input to a [`Prefix`],
131+ /// which contains the operator's binding power and
132+ /// a fold function which applies the operator to its
133+ /// operands.
66134 #[ inline( always) ]
67135 pub fn prefix < NewParsePrefix > (
68136 self ,
@@ -83,6 +151,12 @@ where
83151 }
84152 }
85153
154+ /// Sets the prefix operator parser.
155+ ///
156+ /// The parser should parse the input to a [`Postfix`],
157+ /// which contains the operator's binding power and
158+ /// a fold function which applies the operator to its
159+ /// operands.
86160 #[ inline( always) ]
87161 pub fn postfix < NewParsePostfix > (
88162 self ,
@@ -103,6 +177,12 @@ where
103177 }
104178 }
105179
180+ /// Sets the prefix operator parser.
181+ ///
182+ /// The parser should parse the input to a [`Infix`],
183+ /// which contains the operator's binding power and
184+ /// a fold function which applies the operator to its
185+ /// operands.
106186 #[ inline( always) ]
107187 pub fn infix < NewParseInfix > (
108188 self ,
@@ -123,6 +203,10 @@ where
123203 }
124204 }
125205
206+ /// Sets the precedence level of the parser.
207+ ///
208+ /// This is useful to disambiguate grammars based on the parent operator's
209+ /// precedence.
126210 #[ inline( always) ]
127211 pub fn precedence_level (
128212 mut self ,
@@ -158,6 +242,7 @@ where
158242 }
159243}
160244
245+ // Opaque implementation of the Pratt parser.
161246fn expression_impl < I , O , Pop , Pre , Post , Pix , E > (
162247 i : & mut I ,
163248 parse_operand : & mut Pop ,
@@ -247,7 +332,13 @@ where
247332 Ok ( operand)
248333}
249334
250- pub struct Prefix < I , O , E > ( i64 , fn ( & mut I , O ) -> Result < O , E > ) ;
335+ /// A helper struct for [`expression()`].
336+ ///
337+ /// Represents a prefix operator.
338+ ///
339+ /// It requires an operator binding power, as well as a
340+ /// fold function which applies the operator.
341+ pub struct Prefix < I , O , E > ( pub i64 , pub fn ( & mut I , O ) -> Result < O , E > ) ;
251342
252343impl < I , O , E > Clone for Prefix < I , O , E > {
253344 #[ inline( always) ]
@@ -263,7 +354,13 @@ impl<I: Stream, O, E: ParserError<I>> Parser<I, Prefix<I, O, E>, E> for Prefix<I
263354 }
264355}
265356
266- pub struct Postfix < I , O , E > ( i64 , fn ( & mut I , O ) -> Result < O , E > ) ;
357+ /// A helper struct for [`expression()`].
358+ ///
359+ /// Represents a postfix operator.
360+ ///
361+ /// It requires an operator binding power, as well as a
362+ /// fold function which applies the operator.
363+ pub struct Postfix < I , O , E > ( pub i64 , pub fn ( & mut I , O ) -> Result < O , E > ) ;
267364
268365impl < I , O , E > Clone for Postfix < I , O , E > {
269366 #[ inline( always) ]
@@ -279,9 +376,22 @@ impl<I: Stream, O, E: ParserError<I>> Parser<I, Postfix<I, O, E>, E> for Postfix
279376 }
280377}
281378
379+ /// A helper struct for [`expression()`].
380+ ///
381+ /// Represents a prefix operator.
382+ ///
383+ /// It requires an operator binding power, as well as a
384+ /// fold function which applies the operator.
385+ ///
386+ /// Infix operators also have an associativity. Left-associative
387+ /// operators will bind more tightly to their rightmost operands,
388+ /// and it is the opposite for right-associative operators.
282389pub enum Infix < I , O , E > {
390+ /// Left-associative operator.
283391 Left ( i64 , fn ( & mut I , O , O ) -> Result < O , E > ) ,
392+ /// Right-associative operator.
284393 Right ( i64 , fn ( & mut I , O , O ) -> Result < O , E > ) ,
394+ /// Neither left or right associative.
285395 Neither ( i64 , fn ( & mut I , O , O ) -> Result < O , E > ) ,
286396}
287397
0 commit comments