73 lines
1.9 KiB
Rust
73 lines
1.9 KiB
Rust
use crate::ast::*;
|
|
use pest::iterators::*;
|
|
use pest::Parser;
|
|
use pest_derive::Parser as DeriveParser;
|
|
|
|
#[derive(DeriveParser)]
|
|
#[grammar = "dust_bunny.pest"]
|
|
pub struct PestParser;
|
|
|
|
pub type PestPairs<'a> = Pairs<'a, Rule>;
|
|
pub type PestPair<'a> = Pair<'a, Rule>;
|
|
|
|
pub fn parse_branch(body: &str) -> BranchBody<'_> {
|
|
let rule = Rule::branch;
|
|
let pairs = PestParser::parse(rule, body).unwrap();
|
|
|
|
println!("{:#?}", pairs);
|
|
|
|
let mut statements = Vec::new();
|
|
let mut tail_expr = None;
|
|
|
|
for pair in pairs {
|
|
match pair.as_rule() {
|
|
Rule::let_stmt => {
|
|
let mut tok = pair.into_inner();
|
|
let ident = tok.next().unwrap().into();
|
|
let expr = parse_expr(tok.next().unwrap());
|
|
statements.push(Statement::Let { ident, expr });
|
|
}
|
|
Rule::expr => {
|
|
tail_expr = Some(Box::new(parse_expr(pair)));
|
|
break;
|
|
}
|
|
_ => unimplemented!(),
|
|
};
|
|
}
|
|
|
|
BranchBody {
|
|
statements,
|
|
tail_expr,
|
|
}
|
|
}
|
|
|
|
pub fn parse_expr<'a>(mut pair: PestPair<'a>) -> Expr<'a> {
|
|
assert_eq!(pair.as_rule(), Rule::expr);
|
|
|
|
let mut pairs = pair.into_inner();
|
|
let first_term = pairs.next().unwrap();
|
|
let mut expr = parse_term(first_term);
|
|
|
|
while pairs.peek().is_some() {
|
|
let op = pairs.next().unwrap().into();
|
|
let lhs = expr.clone();
|
|
let rhs = parse_term(pairs.next().unwrap());
|
|
let sides = Box::new((lhs, rhs));
|
|
expr = Expr::BinaryOp(op, sides);
|
|
}
|
|
|
|
expr
|
|
}
|
|
|
|
pub fn parse_term<'a>(mut pair: PestPair<'a>) -> Expr<'a> {
|
|
assert_eq!(pair.as_rule(), Rule::term);
|
|
|
|
let term = pair.into_inner().next().unwrap();
|
|
|
|
match term.as_rule() {
|
|
Rule::identifier => Expr::Local(term.as_span().into()),
|
|
Rule::int => Expr::Literal(Literal::DecimalInteger(term.as_span().into())),
|
|
_ => unimplemented!(),
|
|
}
|
|
}
|