From a54abcc39474f0eee551e48b6c1c26898ca20ba7 Mon Sep 17 00:00:00 2001 From: Araozu Date: Tue, 21 Nov 2023 21:00:58 -0500 Subject: [PATCH] Structure for parsing operators. Parse unary operator --- CHANGELOG.md | 1 + src/codegen/expression.rs | 3 +++ src/syntax/ast/mod.rs | 2 +- src/syntax/expression/comparison.rs | 8 +++++++ src/syntax/expression/equality.rs | 10 ++++---- src/syntax/expression/factor.rs | 8 +++++++ src/syntax/expression/mod.rs | 36 ++++++----------------------- src/syntax/expression/primary.rs | 18 +++++++++++++-- src/syntax/expression/term.rs | 8 +++++++ src/syntax/expression/unary.rs | 25 ++++++++++++++++++++ 10 files changed, 82 insertions(+), 37 deletions(-) create mode 100644 src/syntax/expression/comparison.rs create mode 100644 src/syntax/expression/factor.rs create mode 100644 src/syntax/expression/term.rs create mode 100644 src/syntax/expression/unary.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 569a39d..fc2a900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Parse block of code - Parse multiple statements inside a block +- Parse unary operator (`!` & `-`) ## v0.0.7 diff --git a/src/codegen/expression.rs b/src/codegen/expression.rs index 3ebe936..68338e3 100644 --- a/src/codegen/expression.rs +++ b/src/codegen/expression.rs @@ -21,6 +21,9 @@ impl Transpilable for Expression { Expression::BinaryOperator(_, _, _) => { todo!("BinaryOperator codegen is not implemented yet") } + Expression::UnaryOperator(_, _) => { + todo!("UnaryOperator codegen is not implemented yet") + } } } } diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs index 0d08819..fbcf94b 100644 --- a/src/syntax/ast/mod.rs +++ b/src/syntax/ast/mod.rs @@ -35,6 +35,6 @@ pub enum Expression { Boolean(bool), Identifier(Box), FunctionCall(FunctionCall), + UnaryOperator(Box, Box), BinaryOperator(Box, Box, Box), } - diff --git a/src/syntax/expression/comparison.rs b/src/syntax/expression/comparison.rs new file mode 100644 index 0000000..f84e05c --- /dev/null +++ b/src/syntax/expression/comparison.rs @@ -0,0 +1,8 @@ +use crate::{ + lexic::token::Token, + syntax::{ast::Expression, ParseResult}, +}; + +pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { + return super::term::try_parse(tokens, pos); +} diff --git a/src/syntax/expression/equality.rs b/src/syntax/expression/equality.rs index d7ace6c..53b69d1 100644 --- a/src/syntax/expression/equality.rs +++ b/src/syntax/expression/equality.rs @@ -1,8 +1,8 @@ -use crate::{syntax::{ParseResult, ast::Expression}, lexic::token::Token}; - +use crate::{ + lexic::token::Token, + syntax::{ast::Expression, ParseResult}, +}; pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - // - - todo!() + return super::comparison::try_parse(tokens, pos); } diff --git a/src/syntax/expression/factor.rs b/src/syntax/expression/factor.rs new file mode 100644 index 0000000..1a52907 --- /dev/null +++ b/src/syntax/expression/factor.rs @@ -0,0 +1,8 @@ +use crate::{ + lexic::token::Token, + syntax::{ast::Expression, ParseResult}, +}; + +pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { + return super::unary::try_parse(tokens, pos); +} diff --git a/src/syntax/expression/mod.rs b/src/syntax/expression/mod.rs index eb0da6f..aab819f 100644 --- a/src/syntax/expression/mod.rs +++ b/src/syntax/expression/mod.rs @@ -1,36 +1,14 @@ -use super::{ast::Expression, functions::function_call, ParseResult}; -use crate::lexic::token::{Token, TokenType}; +use super::{ast::Expression, ParseResult}; +use crate::lexic::token::Token; +mod comparison; mod equality; +mod factor; mod primary; +mod term; +mod unary; /// Expression is defined in the grammar. pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { - match function_call::try_parse(tokens, pos) { - super::ParseResult::Ok(function_call, next_pos) => { - return ParseResult::Ok::<_, ()>(Expression::FunctionCall(function_call), next_pos) - } - _ => {} - }; - - match tokens.get(pos) { - Some(token) => match token.token_type { - TokenType::Number => { - ParseResult::Ok(Expression::Number(Box::new(token.value.clone())), pos + 1) - } - TokenType::String => { - ParseResult::Ok(Expression::String(Box::new(token.value.clone())), pos + 1) - } - TokenType::Identifier if token.value == "true" || token.value == "false" => { - ParseResult::Ok(Expression::Boolean(token.value == "true"), pos + 1) - } - TokenType::Identifier => ParseResult::Ok( - Expression::Identifier(Box::new(token.value.clone())), - pos + 1, - ), - _ => ParseResult::Unmatched, - }, - None => ParseResult::Unmatched, - } + return equality::try_parse(tokens, pos); } - diff --git a/src/syntax/expression/primary.rs b/src/syntax/expression/primary.rs index 870598b..ddd4913 100644 --- a/src/syntax/expression/primary.rs +++ b/src/syntax/expression/primary.rs @@ -4,7 +4,7 @@ use crate::{ }; /// This grammar may not be up to date. Refer to the spec for the latest grammar. -/// +/// /// ```ebnf /// primary = number | string | boolean | identifier | ("(", expression, ")"); /// ``` @@ -34,13 +34,27 @@ pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult Expression::Identifier(Box::new(token.value.clone())), pos + 1, ), - // TODO: Parse parenthesized expressions. + TokenType::LeftParen => parse_parenthesized_expression(tokens, pos), _ => ParseResult::Unmatched, }, None => ParseResult::Unmatched, } } +fn parse_parenthesized_expression(tokens: &Vec, pos: usize) -> ParseResult { + let expression = super::try_parse(tokens, pos + 1); + match expression { + ParseResult::Ok(expression, next_pos) => match tokens.get(next_pos) { + Some(token) => match token.token_type { + TokenType::RightParen => ParseResult::Ok(expression, next_pos + 1), + _ => ParseResult::Unmatched, + }, + None => ParseResult::Unmatched, + }, + _ => ParseResult::Unmatched, + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/syntax/expression/term.rs b/src/syntax/expression/term.rs new file mode 100644 index 0000000..4ae82e7 --- /dev/null +++ b/src/syntax/expression/term.rs @@ -0,0 +1,8 @@ +use crate::{ + lexic::token::Token, + syntax::{ast::Expression, ParseResult}, +}; + +pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { + return super::factor::try_parse(tokens, pos); +} diff --git a/src/syntax/expression/unary.rs b/src/syntax/expression/unary.rs new file mode 100644 index 0000000..dfb515b --- /dev/null +++ b/src/syntax/expression/unary.rs @@ -0,0 +1,25 @@ +use crate::{ + lexic::token::Token, + syntax::{ast::Expression, expression::primary, ParseResult}, +}; + +/// Parses an unary expression. +/// +/// ```ebnf +/// unary = ("!" | "-"), expression +/// | primary; +/// ``` +pub fn try_parse(tokens: &Vec, pos: usize) -> ParseResult { + match tokens.get(pos) { + Some(token) if token.value == "!" || token.value == "-" => { + match super::try_parse(tokens, pos + 1) { + ParseResult::Ok(expression, next_pos) => ParseResult::Ok( + Expression::UnaryOperator(Box::new(token.value.clone()), Box::new(expression)), + next_pos, + ), + _ => ParseResult::Unmatched, + } + } + _ => return primary::try_parse(tokens, pos), + } +}