dust-bunny/src/parse.rs

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!(),
}
}