diff --git a/CHANGELOG.md b/CHANGELOG.md index fc2a900..f74313b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Parse block of code - Parse multiple statements inside a block - Parse unary operator (`!` & `-`) +- Parse binary operators `/`, `*` ## v0.0.7 diff --git a/src/syntax/expression/factor.rs b/src/syntax/expression/factor.rs index 1a52907..e486de8 100644 --- a/src/syntax/expression/factor.rs +++ b/src/syntax/expression/factor.rs @@ -3,6 +3,42 @@ use crate::{ syntax::{ast::Expression, ParseResult}, }; +/// Parses a factor expression. +/// +/// ```ebnf +/// factor = unary, (("/" | "*"), unary)*; +/// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - return super::unary::try_parse(tokens, pos); + let (unary, next_pos) = match super::unary::try_parse(tokens, pos) { + ParseResult::Ok(expr, next_pos) => (expr, next_pos), + _ => return ParseResult::Unmatched, + }; + + parse_many(tokens, next_pos, unary) +} + +fn parse_many( + tokens: &Vec, + pos: usize, + prev_expr: Expression, +) -> ParseResult { + // (("/" | "*"), unary)* + + match tokens.get(pos) { + Some(token) if token.value == "/" || token.value == "*" => { + match super::unary::try_parse(tokens, pos + 1) { + ParseResult::Ok(expr, next_pos) => { + let expr = Expression::BinaryOperator( + Box::new(prev_expr), + Box::new(expr), + Box::new(token.value.clone()), + ); + + parse_many(tokens, next_pos, expr) + } + _ => ParseResult::Unmatched, + } + } + _ => ParseResult::Ok(prev_expr, pos), + } } diff --git a/src/syntax/expression/unary.rs b/src/syntax/expression/unary.rs index dfb515b..2a9f9e3 100644 --- a/src/syntax/expression/unary.rs +++ b/src/syntax/expression/unary.rs @@ -7,7 +7,7 @@ use crate::{ /// /// ```ebnf /// unary = ("!" | "-"), expression -/// | primary; +/// | primary; /// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { match tokens.get(pos) { @@ -20,6 +20,7 @@ pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult _ => ParseResult::Unmatched, } } - _ => return primary::try_parse(tokens, pos), + _ => primary::try_parse(tokens, pos), } } +