Struct ielr::input::Production
source · pub struct Production {
pub symbols: Box<[Symbol]>,
/* private fields */
}
Expand description
A production of the grammar.
This can be used to:
- Retreive the right-hand side of the associated production via
Self::symbols
. - Set precedence levels.
- Set extra forbidden derivations in the right-hand side.
Fields§
§symbols: Box<[Symbol]>
The right-hand side of this production.
Implementations§
source§impl Production
impl Production
sourcepub fn set_left_precedence(
&mut self,
precedence_family: PrecedenceFamilyToken,
level: PrecedenceLevel
) -> &mut Self
pub fn set_left_precedence( &mut self, precedence_family: PrecedenceFamilyToken, level: PrecedenceLevel ) -> &mut Self
Add a precedence for the current production.
Any production (including this one) with
- the same precedence family
- strictly lower right precedence
will not be allowed to appear to the left of this production.
Examples found in repository?
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();
}
sourcepub fn set_right_precedence(
&mut self,
precedence_family: PrecedenceFamilyToken,
level: PrecedenceLevel
) -> &mut Self
pub fn set_right_precedence( &mut self, precedence_family: PrecedenceFamilyToken, level: PrecedenceLevel ) -> &mut Self
Add a precedence for the current production.
Any production (including this one) with
- the same precedence family
- strictly lower left precedence
will not be allowed to appear to the right of this production.
Examples found in repository?
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();
}
sourcepub fn forbid_derivation(
&mut self,
symbol_index: usize,
forbidden_production: ProdIdx
) -> Result<&mut Self, ForbidDerivationError>
pub fn forbid_derivation( &mut self, symbol_index: usize, forbidden_production: ProdIdx ) -> Result<&mut Self, ForbidDerivationError>
The symbols at symbol_index
of the production will not be able to derive
forbidden_production
.
Errors
This will return an error if
symbol_index
is out of bounds forSelf::symbols
, or refers to aToken
.symbol_index
refers to a differentNode
thanforbidden_production
.
Example
In rust, it is forbidden to chain comparison operator. As such, one could write:
const E: Node = Node(0);
const EQUAL: Token = match Token::new(1) {
Some(t) => t,
None => unreachable!()
};
let mut grammar = Grammar::new();
let comparison_prod = grammar.add_production(E, vec![Symbol::Node(E), Symbol::Token(EQUAL), Symbol::Node(E)]).unwrap();
let production = grammar.get_production_mut(comparison_prod).unwrap();
production
.forbid_derivation(0, comparison_prod).unwrap()
.forbid_derivation(2, comparison_prod).unwrap();
Note
This can be used to emulate operator precedence. However, it is recommended to
use the Self::set_left_precedence
and Self::set_right_precedence
methods
instead, as those are more versatile, ‘safer’ (they don’t remove any valid
parse), and lead to faster table generation.
Trait Implementations§
source§impl Clone for Production
impl Clone for Production
source§fn clone(&self) -> Production
fn clone(&self) -> Production
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more