Struct ielr::input::Grammar

source ·
pub struct Grammar { /* private fields */ }
Expand description

The grammar used to define the parser.

This contains productions: rules that describe how to create the various syntactic objects.

A production has the form node → symbols, where node is a Node and symbols is a list of Symbols.

Implementations§

source§

impl Grammar

source

pub fn new() -> Self

Creates a new grammar with no productions.

Examples found in repository?
examples/grammar_with_precedence.rs (line 78)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let precedence_family = grammar.add_precedence_family();

    // productions that need precedence annotations
    for (lhs, rhs, left, right) in [
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(STAR), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (EXPRESSION, vec![T(MINUS), N(EXPRESSION)], None, Some(5)),
    ] {
        let production = grammar.add_production(lhs, rhs).unwrap();
        let production = grammar.get_production_mut(production).unwrap();
        if let Some(left) = left {
            production.set_left_precedence(precedence_family, left);
        }
        if let Some(right) = right {
            production.set_right_precedence(precedence_family, right);
        }
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // This grammar only requires LALR(1)
        ielr::Algorithm::Lalr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
More examples
Hide additional examples
examples/grammar_with_conflicts.rs (line 82)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let add_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)])
        .unwrap();
    let sub_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)])
        .unwrap();
    let mul_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(STAR), N(EXPRESSION)])
        .unwrap();
    let div_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)])
        .unwrap();
    let neg_prod = grammar
        .add_production(EXPRESSION, vec![T(MINUS), N(EXPRESSION)])
        .unwrap();

    // Add conflicts solutions.

    let operator_to_production = HashMap::from([
        (PLUS, add_prod),
        (MINUS, sub_prod),
        (STAR, mul_prod),
        (SLASH, div_prod),
    ]);

    // - all binary operators are left-associative here
    // - '-' has precedence over all binary operators
    for operator in [PLUS, MINUS, STAR, SLASH] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator]),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(neg_prod),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
    }

    // operator with the same precedence
    for (operator1, operator2) in [(PLUS, MINUS), (STAR, SLASH)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator1]),
            over: ConflictingAction::Shift(Lookahead::Token(operator2)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator2]),
            over: ConflictingAction::Shift(Lookahead::Token(operator1)),
        });
    }

    // operator with the different precedence
    for (prefer, over) in [(STAR, PLUS), (STAR, MINUS), (SLASH, PLUS), (SLASH, MINUS)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Shift(Lookahead::Token(prefer)),
            over: ConflictingAction::Reduce(operator_to_production[&over]),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&prefer]),
            over: ConflictingAction::Shift(Lookahead::Token(over)),
        });
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // We are required to specify LR(1) when using conflict resolution.
        ielr::Algorithm::Lr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
source

pub fn add_production( &mut self, lhs: Node, rhs: Vec<Symbol> ) -> Result<ProdIdx, AddProductionError>

Add a production to the grammar, and returns a ProdIdx than can be used to retrieve it.

Returns Err(AddProductionError) if rhs.len() > u16::MAX, or if there is already u16::MAX productions associated with lhs.

Examples found in repository?
examples/grammar_with_precedence.rs (line 117)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let precedence_family = grammar.add_precedence_family();

    // productions that need precedence annotations
    for (lhs, rhs, left, right) in [
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(STAR), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (EXPRESSION, vec![T(MINUS), N(EXPRESSION)], None, Some(5)),
    ] {
        let production = grammar.add_production(lhs, rhs).unwrap();
        let production = grammar.get_production_mut(production).unwrap();
        if let Some(left) = left {
            production.set_left_precedence(precedence_family, left);
        }
        if let Some(right) = right {
            production.set_right_precedence(precedence_family, right);
        }
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // This grammar only requires LALR(1)
        ielr::Algorithm::Lalr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
More examples
Hide additional examples
examples/grammar_with_conflicts.rs (line 121)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let add_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)])
        .unwrap();
    let sub_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)])
        .unwrap();
    let mul_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(STAR), N(EXPRESSION)])
        .unwrap();
    let div_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)])
        .unwrap();
    let neg_prod = grammar
        .add_production(EXPRESSION, vec![T(MINUS), N(EXPRESSION)])
        .unwrap();

    // Add conflicts solutions.

    let operator_to_production = HashMap::from([
        (PLUS, add_prod),
        (MINUS, sub_prod),
        (STAR, mul_prod),
        (SLASH, div_prod),
    ]);

    // - all binary operators are left-associative here
    // - '-' has precedence over all binary operators
    for operator in [PLUS, MINUS, STAR, SLASH] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator]),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(neg_prod),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
    }

    // operator with the same precedence
    for (operator1, operator2) in [(PLUS, MINUS), (STAR, SLASH)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator1]),
            over: ConflictingAction::Shift(Lookahead::Token(operator2)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator2]),
            over: ConflictingAction::Shift(Lookahead::Token(operator1)),
        });
    }

    // operator with the different precedence
    for (prefer, over) in [(STAR, PLUS), (STAR, MINUS), (SLASH, PLUS), (SLASH, MINUS)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Shift(Lookahead::Token(prefer)),
            over: ConflictingAction::Reduce(operator_to_production[&over]),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&prefer]),
            over: ConflictingAction::Shift(Lookahead::Token(over)),
        });
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // We are required to specify LR(1) when using conflict resolution.
        ielr::Algorithm::Lr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
