Standard parser definitions typically operate solely on the input string. However, when generating an AST, you often need external context or configuration flags to influence how nodes are built.
Consider a scenario where you want to apply a multiplier to every numeric literal encountered during parsing. You can declare a state parameter directly in the grammar definition:
grammar(multiplier: i32);
This multiplier variable becomes available within your grammar rules. For instance, the Num rule can utilize this value to transform the token immediately:
Num: i32 = {
r"[0-9]+" => i32::from_str(<>).unwrap() * multiplier,
};
When invoking the parser, you provide the state value as the first argument before the input string:
#[test]
fn test_scaled_calculation() {
let factor = 2;
let result = calculator8::ExprParser::new()
.parse(factor, "11 * 22 + 33")
.unwrap();
// Expected: 11*2=22, 22*2=44, 33*2=66
assert_eq!(&format!("{:?}", result), "((22 * 44) + 66)");
}
For complex use cases involving custom tree structures, passing state allows the parser to construct specific AST nodes dynamically based on the provided context.
Constraint: The state parameter must implement the Copy trait. If you need to pass a type that does not implement Copy, pass a reference to the data instead of the value itself.