diff --git a/src/main.rs b/src/main.rs index aa51699..f973024 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,13 +4,12 @@ pub mod parser; pub mod scanner; fn main() -> Result<()> { - let code = "'1' * 10 + 1 + 1 - 1"; + let code = "'1' * 10 + 1 + 1 - 1;"; let tokens = scanner::Scanner::new(code.to_owned()).collect::>(); println!("{:#?}", tokens); let mut parser = parser::Parser::new(tokens); let parsed = parser.parse(); - println!("{:#?}", parsed); Ok(()) diff --git a/src/parser/expression.rs b/src/parser/expression.rs index 525f81d..cd2b623 100644 --- a/src/parser/expression.rs +++ b/src/parser/expression.rs @@ -1,6 +1,5 @@ -use crate::scanner::lexeme::{Lexeme, Token}; - -use super::{lookup::BindingPower, BinaryOperation, Expression, Parser}; +use super::{lookup::BindingPower, Expression, Parser}; +use crate::scanner::lexeme::Lexeme; pub fn parse( parser: &Parser, @@ -27,13 +26,24 @@ pub fn parse( Lexeme::Invalid(_) => break, }; - let token_binding_power = parser.lookup.binding_power_lookup.get(token)?; + let token_binding_power = parser + .lookup + .binding_power_lookup + .get(token) + .unwrap_or(&BindingPower::None); if binding_power > token_binding_power { break; } - let left_expression_handler = parser.lookup.left_expression_lookup.get(token)?; + let left_expression_handler = parser.lookup.left_expression_lookup.get(token); + + if left_expression_handler.is_none() { + break; + } + + let left_expression_handler = left_expression_handler.unwrap(); + let (right_hand_side, new_cursor) = left_expression_handler(parser, cursor, left_hand_side, binding_power)?; @@ -43,26 +53,3 @@ pub fn parse( Some((left_hand_side, cursor)) } - -pub fn parse_binary( - parser: &Parser, - cursor: usize, - left_hand_side: Box, - binding_power: &BindingPower, -) -> Option<(Expression, usize)> { - let operator = parser.lexemes.get(cursor)?; - let operator = match operator { - Lexeme::Valid(Token::Plus, _) => BinaryOperation::Plus, - Lexeme::Valid(Token::Minus, _) => BinaryOperation::Minus, - Lexeme::Valid(Token::Star, _) => BinaryOperation::Times, - Lexeme::Valid(Token::Slash, _) => BinaryOperation::Divide, - _ => return None, - }; - - let (right_hand_side, cursor) = parse(parser, cursor, binding_power)?; - - Some(( - Expression::Binary(left_hand_side, operator, Box::new(right_hand_side)), - cursor, - )) -} diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index 16313a8..d35da2a 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -188,7 +188,14 @@ impl Default for Lookup { lookup.add_statement_handler(Token::Semicolon, |parser, cursor| { let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::Primary)?; - Some((Statement::Expression(expression), cursor)) + // Expect a semicolon after the expression + let (tokens, cursor) = expect_tokens!(parser, cursor, (Token::Semicolon))?; + let semicolon = tokens.first().unwrap(); + if let Lexeme::Valid(Token::Semicolon, _) = semicolon { + Some((Statement::Expression(expression), cursor)) + } else { + None + } }); lookup diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 06ef327..0a1a1ff 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -80,7 +80,7 @@ mod tests { #[test] fn parses_addition() { - let code = "123 + 456"; + let code = "123 + 456;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); @@ -99,7 +99,7 @@ mod tests { #[test] fn parses_subtraction() { - let code = "123 - 456"; + let code = "123 - 456;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); @@ -118,7 +118,7 @@ mod tests { #[test] fn parses_multiplication() { - let code = "123 * 456"; + let code = "123 * 456;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); @@ -137,7 +137,7 @@ mod tests { #[test] fn parses_division() { - let code = "123 / 456"; + let code = "123 / 456;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); @@ -156,7 +156,7 @@ mod tests { #[test] fn parses_long_expression() { - let code = "123 + 456 - 789 + 101"; + let code = "123 + 456 - 789 + 101;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); @@ -183,7 +183,7 @@ mod tests { #[test] fn gives_precedence_to_multiplication() { - let code = "123 * 456 + 789"; + let code = "123 * 456 + 789;"; let lexemes = Scanner::new(code.to_owned()).collect::>(); let mut parser = Parser::new(lexemes); let result = parser.parse(); diff --git a/src/parser/statement.rs b/src/parser/statement.rs index 31d7483..6182506 100644 --- a/src/parser/statement.rs +++ b/src/parser/statement.rs @@ -1,14 +1,23 @@ -use crate::scanner::lexeme::Lexeme; +use crate::scanner::lexeme::{Lexeme, Token}; use super::{expression, lookup::BindingPower, Parser, Statement}; pub fn parse(parser: &Parser, cursor: usize) -> Option<(Statement, usize)> { + let mut cursor = cursor; let lexeme = parser.lexemes.get(cursor)?; if let Lexeme::Invalid(_) = lexeme { return None; } - let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + let (expression, new_cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + + // Expect a semicolon + let lexeme = parser.lexemes.get(new_cursor); + if let Some(Lexeme::Valid(Token::Semicolon, _)) = lexeme { + cursor = new_cursor + 1; + } else { + return None; + } Some((Statement::Expression(expression), cursor)) } diff --git a/src/scanner/mod.rs b/src/scanner/mod.rs index aba00a1..e1ea89c 100644 --- a/src/scanner/mod.rs +++ b/src/scanner/mod.rs @@ -261,6 +261,18 @@ mod tests { ); } + #[test] + fn parses_semicolons() { + test_scanner( + "123;456", + vec![ + Lexeme::valid(Token::Integer(123), 0, 3), + Lexeme::valid(Token::Semicolon, 3, 1), + Lexeme::valid(Token::Integer(456), 4, 3), + ], + ); + } + fn test_scanner(input: &str, expected: Vec) { let lexemes = Scanner::new(input.to_string()).collect::>();