From 56ea63cf8c9b8f6f93a933e24f88921d8dc7e6eb Mon Sep 17 00:00:00 2001 From: Araozu Date: Sat, 15 Jun 2024 16:36:27 -0500 Subject: [PATCH] refactor: parse indentation on term --- src/syntax/parsers/expression/term.rs | 113 ++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 7 deletions(-) diff --git a/src/syntax/parsers/expression/term.rs b/src/syntax/parsers/expression/term.rs index 1729d3d..f85d5e4 100644 --- a/src/syntax/parsers/expression/term.rs +++ b/src/syntax/parsers/expression/term.rs @@ -1,4 +1,6 @@ +use crate::lexic::token::TokenType; use crate::{ + handle_dedentation, handle_indentation, lexic::token::Token, syntax::{ast::Expression, ParsingError, ParsingResult}, }; @@ -14,19 +16,31 @@ pub fn try_parse(tokens: &Vec, pos: usize) -> ParsingResult { _ => return Err(ParsingError::Unmatched), }; - parse_many(tokens, next_pos, factor) + parse_many(tokens, next_pos, factor, 0) } fn parse_many<'a>( tokens: &'a Vec, pos: usize, prev_expr: Expression<'a>, + indentation_level: u32, ) -> ParsingResult<'a, Expression<'a>> { // term = factor, (("-" | "+"), factor)*; - match tokens.get(pos) { + let mut indent_count: u32 = 0; + let mut next_pos = pos; + + // Handle possible indentation before binary operator + handle_indentation!(tokens, next_pos, indent_count, indentation_level); + + let result = match tokens.get(next_pos) { Some(token) if token.value == "+" || token.value == "-" => { - match super::factor::try_parse(tokens, pos + 1) { + next_pos += 1; + + // Handle possible indentation after binary operator + handle_indentation!(tokens, next_pos, indent_count, indentation_level); + + match super::factor::try_parse(tokens, next_pos) { Ok((expr, next_pos)) => { let expr = Expression::BinaryOperator( Box::new(prev_expr), @@ -34,13 +48,22 @@ fn parse_many<'a>( &token.value, ); - parse_many(tokens, next_pos, expr) + parse_many(tokens, next_pos, expr, indentation_level + indent_count) } - _ => Err(ParsingError::Unmatched), + _ => return Err(ParsingError::Unmatched), } } - _ => Ok((prev_expr, pos)), - } + _ => return Ok((prev_expr, pos)), + }; + + let (new_expr, mut next_pos) = match result { + Ok((e, n)) => (e, n), + _ => return result, + }; + + handle_dedentation!(tokens, next_pos, indent_count); + + Ok((new_expr, next_pos)) } #[cfg(test)] @@ -83,4 +106,80 @@ mod tests { _ => panic!("Expected an Unmatched error"), } } + + #[test] + fn should_parse_indented_1() { + let tokens = get_tokens(&String::from("a\n + b")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + + assert_eq!(tokens[5].token_type, TokenType::DEDENT); + assert_eq!(next, 6); + + match result { + Expression::BinaryOperator(_, _, op) => { + assert_eq!(op, "+") + } + _ => panic!("Expected a binary operator"), + } + } + + #[test] + fn should_parse_indented_2() { + let tokens = get_tokens(&String::from("a\n + b\n + c")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + assert_eq!(next, 11); + + match result { + Expression::BinaryOperator(_, _, op) => { + assert_eq!(op, "+") + } + _ => panic!("Expected a binary operator"), + } + } + + #[test] + fn should_parse_indented_3() { + let tokens = get_tokens(&String::from("a\n + b + c")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + + assert_eq!(tokens[7].token_type, TokenType::DEDENT); + assert_eq!(next, 8); + + match result { + Expression::BinaryOperator(_, _, op) => { + assert_eq!(op, "+") + } + _ => panic!("Expected a binary operator"), + } + } + + #[test] + fn should_parse_indented_4() { + let tokens = get_tokens(&String::from("a\n + b\n + c")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + + assert_eq!(next, 9); + + match result { + Expression::BinaryOperator(_, _, op) => { + assert_eq!(op, "+") + } + _ => panic!("Expected a binary operator"), + } + } + + #[test] + fn should_parse_indented_5() { + let tokens = get_tokens(&String::from("a +\n b")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + + assert_eq!(next, 6); + + match result { + Expression::BinaryOperator(_, _, op) => { + assert_eq!(op, "+") + } + _ => panic!("Expected a binary operator"), + } + } }