source

pub fn add_conflict_solution(&mut self, conflict_solution: ConflictSolution)

Add a solution to a LR conflict to the grammar.

Note

When using conflict solutions, the LALR algorithm might remove seemingly valid parses.

To avoid this, conflict resolution is only applied when using the LR algorithm.

Examples found in repository?
examples/grammar_with_conflicts.rs (lines 152-155)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let add_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)])
        .unwrap();
    let sub_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)])
        .unwrap();
    let mul_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(STAR), N(EXPRESSION)])
        .unwrap();
    let div_prod = grammar
        .add_production(EXPRESSION, vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)])
        .unwrap();
    let neg_prod = grammar
        .add_production(EXPRESSION, vec![T(MINUS), N(EXPRESSION)])
        .unwrap();

    // Add conflicts solutions.

    let operator_to_production = HashMap::from([
        (PLUS, add_prod),
        (MINUS, sub_prod),
        (STAR, mul_prod),
        (SLASH, div_prod),
    ]);

    // - all binary operators are left-associative here
    // - '-' has precedence over all binary operators
    for operator in [PLUS, MINUS, STAR, SLASH] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator]),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(neg_prod),
            over: ConflictingAction::Shift(Lookahead::Token(operator)),
        });
    }

    // operator with the same precedence
    for (operator1, operator2) in [(PLUS, MINUS), (STAR, SLASH)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator1]),
            over: ConflictingAction::Shift(Lookahead::Token(operator2)),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&operator2]),
            over: ConflictingAction::Shift(Lookahead::Token(operator1)),
        });
    }

    // operator with the different precedence
    for (prefer, over) in [(STAR, PLUS), (STAR, MINUS), (SLASH, PLUS), (SLASH, MINUS)] {
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Shift(Lookahead::Token(prefer)),
            over: ConflictingAction::Reduce(operator_to_production[&over]),
        });
        grammar.add_conflict_solution(ConflictSolution {
            prefer: ConflictingAction::Reduce(operator_to_production[&prefer]),
            over: ConflictingAction::Shift(Lookahead::Token(over)),
        });
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // We are required to specify LR(1) when using conflict resolution.
        ielr::Algorithm::Lr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
source

pub fn add_precedence_family(&mut self) -> PrecedenceFamilyToken

Generate a new precedence family.

Note that using multiple precedence families on the same production may not be a good idea.

