refactor: implement new indent strategy on equality parsing

This commit is contained in:
Araozu 2024-06-05 20:50:01 -05:00
parent 9685c132c5
commit be8c16ccf0
2 changed files with 19 additions and 44 deletions

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
lexic::token::{Token, TokenType}, handle_dedentation, handle_indentation, lexic::token::{Token, TokenType}, syntax::{ast::Expression, ParsingError, ParsingResult}
syntax::{ast::Expression, ParsingError, ParsingResult},
}; };
/// Parses a factor expression. /// Parses a factor expression.
@ -25,16 +24,20 @@ fn parse_many<'a>(
) -> ParsingResult<'a, Expression<'a>> { ) -> ParsingResult<'a, Expression<'a>> {
// equality = comparison, (("==" | "!="), comparison )*; // equality = comparison, (("==" | "!="), comparison )*;
let mut indented = false; let mut indent_count: u32 = 0;
let result = match tokens.get(pos) { let mut next_pos = pos;
Some(token) if token.value == "==" || token.value == "!=" => {
// here handle indentation, again, for:
// ```
// value
// == value
// ```
match super::comparison::try_parse(tokens, pos + 1) { // 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 == "!=" => {
next_pos += 1;
// Handle possible indentation after binary operator
handle_indentation!(tokens, next_pos, indent_count, indentation_level);
match super::comparison::try_parse(tokens, next_pos) {
Ok((expr, next_pos)) => { Ok((expr, next_pos)) => {
let expr = Expression::BinaryOperator( let expr = Expression::BinaryOperator(
Box::new(prev_expr), Box::new(prev_expr),
@ -42,45 +45,20 @@ fn parse_many<'a>(
&token.value, &token.value,
); );
parse_many(tokens, next_pos, expr, indentation_level) parse_many(tokens, next_pos, expr, indentation_level + indent_count)
} }
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
} }
} }
// Handle indentation _ => return Ok((prev_expr, pos)),
Some(token) if token.token_type == TokenType::NewLine => {
let next_tok = match tokens.get(pos + 1) {
Some(t) => t,
None => return Ok((prev_expr, pos)),
};
let next_is_indent = next_tok.token_type == TokenType::INDENT;
if next_is_indent {
// increase indentation level and continue parsing
indented = true;
parse_many(tokens, pos + 2, prev_expr, indentation_level + 1)
} else if indentation_level > 0 {
// ignore the newline, as we are indented
parse_many(tokens, pos + 1, prev_expr, indentation_level)
} else {
Ok((prev_expr, pos))
}
}
_ => Ok((prev_expr, pos)),
}; };
let (new_expr, next_pos) = match result { let (new_expr, mut next_pos) = match result {
Ok((e, n)) => (e, n), Ok((e, n)) => (e, n),
_ => return result, _ => return result,
}; };
// Here expect dedents if there are any handle_dedentation!(tokens, next_pos, indent_count);
if indented {
match tokens.get(next_pos) {
Some(t) if t.token_type == TokenType::DEDENT => return Ok((new_expr, next_pos + 1)),
_ => panic!("Expected DEDENT"),
}
}
Ok((new_expr, next_pos)) Ok((new_expr, next_pos))
} }
@ -190,7 +168,6 @@ mod tests {
} }
} }
/*
#[test] #[test]
fn should_parse_indented_5() { fn should_parse_indented_5() {
let tokens = get_tokens(&String::from("a ==\n b")).unwrap(); let tokens = get_tokens(&String::from("a ==\n b")).unwrap();
@ -205,5 +182,4 @@ mod tests {
_ => panic!("Expected a binary operator"), _ => panic!("Expected a binary operator"),
} }
} }
*/
} }

View File

@ -25,7 +25,6 @@ fn parse_many<'a>(
// (("/" | "*"), unary)* // (("/" | "*"), unary)*
let mut indent_count: u32 = 0; let mut indent_count: u32 = 0;
let mut next_pos = pos; let mut next_pos = pos;
// Handle possible indentation before binary operator // Handle possible indentation before binary operator