refactor: parse indentation on term
This commit is contained in:
parent
fa14439507
commit
56ea63cf8c
@ -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<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||
_ => return Err(ParsingError::Unmatched),
|
||||
};
|
||||
|
||||
parse_many(tokens, next_pos, factor)
|
||||
parse_many(tokens, next_pos, factor, 0)
|
||||
}
|
||||
|
||||
fn parse_many<'a>(
|
||||
tokens: &'a Vec<Token>,
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user