diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/interpret/walker.rs | 24 | ||||
| -rw-r--r-- | src/lex/lexer.rs | 14 | ||||
| -rw-r--r-- | src/lex/token.rs | 3 | ||||
| -rw-r--r-- | src/parse/ast/nodes.rs | 4 | ||||
| -rw-r--r-- | src/parse/parser.rs | 34 |
5 files changed, 77 insertions, 2 deletions
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs index b8a2e68..471da89 100644 --- a/src/interpret/walker.rs +++ b/src/interpret/walker.rs @@ -69,6 +69,25 @@ impl Walker { _ => {} } + // Short-circuting operators + if let BinOp::And | BinOp::Or = op { + let left_value = self.walk_expression(left)?; + let is_left_true = match left_value { + Value::Bool(bool) => bool, + _ => return Err(WalkerError::WrongAndOrType), + }; + + if let BinOp::And = op { + if !is_left_true { + return Ok(Value::Bool(false)); + } + } else if is_left_true { + return Ok(Value::Bool(true)); + } + + return self.walk_expression(right); + } + let left = self.walk_expression(left)?; let right = self.walk_expression(right)?; @@ -78,13 +97,14 @@ impl Walker { BinOp::Minus => left.sub(right), BinOp::Star => left.mul(right), BinOp::Slash => left.div(right), + BinOp::Dot => todo!("Structures not implemented yet."), BinOp::Eq => left.eq(right), BinOp::Neq => left.neq(right), BinOp::Gt => left.gt(right), BinOp::Gte => left.gte(right), BinOp::Lt => right.gt(left), BinOp::Lte => right.gte(left), - BinOp::Dot => todo!("Structures not implemented yet."), + _ => unreachable!(), } .map_err(WalkerError::OperationError) @@ -245,6 +265,8 @@ pub enum WalkerError { WrongLoopConditionType, #[error("If and Elif expressions can only take boolean values as conditions.")] WrongIfConditionType, + #[error("&& and || expressions can only take boolean values as their operands.")] + WrongAndOrType, #[error("Can only assign to identifiers and member or array access results.")] NonLValueAssignment, #[error(transparent)] diff --git a/src/lex/lexer.rs b/src/lex/lexer.rs index edd1ff0..1d46ce7 100644 --- a/src/lex/lexer.rs +++ b/src/lex/lexer.rs @@ -79,6 +79,20 @@ impl Iterator for Lexer<'_> { OpGt } } + '&' => { + if self.advance_if('&') { + OpAnd + } else { + Unknown('&') + } + } + '|' => { + if self.advance_if('|') { + OpOr + } else { + Unknown('|') + } + } '(' => GroupOpen, ')' => GroupClose, '{' => BlockOpen, diff --git a/src/lex/token.rs b/src/lex/token.rs index 3c6d5c6..77b0df6 100644 --- a/src/lex/token.rs +++ b/src/lex/token.rs @@ -25,6 +25,9 @@ pub enum TokenVariant { OpGt, OpLte, OpGte, + // Short-circuting boolean operators + OpAnd, + OpOr, // Statement symbols Dot, diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs index bffaea3..2bf3f17 100644 --- a/src/parse/ast/nodes.rs +++ b/src/parse/ast/nodes.rs @@ -14,6 +14,8 @@ pub enum BinaryOperator { Gte, Lt, Lte, + And, + Or, Assign, ConstAssign, Dot, @@ -32,6 +34,8 @@ impl BinaryOperator { OpGt => Self::Gt, OpLte => Self::Lte, OpGte => Self::Gte, + OpAnd => Self::And, + OpOr => Self::Or, Assign => Self::Assign, ConstAssign => Self::ConstAssign, Dot => Self::Dot, diff --git a/src/parse/parser.rs b/src/parse/parser.rs index a882f35..6b0a785 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -87,7 +87,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { fn assignment_expression(&mut self) -> Result<Expression> { // Parse any expressions as l-values for now. - let left = self.equality_expression()?; + let left = self.or_expression()?; if let Some(op) = consume_if!(self, Assign | ConstAssign) { let right = self.assignment_expression()?; @@ -102,6 +102,38 @@ impl<T: Iterator<Item = Token>> Parser<T> { } } + fn or_expression(&mut self) -> Result<Expression> { + let mut left = self.and_expression()?; + + while let Some(op) = consume_if!(self, OpAnd) { + let right = self.and_expression()?; + + left = Expression::Binary { + left: Box::new(left), + op: BinaryOperator::from_token(op), + right: Box::new(right), + }; + } + + Ok(left) + } + + fn and_expression(&mut self) -> Result<Expression> { + let mut left = self.equality_expression()?; + + while let Some(op) = consume_if!(self, OpOr) { + let right = self.equality_expression()?; + + left = Expression::Binary { + left: Box::new(left), + op: BinaryOperator::from_token(op), + right: Box::new(right), + }; + } + + Ok(left) + } + fn equality_expression(&mut self) -> Result<Expression> { let mut left = self.comparison_expression()?; |
