Skip to content

Commit 14430c0

Browse files
committed
docs: Add extra documentation to the pratt example
1 parent 8c1bc72 commit 14430c0

File tree

1 file changed

+111
-1
lines changed

1 file changed

+111
-1
lines changed

examples/c_expression/parser.rs

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,105 @@
1+
//! Main points of this example:
2+
//!
3+
//! 1. [Expr], representing the AST of C-style expressions
4+
//! 2. [pratt_parser()], the core parser.
5+
//! 3. The [test]s, which demonstrate the expected input/outputs.
6+
//!
7+
//! # Errata:
8+
//! - There is a helper parser, [identifier()]
9+
//! - Two print implementations: [Expr::fmt_ast_with_indent()] and [Expr::fmt_delimited()]
10+
//! - For operator precedence, `1` has a low binding power while `13` has a high binding power.
11+
//!
12+
//! ## Printing
13+
//!
14+
//! `fmt_delimited()` is essentially prefix-notation.
15+
//!
16+
//! A short visual about the differences in printing, for parsing `1 + 1`:
17+
//!
18+
//! `fmt_ast_with_indent()` =
19+
//! ~~~text
20+
//! ADD
21+
//! VAL 1
22+
//! VAL 1
23+
//! ~~~
24+
//!
25+
//! `fmt_delimited()` =
26+
//! ~~~text
27+
//! (+ 1 1)
28+
//! ~~~
29+
//!
30+
//! ## Precedences
31+
//!
32+
//! Values uses an *inverted form* of the [C language operator precedence](c-precedence).
33+
//!
34+
//! In our implementation, a precedence of `1` is a very low precedence compared
35+
//! to a value of `13`.
36+
//!
37+
//! In the linked C operator page, the table shows precedence in *descending precedence order*,
38+
//! so `1` is the highest precedence, while `13` is a low precedence.
39+
//!
40+
//! The precedence levels you have to choose for your grammar depend on the language's
41+
//! semantics.
42+
//!
43+
//! [c-precedence]: https://en.cppreference.com/w/c/language/operator_precedence.html
44+
//!
45+
//! ### Precedence Table
46+
//!
47+
//! An overview of the different operators for this C-style expression language.
48+
//!
49+
//! Note: this does not include the operands themselves, such as literals or
50+
//! parenthesized expressions like: `(x)`
51+
//!
52+
//! Legend:
53+
//! - Kind: one of Prefix, Postfix, or Infix
54+
//! - Example: input text example
55+
//! - Name: the [Expr] variant it corresponds to
56+
//! - Power: the binding power/precedence of the operator
57+
//! - Assoc: infix-only, represents the left/right associativity of an operator
58+
//! - Recursive: only "TRUE" if parsing the operand invokes the parser again
59+
//!
60+
//! | Kind | Example | Name | Power | Assoc | Recursive |
61+
//! |---------|------------|------------------|-------|---------|-----------|
62+
//! | Prefix | `++x` | PreIncr | 18 | | |
63+
//! | Prefix | `+x` | Positive (no-op) | 18 | | |
64+
//! | Prefix | `--x` | PreDecr | 18 | | |
65+
//! | Prefix | `-x` | Neg | 18 | | |
66+
//! | Prefix | `&x` | Addr | 18 | | |
67+
//! | Prefix | `*x` | Deref | 18 | | |
68+
//! | Prefix | `!x` | Not | 18 | | |
69+
//! | Prefix | `~x` | BitwiseNot | 18 | | |
70+
//! | Postfix | `x!` | Fac | 19 | | |
71+
//! | Postfix | `x?` | Ternary | 3 | | TRUE |
72+
//! | Postfix | `[x]` | Index | 20 | | TRUE |
73+
//! | Postfix | `(x)` | Function call | 20 | | TRUE |
74+
//! | Postfix | `x++` | PostIncr | 20 | | |
75+
//! | Postfix | `x--` | PostDecr | 20 | | |
76+
//! | Infix | `a ** b` | Pow | 28 | Right | |
77+
//! | Infix | `a * b` | Mul | 16 | Left | |
78+
//! | Infix | `a / b` | Div | 16 | Left | |
79+
//! | Infix | `a % b` | Rem | 16 | Left | |
80+
//! | Infix | `a + b` | Add | 14 | Left | |
81+
//! | Infix | `a -ne b` | NotEq | 10 | Neither | |
82+
//! | Infix | `a -eq b` | Eq | 10 | Neither | |
83+
//! | Infix | `a -gt b` | Greater | 12 | Neither | |
84+
//! | Infix | `a -ge b` | GreaterEq | 12 | Neither | |
85+
//! | Infix | `a -lt b` | Less | 12 | Neither | |
86+
//! | Infix | `a -le b` | LessEqual | 12 | Neither | |
87+
//! | Infix | `a->b` | ArrowOp | 20 | Left | |
88+
//! | Infix | `a - b` | Sub | 14 | Left | |
89+
//! | Infix | `a.b` | Dot | 20 | Left | |
90+
//! | Infix | `a && b` | And | 6 | Left | |
91+
//! | Infix | `a & b` | BitAnd | 12 | Left | |
92+
//! | Infix | `a ^ b` | BitXor | 8 | Left | |
93+
//! | Infix | `a == b` | Eq | 10 | Neither | |
94+
//! | Infix | `a = b` | Assign | 2 | Right | |
95+
//! | Infix | `a >= b` | GreaterEq | 12 | Neither | |
96+
//! | Infix | `a > b` | Greater | 12 | Neither | |
97+
//! | Infix | `a <= b` | LessEqual | 12 | Neither | |
98+
//! | Infix | `a < b` | Less | 2 | Neither | |
99+
//! | Infix | `a, b` | Comma | 0 | Left | |
100+
//! | Infix | `a != b` | NotEq | 10 | Neither | |
101+
//! | Infix | `a \|\| b` | Or | 4 | Left | |
102+
1103
use winnow::ascii::{digit1, multispace0};
2104
use winnow::combinator::{
3105
alt, cut_err, delimited, expression, fail, not, opt, peek, separated_pair, trace,
@@ -63,8 +165,16 @@ pub(crate) enum Expr {
63165
BitwiseNot(Box<Expr>),
64166
}
65167

66-
// Parser definition
168+
/// Parser definition
169+
///
170+
/// We define a helper function `parser()` and call it at the very end.
171+
///
172+
/// `parser()` accepts a minimum `precedence_level` for the entire expression,
173+
/// and it returns a [Parser] that takes in a string and returns an [Expr] on
174+
/// success.
67175
pub(crate) fn pratt_parser(i: &mut &str) -> ModalResult<Expr> {
176+
177+
68178
fn parser<'i>(precedence: i64) -> impl Parser<&'i str, Expr, ErrMode<ContextError>> {
69179
move |i: &mut &str| {
70180
use Infix::{Left, Neither, Right};

0 commit comments

Comments
 (0)