use std::error::Error; use crate::tokenizer::{MotError, Token, TokenType, error}; #[derive(Debug, Clone)] pub struct Param { var_type: Token, var_name: Token, } #[derive(Debug, Clone)] pub enum Stmt { Expression(Expr), Var { name: Token, var_type: Token, initializer: Expr, }, Block(Vec), If { condition: Expr, then_branch: Box, else_branch: Box, }, While { condition: Expr, body: Box, }, Function { name: Token, params: Vec, body: Box, }, Return(Expr), } #[derive(Debug, Clone)] pub enum Expr { Binary { left: Box, op: Token, right: Box, }, Grouping(Box), Literal(Token), Unary { op: Token, right: Box, }, Variable(Token), Assign { name: Token, value: Box, }, Call { callee: Box, paren: Token, args: Vec, }, } pub struct Parser { tokens: Vec, current: usize, } impl Parser { pub fn new(tokens: Vec) -> Parser { Parser { tokens, current: 0 } } pub fn parse(mut self) -> Result, Box> { let mut statements = vec![]; while !self.eof() { statements.push(self.declaration()?); } Ok(statements) } fn declaration(&mut self) -> Result> { // TODO: synchronization after parse error if self.match_token(&[TokenType::KeywordLet]) { self.let_declaration() } else if self.match_token(&[TokenType::KeywordFunc]) { self.func_declaration() } else { self.statement() } } // TOOD: parse return type fn func_declaration(&mut self) -> Result> { let name = self.consume(TokenType::Identifier, "expected function name")?; self.consume(TokenType::LeftBracket, "expected '[' after function name")?; let mut params = vec![]; if !self.check(&TokenType::RightBracket) { loop { let var_name = self.consume(TokenType::Identifier, "expected parameter name")?; self.consume(TokenType::Colon, "expected ':' after parameter name")?; let var_type = self.consume(TokenType::Identifier, "expected parameter type")?; params.push(Param { var_type, var_name }); if !self.match_token(&[TokenType::Comma]) { break; } } } self.consume(TokenType::RightBracket, "expected ']' after arguments")?; let body = Box::new(self.block()?); Ok(Stmt::Function { name, params, body }) } fn let_declaration(&mut self) -> Result> { let name = self.consume(TokenType::Identifier, "expected variable name")?; self.consume(TokenType::Colon, "expected ':' after variable name")?; let var_type = self.consume(TokenType::Identifier, "expected variable type")?; self.consume(TokenType::Equal, "expected '=' after variable type")?; let initializer = self.expression()?; Ok(Stmt::Var { name, var_type, initializer, }) } fn block(&mut self) -> Result> { self.consume(TokenType::Indent, "expected an indent")?; let mut statements = vec![]; while !self.eof() && !self.match_token(&[TokenType::Dedent]) { statements.push(self.declaration()?); } Ok(Stmt::Block(statements)) } fn statement(&mut self) -> Result> { if self.match_token(&[TokenType::KeywordIf]) { self.if_statement() } else if self.match_token(&[TokenType::KeywordWhile]) { self.while_statement() } else if self.match_token(&[TokenType::KeywordReturn]) { self.return_statement() } else { Ok(Stmt::Expression(self.expression()?)) } } fn return_statement(&mut self) -> Result> { Ok(Stmt::Return(self.expression()?)) } fn if_statement(&mut self) -> Result> { let condition = self.expression()?; let then_branch = self.block()?; let else_branch = if self.match_token(&[TokenType::KeywordElse]) { if self.match_token(&[TokenType::KeywordIf]) { Box::new(self.if_statement()?) } else { Box::new(self.block()?) } } else { Box::new(Stmt::Block(vec![])) }; Ok(Stmt::If { condition, then_branch: Box::new(then_branch), else_branch, }) } fn while_statement(&mut self) -> Result> { let condition = self.expression()?; let body = self.block()?; Ok(Stmt::While { condition, body: Box::new(body), }) } fn expression(&mut self) -> Result> { self.assignment() } fn assignment(&mut self) -> Result> { let expr = self.pipe()?; if self.match_token(&[TokenType::Equal]) { let equals = self.previous().clone(); let value = self.assignment()?; return match expr { Expr::Variable(name) => Ok(Expr::Assign { name, value: Box::new(value), }), _ => return error!(equals.loc, "invalid assignment target"), }; } Ok(expr) } fn pipe(&mut self) -> Result> { let mut expr = self.logical_or()?; while self.match_token(&[TokenType::Pipe]) { let pipe = self.previous().clone(); let right = self.equality()?; match right { Expr::Call { callee, paren, args, } => { let mut new_args = args; new_args.insert(0, expr); expr = Expr::Call { callee, paren, args: new_args, } } _ => { return error!(pipe.loc, "tried to pipe into a non-call expression"); } }; } Ok(expr) } fn logical_or(&mut self) -> Result> { let mut expr = self.logical_and()?; while self.match_token(&[TokenType::Or]) { let op = self.previous().clone(); let right = self.logical_and()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn logical_and(&mut self) -> Result> { let mut expr = self.equality()?; while self.match_token(&[TokenType::And]) { let op = self.previous().clone(); let right = self.equality()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn equality(&mut self) -> Result> { let mut expr = self.comparison()?; while self.match_token(&[TokenType::DoubleEqual, TokenType::NotEqual]) { let op = self.previous().clone(); let right = self.comparison()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn comparison(&mut self) -> Result> { let mut expr = self.term()?; while self.match_token(&[ TokenType::Greater, TokenType::GreaterEqual, TokenType::LessEqual, TokenType::Less, ]) { let op = self.previous().clone(); let right = self.term()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn term(&mut self) -> Result> { let mut expr = self.factor()?; while self.match_token(&[TokenType::Plus, TokenType::Minus, TokenType::Xor]) { let op = self.previous().clone(); let right = self.factor()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn factor(&mut self) -> Result> { let mut expr = self.unary()?; while self.match_token(&[TokenType::Star, TokenType::Slash, TokenType::Mod]) { let op = self.previous().clone(); let right = self.unary()?; expr = Expr::Binary { left: Box::new(expr), op, right: Box::new(right), } } Ok(expr) } fn unary(&mut self) -> Result> { if self.match_token(&[TokenType::Bang, TokenType::Minus]) { let op = self.previous().clone(); let right = self.unary()?; return Ok(Expr::Unary { op, right: Box::new(right), }); } self.call() } fn call(&mut self) -> Result> { let mut expr = self.primary()?; while self.match_token(&[TokenType::LeftParen]) { let mut args = vec![]; if !self.check(&TokenType::RightParen) { loop { args.push(self.expression()?); if !self.match_token(&[TokenType::Comma]) { break; } } } let paren = self.consume(TokenType::RightParen, "expected ')' after arguments")?; expr = Expr::Call { callee: Box::new(expr), paren, args, }; } Ok(expr) } fn primary(&mut self) -> Result> { if self.match_token(&[TokenType::Number, TokenType::String]) { Ok(Expr::Literal(self.previous().clone())) } else if self.match_token(&[TokenType::LeftParen]) { let expr = self.expression()?; self.consume(TokenType::RightParen, "expected ')' after expression")?; Ok(Expr::Grouping(Box::new(expr))) } else if self.match_token(&[TokenType::Identifier]) { Ok(Expr::Variable(self.previous().clone())) } else { error!(self.peek().loc, "expected expression") } } fn consume(&mut self, token_type: TokenType, message: &str) -> Result> { if self.check(&token_type) { Ok(self.advance().clone()) } else { error!(self.previous().loc, format!("{}", message)) } } fn match_token(&mut self, token_types: &[TokenType]) -> bool { for x in token_types { if self.check(x) { self.advance(); return true; } } false } fn check(&self, token_type: &TokenType) -> bool { if self.eof() { false } else { self.peek().token_type == *token_type } } fn advance(&mut self) -> &Token { if !self.eof() { self.current += 1; } self.previous() } fn peek(&self) -> &Token { &self.tokens[self.current] } fn previous(&self) -> &Token { &self.tokens[self.current - 1] } fn eof(&self) -> bool { self.peek().token_type == TokenType::Eof } }