use pest::{iterators::Pair, Parser}; use pest_derive::Parser; use crate::{expression::Expression, statement::Statement, value::Value}; #[derive(Parser)] #[grammar = "grammar.pest"] pub struct LangParser; pub fn parse(source: &S) -> (Statement, FuncHolder) { let source = source.to_string(); let pairs = LangParser::parse(Rule::root_statement, &source).unwrap(); handle_rules(pairs) } type Func = (String, Vec, Vec); #[derive(Default)] pub struct FuncHolder(Vec); impl FuncHolder { fn insert(mut self, name: String, params: Vec, body: Vec) -> Self { self.0.push((name, params, body)); self } } impl Extend for FuncHolder { fn extend(&mut self, iter: T) where T: IntoIterator, { self.0.extend(iter); } } impl Extend for FuncHolder { fn extend(&mut self, iter: T) where T: IntoIterator, { self.0 .extend(iter.into_iter().flat_map(|h| h.0.into_iter())); } } impl IntoIterator for FuncHolder { type Item = Func; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } fn handle_rules(mut p: pest::iterators::Pairs) -> (Statement, FuncHolder) { let z = p.next().unwrap(); parse_statement(z) } fn parse_statement(pair: Pair) -> (Statement, FuncHolder) { match pair.as_rule() { Rule::root_statement => { let (z, f) = pair.into_inner().map(parse_statement).unzip(); (Statement::Body(z), f) } Rule::while_block => { let mut inner = pair.into_inner(); let expr = inner.next().unwrap(); let body = inner.next().unwrap(); ( Statement::While(parse_expression(expr), Box::new(parse_statement(body).0)), FuncHolder::default(), ) } Rule::if_block => { let mut inner = pair.into_inner(); let mut the_list = vec![]; let mut the_else = None; while let Some(expr) = inner.next() { if expr.as_rule() == Rule::expression { let body = inner.next().unwrap(); the_list.push((parse_expression(expr), parse_statement(body).0)); } else { the_else = Some(Box::new(parse_statement(expr).0)); } } (Statement::If(the_list, the_else), FuncHolder::default()) } Rule::assignment => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let expr = inner.next().unwrap(); ( Statement::Assignment(name.as_str().to_string(), parse_expression(expr), false), FuncHolder::default(), ) } Rule::assignment_let => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let expr = inner.next().unwrap(); ( Statement::Assignment(name.as_str().to_string(), parse_expression(expr), true), FuncHolder::default(), ) } Rule::expression => ( Statement::Expression(parse_expression(pair)), FuncHolder::default(), ), Rule::statement => { let inner = pair.into_inner().next().unwrap(); parse_statement(inner) } Rule::block => { let (z, _): (_, FuncHolder) = pair.into_inner().map(parse_statement).unzip(); (Statement::Body(z), FuncHolder::default()) } Rule::def => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let args = inner .next() .unwrap() .into_inner() .map(|a| a.as_str().to_string()) .collect(); let body = inner.next().unwrap(); let body = parse_statement(body); ( Statement::Body(vec![]), FuncHolder::default().insert(name.as_str().to_string(), args, vec![body.0]), ) } Rule::EOI => (Statement::Body(vec![]), FuncHolder::default()), x => unreachable!("How did we get to {:?}", x), } } fn parse_expression(pair: Pair) -> Expression { match pair.as_rule() { Rule::expression => { let mut inner = pair.into_inner(); parse_expression(inner.next().unwrap()) } Rule::equality | Rule::inequality | Rule::sum | Rule::product => { let mut inner = pair.into_inner(); let lhs = parse_expression(inner.next().unwrap()); if let Some(op) = inner.next() { let rhs = parse_expression(inner.next().unwrap()); Expression::Binary(Box::new(lhs), op.as_str().parse().unwrap(), Box::new(rhs)) } else { lhs } } Rule::value => { let mut inner = pair.into_inner(); let v = parse_value(inner.next().unwrap()); if let Some((name, args)) = method_call(inner.next().unwrap()) { Expression::CallMethod(Box::new(v), name, args) } else { v } } _ => unreachable!(), } } fn method_call(pair: Pair) -> Option<(String, Vec)> { match pair.as_rule() { Rule::method_call => { let mut inner = pair.into_inner(); if let Some(name) = inner.next() { let args = inner .next() .unwrap() .into_inner() .map(parse_expression) .collect(); Some((name.as_str().to_string(), args)) } else { None } } _ => None, } } fn parse_value(pair: Pair) -> Expression { match pair.as_rule() { Rule::const_value => { Expression::Constant(parse_const_value(&pair.into_inner().next().unwrap())) } Rule::identifier => Expression::Variable(pair.as_str().to_string()), Rule::call => { let mut inner = pair.into_inner(); let name = inner.next().unwrap(); let args = inner .next() .unwrap() .into_inner() .map(parse_expression) .collect(); Expression::Call(name.as_str().to_string(), args) } Rule::parens => { let mut inner = pair.into_inner(); parse_expression(inner.next().unwrap()) } _ => unreachable!(), } } fn parse_const_value(pair: &Pair) -> Value { match pair.as_rule() { Rule::number => { if let Ok(f) = pair.as_str().parse::() { Value::Int(f) } else if let Ok(f) = pair.as_str().parse::() { Value::Float(f) } else { unreachable!() } } Rule::string => Value::String(pair.as_str().to_string()), Rule::boolean => Value::Bool(pair.as_str() == "true"), Rule::char => Value::Char(pair.as_str().chars().next().unwrap()), _ => unreachable!(), } }