Examples found in repository?
examples/grammar_with_precedence.rs (line 120)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let precedence_family = grammar.add_precedence_family();

    // productions that need precedence annotations
    for (lhs, rhs, left, right) in [
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(STAR), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (EXPRESSION, vec![T(MINUS), N(EXPRESSION)], None, Some(5)),
    ] {
        let production = grammar.add_production(lhs, rhs).unwrap();
        let production = grammar.get_production_mut(production).unwrap();
        if let Some(left) = left {
            production.set_left_precedence(precedence_family, left);
        }
        if let Some(right) = right {
            production.set_right_precedence(precedence_family, right);
        }
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // This grammar only requires LALR(1)
        ielr::Algorithm::Lalr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
source

pub fn get_all_nodes(&self) -> impl Iterator<Item = Node> + '_

Get all the nodes that appear as the right-hand side of a production in the grammar.

source

pub fn get_conflict_solutions(&self) -> &[ConflictSolution]

Get all conflict solutions added with Self::add_conflict_solution.

source

pub fn get_conflict_solutions_mut(&mut self) -> &mut [ConflictSolution]

Get all conflict solutions added with Self::add_conflict_solution.

source

pub fn get_production(&self, prod_idx: ProdIdx) -> Option<&Production>

Get the production associated with prod_idx.

source

pub fn get_production_mut( &mut self, prod_idx: ProdIdx ) -> Option<&mut Production>

Get the production associated with prod_idx.

Examples found in repository?
examples/grammar_with_precedence.rs (line 151)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
fn main() {
    use Symbol::{Node as N, Token as T};

    let mut grammar = Grammar::new();
    // productions that do not need precedence annotations
    for (lhs, rhs) in [
        (START, vec![N(STATEMENTS)]),
        (STATEMENTS, vec![N(STATEMENT), N(STATEMENTS)]),
        (STATEMENTS, vec![]),
        (STATEMENT, vec![N(FUNCTION)]),
        (STATEMENT, vec![T(RETURN_KW), N(EXPRESSION), T(SEMICOLON)]),
        (
            STATEMENT,
            vec![T(LET_KW), T(IDENT), T(EQUAL), N(EXPRESSION), T(SEMICOLON)],
        ),
        (STATEMENT, vec![N(EXPRESSION), T(SEMICOLON)]),
        (
            FUNCTION,
            vec![
                T(FN_KW),
                T(IDENT),
                T(PARENTHESIS_LEFT),
                N(FUNCTION_ARGS),
                T(PARENTHESIS_RIGHT),
                T(BRACE_LEFT),
                N(STATEMENTS),
                T(BRACE_RIGHT),
            ],
        ),
        (
            FUNCTION_ARGS,
            vec![N(FUNCTION_ARG), T(COMMA), N(FUNCTION_ARGS)],
        ),
        (FUNCTION_ARGS, vec![N(FUNCTION_ARG)]),
        (FUNCTION_ARGS, vec![]),
        (FUNCTION_ARG, vec![T(IDENT)]),
        (EXPRESSION, vec![T(INT)]),
        (EXPRESSION, vec![T(IDENT)]),
        (ARGS, vec![N(EXPRESSION), T(COMMA), N(ARGS)]),
        (ARGS, vec![N(EXPRESSION)]),
        (ARGS, vec![]),
    ] {
        grammar.add_production(lhs, rhs).unwrap();
    }

    let precedence_family = grammar.add_precedence_family();

    // productions that need precedence annotations
    for (lhs, rhs, left, right) in [
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(PLUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(MINUS), N(EXPRESSION)],
            Some(1),
            Some(2),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(STAR), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (
            EXPRESSION,
            vec![N(EXPRESSION), T(SLASH), N(EXPRESSION)],
            Some(3),
            Some(4),
        ),
        (EXPRESSION, vec![T(MINUS), N(EXPRESSION)], None, Some(5)),
    ] {
        let production = grammar.add_production(lhs, rhs).unwrap();
        let production = grammar.get_production_mut(production).unwrap();
        if let Some(left) = left {
            production.set_left_precedence(precedence_family, left);
        }
        if let Some(right) = right {
            production.set_right_precedence(precedence_family, right);
        }
    }

    // Now we build the parsing table !
    let (_tables, _statistics) = ielr::compute_table(
        // This grammar only requires LALR(1)
        ielr::Algorithm::Lalr(std::num::NonZeroU8::new(1).unwrap()),
        // We do not care about a maximum number of states
        &grammar,
        [START],
    )
    .unwrap();
}
source

pub fn get_rhs(&self, prod_idx: ProdIdx) -> Option<&[Symbol]>

Get the right-hand side of the production associated with prod_idx.

source

pub fn get_all_productions( &self ) -> impl Iterator<Item = (ProdIdx, &[Symbol])> + '_

Get all the productions in the grammar.

source

pub fn get_node_productions( &self, node: Node ) -> impl Iterator<Item = (ProdIdx, &Production)> + '_

Get all the productions for node node.

Trait Implementations§

source§

impl Clone for Grammar

source§

fn clone(&self) -> Grammar

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Grammar

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Grammar

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.