1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
* Copyright 2022 Arnaud Golfouse
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
//! Structures to build your [`Grammar`].
//!
//! The [`Grammar`] will then be used as input to
//! [`compute_table`](crate::compute_table).
//!
//! # Note on conflicts and their resolution
//!
//! When trying to write a LR(1) grammar, one almost always stumble upon _conflicts_:
//! places in the grammar where the parser generator thinks there is an ambiguity.
//! Those will be reported when calling the [`compute_table`](crate::compute_table)
//! function: it will return [`Error::Conflict`](crate::output::Error::Conflict).
//!
//! It should be noted that conflicts are usually resolved when dealing with
//! expressions (aka `E + E`, is it left or right associative ?). In most other cases,
//! the actual grammar should be changed in order to avoid the conflict.
//!
//! This crate provides two ways of dealing with such conflicts:
//! - **conflict resolution**: by using the [`Grammar::add_conflict_solution`] method,
//! you can resolve specific conflict. In a parser generator, those may be added in
//! bulk when resolving conflicts related to expressions precedence.
//!
//! See [ConflictSolution] for an example.
//! - **precedence annotations**: you can set the precedence of a particular
//! expression, by using [`Production::set_left_precedence`] and
//! [`Production::set_right_precedence`]:
//! ```rust
//! # use ielr::input::{Node, Grammar, Token, Symbol};
//! let expr = Node(0);
//! let plus = Token::new(1).unwrap();
//! let times = Token::new(2).unwrap();
//! let mut grammar = Grammar::new();
//! let add_prod = grammar.add_production(expr, vec![Symbol::Node(expr), Symbol::Token(plus), Symbol::Node(expr)]).unwrap();
//! let mul_prod = grammar.add_production(expr, vec![Symbol::Node(expr), Symbol::Token(times), Symbol::Node(expr)]).unwrap();
//! let precedence_family = grammar.add_precedence_family();
//! grammar
//! .get_production_mut(add_prod)
//! .unwrap()
//! .set_left_precedence(precedence_family, 1)
//! .set_right_precedence(precedence_family, 2);
//! grammar
//! .get_production_mut(mul_prod)
//! .unwrap()
//! .set_left_precedence(precedence_family, 3)
//! .set_right_precedence(precedence_family, 4);
//! ```
//!
//! ## Remark
//! On big grammars (like Rust's 😉), precedence annotations slow the generator
//! considerably. In should be fine on small/medium grammars though.
use crateNonZero;
pub use ;
use fmt;
/// A token of the grammar.
///
/// Also called a terminal in some literature.
///
/// A token is a single 'word' in the text. For example, in the following Rust code:
/// ```
/// let x: i32 = 1 + 2;
/// ```
/// The list of tokens (excluding whitespace) would be
/// `["let", "x", ":", "i32", "=", "1", "+", "2", ";"]`.
pub type Token = ;
/// A node of the grammar.
///
/// Also called a non-terminal in some literature.
///
/// A node is a lexical element of the text, made of tokens (a node may contain 0, 1 or
/// more tokens). For example, in the following Rust code:
/// ```
/// let x: i32 = 1 + 2;
/// ```
/// The grammar would look like this:
/// ```text
/// Statement → 'let' Pattern ':' Type '=' Expression ';'
/// ```
/// As such, the nodes would be `"x"`, `"i32"`, `"1 + 2"` and the whole statement (and
/// maybe other sub-nodes).
;
/// A symbol of the grammar, either a [`Token`] or a [`Node`].