diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4aa9c42 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["Peekable"] +} diff --git a/src/frontend.rs b/src/frontend.rs index 6befa94..b77d9b4 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -1,6 +1,6 @@ use std::process; -use crate::parser::{self, Parser}; +use crate::parser::Parser; pub fn repl() { // Read-Eval-Print Loop diff --git a/src/lexer.rs b/src/lexer.rs index 2fb4ba4..ae6861a 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -40,7 +40,7 @@ pub mod interpreter { match token.as_str() { "(" => Some(Token::OpenParen), ")" => Some(Token::CloseParen), - "+" | "-" | "*" | "/" => Some(Token::BinaryOperator(token)), + "+" | "-" | "*" | "/" | "%" => Some(Token::BinaryOperator(token)), "=" => Some(Token::Equals), _ => { diff --git a/src/parser.rs b/src/parser.rs index 2673d09..c420047 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,6 @@ use std::process; -use crate::ast::{BinaryExpr, Expr, Identifier, NodeType, NumericLiteral, Program, Stmt}; +use crate::ast::{BinaryExpr, Identifier, NodeType, NumericLiteral, Program}; use crate::lexer::interpreter; pub struct Parser { @@ -13,38 +13,56 @@ impl Parser { tokens: interpreter::tokenize(source_code).into_iter().peekable(), } } - pub fn produce_ast(&mut self) -> Program { let mut program = Program { body: vec![] }; - while let Some(t) = self.tokens.next() { - program.body.push(self.parse_stmt(t)); + // Keep parsing statements until we hit EOF + while let Some(token) = self.tokens.peek() { + if matches!(token, interpreter::Token::EOF) { + break; + } + program.body.push(self.parse_stmt()); } program } - fn parse_stmt(&mut self, t: interpreter::Token) -> NodeType { - // skip to parse_expr - self.parse_expr(t) + fn parse_stmt(&mut self) -> NodeType { + self.parse_expr() } - fn parse_expr(&mut self, t: interpreter::Token) -> NodeType { - self.parse_additive_expr(t) + fn parse_expr(&mut self) -> NodeType { + self.parse_additive_expr() } - fn parse_primary_expr(&mut self, t: interpreter::Token) -> NodeType { + fn parse_primary_expr(&mut self) -> NodeType { use crate::ast::NodeType; use interpreter::Token; + // Advance and grab the current token + let t = match self.tokens.next() { + Some(token) => token, + None => return NodeType::EOF, + }; + match t { Token::Identifier(i) => NodeType::Identifier(Identifier { symbol: i.clone() }), Token::Number(n) => NodeType::NumericLiteral(NumericLiteral { - value: n.parse().expect( - format!("Failed to parse source code, {} was not a number", n).as_str(), - ), + value: n.parse().expect(&format!("Failed to parse number: {}", n)), }), Token::EOF => NodeType::EOF, + + Token::OpenParen => { + let expr = self.parse_expr(); + match self.tokens.next() { + Some(Token::CloseParen) => expr, + _ => { + eprintln!("Expected closing parenthesis..."); + process::exit(1); + } + } + } + _ => { eprintln!("Unexpected token: {}", t); process::exit(1); @@ -52,8 +70,8 @@ impl Parser { } } - fn parse_additive_expr(&mut self, t: interpreter::Token) -> NodeType { - let mut left = self.parse_primary_expr(t); + fn parse_additive_expr(&mut self) -> NodeType { + let mut left = self.parse_multiplicative_expr(); while let Some(interpreter::Token::BinaryOperator(operator)) = self.tokens.peek() { if operator != "+" && operator != "-" { @@ -61,12 +79,32 @@ impl Parser { } let operator = operator.clone(); - self.tokens.next(); + self.tokens.next(); // Consume the operator - let right = match self.tokens.next() { - Some(token) => self.parse_primary_expr(token), - None => break, - }; + let right = self.parse_multiplicative_expr(); + + left = NodeType::BinaryExpr(BinaryExpr { + left: Box::new(left), + right: Box::new(right), + operator, + }); + } + + left + } + + fn parse_multiplicative_expr(&mut self) -> NodeType { + let mut left = self.parse_primary_expr(); + + while let Some(interpreter::Token::BinaryOperator(operator)) = self.tokens.peek() { + if operator != "*" && operator != "/" && operator != "%" { + break; + } + + let operator = operator.clone(); + self.tokens.next(); // Consume the operator + + let right = self.parse_primary_expr(); left = NodeType::BinaryExpr(BinaryExpr { left: Box::new(left),