From dcffe062a187b15181006e0fc66ebe4068f8c921 Mon Sep 17 00:00:00 2001 From: Araozu Date: Tue, 21 Nov 2023 21:40:11 -0500 Subject: [PATCH] Parse binary operators --- CHANGELOG.md | 2 +- src/syntax/expression/comparison.rs | 43 ++++++++++++++++++++++++++++- src/syntax/expression/equality.rs | 38 ++++++++++++++++++++++++- src/syntax/expression/term.rs | 38 ++++++++++++++++++++++++- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f74313b..f61c788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - Parse block of code - Parse multiple statements inside a block - Parse unary operator (`!` & `-`) -- Parse binary operators `/`, `*` +- Parse binary operators ## v0.0.7 diff --git a/src/syntax/expression/comparison.rs b/src/syntax/expression/comparison.rs index f84e05c..42f10a9 100644 --- a/src/syntax/expression/comparison.rs +++ b/src/syntax/expression/comparison.rs @@ -3,6 +3,47 @@ use crate::{ syntax::{ast::Expression, ParseResult}, }; +/// Parses a factor expression. +/// +/// ```ebnf +/// comparison = term, ((">" | ">=" | "<" | "<="), term)*; +/// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - return super::term::try_parse(tokens, pos); + let (term, next_pos) = match super::term::try_parse(tokens, pos) { + ParseResult::Ok(expr, next_pos) => (expr, next_pos), + _ => return ParseResult::Unmatched, + }; + + parse_many(tokens, next_pos, term) +} + +fn parse_many( + tokens: &Vec, + pos: usize, + prev_expr: Expression, +) -> ParseResult { + // comparison = term, ((">" | ">=" | "<" | "<="), term)*; + + match tokens.get(pos) { + Some(token) + if token.value == "<" + || token.value == "<=" + || token.value == ">" + || token.value == ">=" => + { + match super::term::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/equality.rs b/src/syntax/expression/equality.rs index 53b69d1..ebae488 100644 --- a/src/syntax/expression/equality.rs +++ b/src/syntax/expression/equality.rs @@ -3,6 +3,42 @@ use crate::{ syntax::{ast::Expression, ParseResult}, }; +/// Parses a factor expression. +/// +/// ```ebnf +/// equality = comparison, (("==" | "!="), comparison )*; +/// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - return super::comparison::try_parse(tokens, pos); + let (comparison, next_pos) = match super::comparison::try_parse(tokens, pos) { + ParseResult::Ok(expr, next_pos) => (expr, next_pos), + _ => return ParseResult::Unmatched, + }; + + parse_many(tokens, next_pos, comparison) +} + +fn parse_many( + tokens: &Vec, + pos: usize, + prev_expr: Expression, +) -> ParseResult { + // equality = comparison, (("==" | "!="), comparison )*; + + match tokens.get(pos) { + Some(token) if token.value == "==" || token.value == "!=" => { + match super::comparison::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/term.rs b/src/syntax/expression/term.rs index 4ae82e7..22b15ad 100644 --- a/src/syntax/expression/term.rs +++ b/src/syntax/expression/term.rs @@ -3,6 +3,42 @@ use crate::{ syntax::{ast::Expression, ParseResult}, }; +/// Parses a factor expression. +/// +/// ```ebnf +/// term = factor, (("-" | "+"), factor)*; +/// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - return super::factor::try_parse(tokens, pos); + let (factor, next_pos) = match super::factor::try_parse(tokens, pos) { + ParseResult::Ok(expr, next_pos) => (expr, next_pos), + _ => return ParseResult::Unmatched, + }; + + parse_many(tokens, next_pos, factor) +} + +fn parse_many( + tokens: &Vec, + pos: usize, + prev_expr: Expression, +) -> ParseResult { + // term = factor, (("-" | "+"), factor)*; + + match tokens.get(pos) { + Some(token) if token.value == "+" || token.value == "-" => { + match super::factor::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), + } }