diff --git a/plang2/src/main.rs b/plang2/src/main.rs index bbc0a26..9265cb1 100644 --- a/plang2/src/main.rs +++ b/plang2/src/main.rs @@ -4,7 +4,7 @@ use plang2_lib::*; fn main() { let code = r#" - -( -5 + 2 ) * -( 2 * -5 ) + -( 2 - 6 ) + (-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30 "#; let mut lexer = Lexer::new(code); diff --git a/plang2_lib/src/ast.rs b/plang2_lib/src/ast.rs index 53dff35..5e55fa0 100644 --- a/plang2_lib/src/ast.rs +++ b/plang2_lib/src/ast.rs @@ -17,9 +17,18 @@ pub enum UnOpType { Neg } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FnCall { + pub fn_name: String, + pub args: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { Literal(Literal), + // contains variable name + Variable(String), + FnCall(FnCall), BinOp(BinOpType, Box, Box), UnOp(UnOpType, Box), } \ No newline at end of file diff --git a/plang2_lib/src/parser.rs b/plang2_lib/src/parser.rs index 1000dbf..b11cdda 100644 --- a/plang2_lib/src/parser.rs +++ b/plang2_lib/src/parser.rs @@ -1,5 +1,5 @@ use crate::{ - ast::{BinOpType, Expr, UnOpType}, + ast::{BinOpType, Expr, FnCall, UnOpType}, token::{Group, Op, Token, TokenStream}, }; @@ -15,7 +15,10 @@ pub struct Parser { /* GRAMMAR -expr_literal = "-" Literal | Literal +expr_literal = Literal +expr_fn_call = FnCall +expr_varibale = Variable +expr_value = expr_literal | expr_fn_call | expr_variable expr_term = "-" expr_term | "(" expr_add ")" | expr_literal expr_mul = expr_term (("*"|"/") expr_term)* expr_add = expr_mul (("+"|"-") expr_mul)* @@ -99,15 +102,64 @@ impl Parser { self.advance(); Expr::UnOp(UnOpType::Neg, self.parse_expr_term()?.into()) } - _ => self.parse_expr_literal()?, + _ => self.parse_expr_value()?, }; Ok(term) } + pub fn parse_expr_value(&mut self) -> PRes { + match self.curr() { + Some(Token::Literal(_)) => self.parse_expr_literal(), + Some(Token::Ident(_)) if matches!(self.peek(), Some(Token::Open(Group::Paren))) => { + self.parse_expr_fn_call() + } + Some(Token::Ident(_)) => self.parse_expr_varibale(), + _ => panic!("Expected value (literal, variable or function call)"), + } + } + + pub fn parse_expr_fn_call(&mut self) -> PRes { + // The first 2 checks are not really necessary for internal calls since parse_expr_value + // verifies the tokens already + let fn_name = match self.advance() { + Some(Token::Ident(ident)) => ident.clone(), + _ => panic!("Unexpected token while parsing function call. Expected identifier"), + }; + + if !matches!(self.advance(), Some(Token::Open(Group::Paren))) { + panic!("Unexpected token while parsing function call. Expected '('"); + } + + let mut args = Vec::new(); + + // TODO: This is *suboptimal* code + if !matches!(self.curr(), Some(Token::Close(Group::Paren))) { + args.push(self.parse_expr_add()?); + + while matches!(self.curr(), Some(Token::Comma)) { + self.advance(); + args.push(self.parse_expr_add()?); + } + } + + if !matches!(self.advance(), Some(Token::Close(Group::Paren))) { + panic!("Unexpected token while parsing function call. Expected '('"); + } + + Ok(Expr::FnCall(FnCall { fn_name, args })) + } + + pub fn parse_expr_varibale(&mut self) -> PRes { + match self.advance() { + Some(Token::Ident(ident)) => Ok(Expr::Variable(ident.clone())), + _ => panic!("Unexpected token while parsing variable. Expected identifier"), + } + } + pub fn parse_expr_literal(&mut self) -> PRes { match self.advance() { Some(Token::Literal(lit)) => Ok(Expr::Literal(lit.clone())), - _ => panic!("Unexpected token. Expected literal"), + _ => panic!("Unexpected token while parsing literal. Expected literal"), } } } @@ -115,51 +167,49 @@ impl Parser { #[cfg(test)] mod tests { use crate::{ - ast::{BinOpType, Expr, UnOpType}, + ast::{BinOpType, Expr, FnCall, UnOpType}, token::{Group, Literal, Op, Token, TokenStream}, Parser, }; - // fn parse_str(code: &str) -> Expr { - // let mut lexer = Lexer::new(code); - // let tokens = lexer.tokenize().unwrap(); - // let mut parser = Parser::new(tokens); - - // parser.parse().unwrap() - // } - #[test] fn test_groupings_neg() { - // let input = "(-(-5+2)*-(2*-5)+-(2-6)) % 30"; + // let input = "(-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30"; - // (-(-5+2)*-(2*-5)+-(2-6)) % 30 + let fn_name = "sqrt".to_string(); + let var_name = "a".to_string(); + + // (-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30 let input_toks = vec![ - Token::Open(Group::Paren), - Token::Op(Op::Sub), - Token::Open(Group::Paren), - Token::Op(Op::Sub), - Token::Literal(Literal::Int64(5)), - Token::Op(Op::Add), - Token::Literal(Literal::Int64(2)), - Token::Close(Group::Paren), - Token::Op(Op::Mul), - Token::Op(Op::Sub), - Token::Open(Group::Paren), - Token::Literal(Literal::Int64(2)), - Token::Op(Op::Mul), - Token::Op(Op::Sub), - Token::Literal(Literal::Int64(5)), - Token::Close(Group::Paren), - Token::Op(Op::Add), - Token::Op(Op::Sub), - Token::Open(Group::Paren), - Token::Literal(Literal::Int64(2)), - Token::Op(Op::Sub), - Token::Literal(Literal::Int64(6)), - Token::Close(Group::Paren), - Token::Close(Group::Paren), - Token::Op(Op::Mod), - Token::Literal(Literal::Int64(30)), + Token::Open(Group::Paren), // ( + Token::Op(Op::Sub), // - + Token::Open(Group::Paren), // ( + Token::Op(Op::Sub), // - + Token::Literal(Literal::Int64(5)), // 5 + Token::Op(Op::Add), // + + Token::Literal(Literal::Int64(2)), // 2 + Token::Close(Group::Paren), // ) + Token::Op(Op::Mul), // * + Token::Op(Op::Sub), // - + Token::Open(Group::Paren), // ( + Token::Literal(Literal::Int64(2)), // 2 + Token::Op(Op::Mul), // * + Token::Op(Op::Sub), // - + Token::Ident(fn_name.clone()), // sqrt + Token::Open(Group::Paren), // ( + Token::Literal(Literal::Int64(9)), // 9 + Token::Close(Group::Paren), // ) + Token::Close(Group::Paren), // ) + Token::Op(Op::Add), // + + Token::Op(Op::Sub), // - + Token::Open(Group::Paren), // ( + Token::Ident(var_name.clone()), // a + Token::Op(Op::Sub), // - + Token::Literal(Literal::Int64(6)), // 6 + Token::Close(Group::Paren), // ) + Token::Close(Group::Paren), // ) + Token::Op(Op::Mod), // % + Token::Literal(Literal::Int64(30)), // 30 ]; // -(-5+2) @@ -175,40 +225,44 @@ mod tests { )), ); - // -(2*-5) - let neg_grp_2_mul_neg_2 = Expr::UnOp( + // -(2*-sqrt(9)) + let neg_grp_2_mul_neg_sqrt = Expr::UnOp( UnOpType::Neg, Box::new(Expr::BinOp( BinOpType::Mul, Expr::Literal(Literal::Int64(2)).into(), Box::new(Expr::UnOp( UnOpType::Neg, - Expr::Literal(Literal::Int64(5)).into(), + Expr::FnCall(FnCall { + fn_name, + args: vec![Expr::Literal(Literal::Int64(9))], + }) + .into(), )), )), ); - // -(-5+2)*-(2*-5) + // -(-5+2) * -(2*-sqrt(9)) let mul_first = Expr::BinOp( BinOpType::Mul, neg_grp_neg_5_add_2.into(), - neg_grp_2_mul_neg_2.into(), + neg_grp_2_mul_neg_sqrt.into(), ); - // -(2-6) - let neg_grp_2_sub_6 = Expr::UnOp( + // -(a-6) + let neg_grp_a_sub_6 = Expr::UnOp( UnOpType::Neg, Box::new(Expr::BinOp( BinOpType::Sub, - Expr::Literal(Literal::Int64(2)).into(), + Expr::Variable(var_name).into(), Expr::Literal(Literal::Int64(6)).into(), )), ); - // -(-5+2)*-(2*-5)+-(2-6) - let left_of_mod = Expr::BinOp(BinOpType::Add, mul_first.into(), neg_grp_2_sub_6.into()); + // -(-5+2)*-(2*-sqrt(9)) + -(a-6) + let left_of_mod = Expr::BinOp(BinOpType::Add, mul_first.into(), neg_grp_a_sub_6.into()); - // (-(-5+2)*-(2*-5)+-(2-6)) % 30 + // (-(-5+2) * -(2*-sqrt(9)) + -(a-6)) % 30 let expected = Expr::BinOp( BinOpType::Mod, left_of_mod.into(),