diff --git a/src/lexer/token.rs b/src/lexer/token.rs index b2dbbab..fb2043c 100644 --- a/src/lexer/token.rs +++ b/src/lexer/token.rs @@ -106,6 +106,10 @@ pub enum TokenKind { Equality, /// An inequality sign; `!=`. Inequality, + /// An and sign; `&&`. + And, + /// An or sign; `||`. + Or, /// An at sign; `@`. At, @@ -211,6 +215,8 @@ impl Display for TokenKind { TokenKind::Question => write!(f, "`?`"), TokenKind::Pipe => write!(f, "`|`"), TokenKind::Caret => write!(f, "`^`"), + TokenKind::And => todo!("`&&`"), + TokenKind::Or => todo!("`||`"), } } } diff --git a/src/main.rs b/src/main.rs index 2dedd0a..cb0ab2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ pub mod lexer; pub mod parser; fn main() { - let input = "1 / ( 1 * 1 )\n"; + let input = "2 == 12;\n"; let mut parser = Parser::new(input); let symbol = match parser.parse() { diff --git a/src/parser/ast.rs b/src/parser/ast.rs index f38f7b5..38948ac 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -20,6 +20,10 @@ pub enum Expression<'de> { left: Box>, right: Box>, }, + Unary { + operator: UnaryOperator, + operand: Box>, + }, Group(Box>), } @@ -37,4 +41,19 @@ pub enum BinaryOperator { Subtract, Multiply, Divide, + Modulo, + Equal, + NotEqual, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual, + And, + Or, +} + +#[derive(Debug)] +pub enum UnaryOperator { + Negate, + Negative, } diff --git a/src/parser/expression/binary.rs b/src/parser/expression/binary.rs index e91d6a0..f312c58 100644 --- a/src/parser/expression/binary.rs +++ b/src/parser/expression/binary.rs @@ -60,3 +60,129 @@ pub fn division<'de>( right: Box::new(rhs), }) } + +pub fn modulo<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::Modulo, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn equal<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::Equal, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn not_equal<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::NotEqual, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn less_than<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::LessThan, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn less_than_or_equal<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::LessThanOrEqual, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn greater_than<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::GreaterThan, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn greater_than_or_equal<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::GreaterThanOrEqual, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn and<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::And, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} + +pub fn or<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = crate::parser::expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::Or, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} diff --git a/src/parser/expression/mod.rs b/src/parser/expression/mod.rs index a913bcb..f169758 100644 --- a/src/parser/expression/mod.rs +++ b/src/parser/expression/mod.rs @@ -13,6 +13,7 @@ use super::{ pub mod binary; pub mod primitive; +pub mod unary; pub fn parse<'de>( parser: &mut Parser<'de>, diff --git a/src/parser/expression/unary.rs b/src/parser/expression/unary.rs new file mode 100644 index 0000000..c5de31f --- /dev/null +++ b/src/parser/expression/unary.rs @@ -0,0 +1,33 @@ +use crate::{ + lexer::TokenKind, + parser::{ + ast::{Expression, UnaryOperator}, + lookup::BindingPower, + Parser, + }, +}; +use miette::Result; + +pub fn negate<'de>(parser: &mut Parser<'de>) -> Result> { + parser + .lexer + .expect(TokenKind::Not, "expected a negate operator")?; + let expression = crate::parser::expression::parse(parser, BindingPower::None)?; + + Ok(Expression::Unary { + operator: UnaryOperator::Negate, + operand: Box::new(expression), + }) +} + +pub fn negative<'de>(parser: &mut Parser<'de>) -> Result> { + parser + .lexer + .expect(TokenKind::Minus, "expected a negative operator")?; + let expression = crate::parser::expression::parse(parser, BindingPower::None)?; + + Ok(Expression::Unary { + operator: UnaryOperator::Negative, + operand: Box::new(expression), + }) +} diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index 8d3740e..d6146f4 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -113,6 +113,8 @@ impl<'de> Default for Lookup<'de> { .add_expression_handler(TokenKind::Decimal, expression::primitive::decimal) .add_expression_handler(TokenKind::ParenOpen, group) .add_expression_handler(TokenKind::If, if_) + .add_expression_handler(TokenKind::Not, expression::unary::negate) + .add_expression_handler(TokenKind::Minus, expression::unary::negative) .add_left_expression_handler( TokenKind::Plus, BindingPower::Additive, @@ -133,6 +135,51 @@ impl<'de> Default for Lookup<'de> { BindingPower::Multiplicative, expression::binary::division, ) + .add_left_expression_handler( + TokenKind::Equality, + BindingPower::Assignment, + expression::binary::equal, + ) + .add_left_expression_handler( + TokenKind::Inequality, + BindingPower::Assignment, + expression::binary::not_equal, + ) + .add_left_expression_handler( + TokenKind::LessThan, + BindingPower::Relational, + expression::binary::less_than, + ) + .add_left_expression_handler( + TokenKind::LessThanOrEqual, + BindingPower::Relational, + expression::binary::less_than_or_equal, + ) + .add_left_expression_handler( + TokenKind::GreaterThan, + BindingPower::Relational, + expression::binary::greater_than, + ) + .add_left_expression_handler( + TokenKind::GreaterThanOrEqual, + BindingPower::Relational, + expression::binary::greater_than_or_equal, + ) + .add_left_expression_handler( + TokenKind::Percent, + BindingPower::Multiplicative, + expression::binary::modulo, + ) + .add_left_expression_handler( + TokenKind::And, + BindingPower::Relational, + expression::binary::and, + ) + .add_left_expression_handler( + TokenKind::Or, + BindingPower::Relational, + expression::binary::or, + ) } }