I have an example Pest grammar:
WHITESPACE = _{ " " }
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
int_literal = { DECIMAL_NUMBER+ }
assignment_op = { ":=" }
formula = { (identifier ~ assignment_op ~ int_literal) | int_literal }
file = { formula ~ EOI }
and a pest-ast derives:
extern crate pest_derive;
extern crate from_pest;
extern crate pest_ast;
extern crate pest;
mod parser {
#[derive(Parser)]
#[grammar = "talk/formula.pest"]
pub struct Parser;
}
mod ast {
use super::parser::Rule;
use pest::Span;
fn span_into_str(span: Span) -> &str {
span.as_str()
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::int_literal))]
pub struct IntLiteral {
#[pest_ast(outer(with(span_into_str), with(str::parse::<i64>), with(Result::unwrap)))]
pub value: i64
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::identifier))]
pub struct Identifier {
#[pest_ast(inner(with(span_into_str), with(String::from)))]
pub value: String
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::assignment_op))]
pub struct AssignmentOp {
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::formula))]
pub enum Formula {
Assignment {
lvalue: Identifier,
a: AssignmentOp, // can I skip this?
rvalue: IntLiteral,
},
IntLiteral {
rvalue: IntLiteral,
}
}
#[cfg(test)]
mod tests {
use super::*;
use super::ast::*;
use pest::Parser;
use from_pest::FromPest;
#[test]
fn test_formula0() {
let source = "a := 12";
let mut parse_tree = parser::Parser::parse(parser::Rule::formula, source).unwrap();
println!("parse tree = {:#?}", parse_tree);
let syntax_tree: Formula = Formula::from_pest(&mut parse_tree).expect("infallible");
println!("syntax tree = {:#?}", syntax_tree);
}
}
Running the test, I'm getting infallible: NoMatch
panic.
- Does pest-ast even support deriving enum variants with fields?
- Can I match enum variant to a parenthesed
()
group of terminals? - Can I skip some terminals? I don't exactly need to know
:=
was used if I get anAssignmentExpression { lvalue, rvalue }
in the end.
I found an example in pest-ast issue #8. Grammar rules:
correspond to code:
Once I knew I was on the right track, I figured out the error in my code, completely unrelated to the question asked. It was that
Identifier
rule should useouter
span instead ofinner
.The most useful debugging tool was to print the raw syntax tree the
Identifier
rule produced:I also had to remove
struct
inside anenum
to haveFormula
compile:The answers to the questions:
Yes, example above.
No answer yet. This hasn't worked for me.
pest-ast
works with the tree produced by pest. In order to skip something, make it a silent rule in the source grammar.