feat: abstract parsing binary operators into a function

This commit is contained in:
Araozu 2024-11-02 19:44:54 -05:00
parent cef4459648
commit ff533c5ae7
6 changed files with 50 additions and 153 deletions

View File

@ -3,7 +3,7 @@ use crate::{
syntax::{ast::Expression, ParsingError, ParsingResult}, syntax::{ast::Expression, ParsingError, ParsingResult},
}; };
use super::utils::try_binary_op; use super::utils::parse_many;
/// Parses a factor expression. /// Parses a factor expression.
/// ///
@ -16,33 +16,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
}; };
parse_many(tokens, next_pos, term, 0) parse_many(tokens, next_pos, term, 0, &vec![">", ">=", "<", "<="])
}
fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
) -> ParsingResult<'a, Expression<'a>> {
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
try_binary_op(
tokens,
pos,
prev_expr,
vec![">", ">=", "<", "<="],
indentation_level,
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::term::try_parse(
tokens, next_pos,
) {
Ok((expr, next_pos)) => {
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
}
_ => return Err(ParsingError::Unmatched),
},
)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,10 +1,10 @@
use crate::{ use crate::{
lexic::token::Token, lexic::token::Token,
syntax::{ syntax::{ast::Expression, ParsingError, ParsingResult},
ast::Expression, parsers::expression::utils::try_binary_op, ParsingError, ParsingResult,
},
}; };
use super::utils::parse_many;
/// Parses a dot access /// Parses a dot access
/// ///
/// ```ebnf /// ```ebnf
@ -16,33 +16,5 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
}; };
parse_many(tokens, next_pos, unary, 0) parse_many(tokens, next_pos, unary, 0, &vec![".", "?.", "!."])
}
fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
) -> ParsingResult<'a, Expression<'a>> {
// (("/" | "*" | "%"), unary)*
try_binary_op(
tokens,
pos,
prev_expr,
vec!["."],
indentation_level,
|tokens, next_pos, prev_expr, token, indent_count: u32| {
// match next
match super::unary::try_parse(tokens, next_pos) {
Ok((expr, next_pos)) => {
let expr =
Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
}
_ => return Err(ParsingError::Unmatched),
}
},
)
} }

View File

@ -3,7 +3,7 @@ use crate::{
syntax::{ast::Expression, ParsingError, ParsingResult}, syntax::{ast::Expression, ParsingError, ParsingResult},
}; };
use super::utils::try_binary_op; use super::utils::parse_many;
/// Parses a factor expression. /// Parses a factor expression.
/// ///
@ -16,33 +16,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
}; };
parse_many(tokens, next_pos, comparison, 0) parse_many(tokens, next_pos, comparison, 0, &vec!["==", "!="])
}
fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
) -> ParsingResult<'a, Expression<'a>> {
// equality = comparison, (("==" | "!="), comparison )*;
try_binary_op(
tokens,
pos,
prev_expr,
vec!["==", "!="],
indentation_level,
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::comparison::try_parse(
tokens, next_pos,
) {
Ok((expr, next_pos)) => {
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
}
_ => return Err(ParsingError::Unmatched),
},
)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,10 +1,10 @@
use crate::{ use crate::{
lexic::token::Token, lexic::token::Token,
syntax::{ syntax::{ast::Expression, ParsingError, ParsingResult},
ast::Expression, parsers::expression::utils::try_binary_op, ParsingError, ParsingResult,
},
}; };
use super::utils::parse_many;
/// Parses a factor expression. /// Parses a factor expression.
/// ///
/// ```ebnf /// ```ebnf
@ -16,35 +16,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
}; };
parse_many(tokens, next_pos, unary, 0) parse_many(tokens, next_pos, unary, 0, &vec!["/", "*", "%"])
}
fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
) -> ParsingResult<'a, Expression<'a>> {
// (("/" | "*" | "%"), unary)*
try_binary_op(
tokens,
pos,
prev_expr,
vec!["/", "*", "%"],
indentation_level,
|tokens, next_pos, prev_expr, token, indent_count: u32| {
// match next
match super::unary::try_parse(tokens, next_pos) {
Ok((expr, next_pos)) => {
let expr =
Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
}
_ => return Err(ParsingError::Unmatched),
}
},
)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,9 +1,10 @@
use crate::syntax::parsers::expression::utils::try_binary_op;
use crate::{ use crate::{
lexic::token::Token, lexic::token::Token,
syntax::{ast::Expression, ParsingError, ParsingResult}, syntax::{ast::Expression, ParsingError, ParsingResult},
}; };
use super::utils::parse_many;
/// Parses a factor expression. /// Parses a factor expression.
/// ///
/// ```ebnf /// ```ebnf
@ -15,36 +16,7 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
_ => return Err(ParsingError::Unmatched), _ => return Err(ParsingError::Unmatched),
}; };
parse_many(tokens, next_pos, factor, 0) parse_many(tokens, next_pos, factor, 0, &vec!["-", "+", "++"])
}
fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
) -> ParsingResult<'a, Expression<'a>> {
// term = factor, (("-" | "+" | "++"), factor)*;
try_binary_op(
tokens,
pos,
prev_expr,
vec!["+", "-", "++"],
indentation_level,
|tokens, pos, prev_expr, token, indent_count: u32| {
// Parse the next factor
match super::factor::try_parse(tokens, pos) {
Ok((expr, next_pos)) => {
let expr =
Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
}
_ => return Err(ParsingError::Unmatched),
}
},
)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use crate::lexic::token::Token; use crate::lexic::token::Token;
use crate::lexic::token::TokenType::{NewLine, DEDENT, INDENT}; use crate::lexic::token::TokenType::{NewLine, DEDENT, INDENT};
use crate::syntax::ast::Expression; use crate::syntax::ast::Expression;
use crate::syntax::parseable::ParsingResult; use crate::syntax::parseable::{ParsingError, ParsingResult};
/// Parses a binary operator, handles indentation and runs a function on it. /// Parses a binary operator, handles indentation and runs a function on it.
/// ///
@ -15,7 +15,7 @@ pub fn try_binary_op<'a, F>(
tokens: &'a Vec<Token>, tokens: &'a Vec<Token>,
original_pos: usize, original_pos: usize,
prev_expr: Expression<'a>, prev_expr: Expression<'a>,
operators: Vec<&str>, operators: &Vec<&str>,
indentation_level: u32, indentation_level: u32,
fun: F, fun: F,
) -> ParsingResult<'a, Expression<'a>> ) -> ParsingResult<'a, Expression<'a>>
@ -87,3 +87,36 @@ where
Ok((new_expr, next_pos)) Ok((new_expr, next_pos))
} }
pub fn parse_many<'a>(
tokens: &'a Vec<Token>,
pos: usize,
prev_expr: Expression<'a>,
indentation_level: u32,
operators: &Vec<&str>,
) -> ParsingResult<'a, Expression<'a>> {
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
try_binary_op(
tokens,
pos,
prev_expr,
operators,
indentation_level,
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::term::try_parse(
tokens, next_pos,
) {
Ok((expr, next_pos)) => {
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
parse_many(
tokens,
next_pos,
expr,
indentation_level + indent_count,
operators,
)
}
_ => return Err(ParsingError::Unmatched),
},
)
}