1
0

Implement equality operation

This commit is contained in:
Jeff 2024-08-09 07:15:09 -04:00
parent 24a2642f17
commit f389f7e422
5 changed files with 92 additions and 2 deletions

View File

@ -238,6 +238,7 @@ pub enum BinaryOperator {
Subtract, Subtract,
// Comparison // Comparison
Equal,
Greater, Greater,
GreaterOrEqual, GreaterOrEqual,
Less, Less,
@ -254,6 +255,7 @@ impl Display for BinaryOperator {
BinaryOperator::Add => write!(f, "+"), BinaryOperator::Add => write!(f, "+"),
BinaryOperator::And => write!(f, "&&"), BinaryOperator::And => write!(f, "&&"),
BinaryOperator::Divide => write!(f, "/"), BinaryOperator::Divide => write!(f, "/"),
BinaryOperator::Equal => write!(f, "=="),
BinaryOperator::Greater => write!(f, ">"), BinaryOperator::Greater => write!(f, ">"),
BinaryOperator::GreaterOrEqual => write!(f, ">="), BinaryOperator::GreaterOrEqual => write!(f, ">="),
BinaryOperator::Less => write!(f, "<"), BinaryOperator::Less => write!(f, "<"),

View File

@ -143,9 +143,15 @@ impl Lexer {
(Token::RightParenthesis, (self.position - 1, self.position)) (Token::RightParenthesis, (self.position - 1, self.position))
} }
'=' => { '=' => {
self.position += 1; if let Some('=') = self.peek_second_char(source) {
self.position += 2;
(Token::Equal, (self.position - 1, self.position)) (Token::DoubleEqual, (self.position - 2, self.position))
} else {
self.position += 1;
(Token::Equal, (self.position - 1, self.position))
}
} }
'[' => { '[' => {
self.position += 1; self.position += 1;
@ -435,6 +441,21 @@ impl From<ParseIntError> for LexError {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn equal() {
let input = "42 == 42";
assert_eq!(
lex(input),
Ok(vec![
(Token::Integer(42), (0, 2)),
(Token::DoubleEqual, (3, 5)),
(Token::Integer(42), (6, 8)),
(Token::Eof, (8, 8)),
])
)
}
#[test] #[test]
fn modulo() { fn modulo() {
let input = "42 % 2"; let input = "42 % 2";

View File

@ -319,6 +319,23 @@ impl<'src> Parser<'src> {
(left_start, right_end), (left_start, right_end),
)); ));
} }
(Token::DoubleEqual, _) => {
let operator = Node::new(BinaryOperator::Equal, self.current.1);
self.next_token()?;
let right_node = self.parse_node(self.current_precedence())?;
let right_end = right_node.position.1;
return Ok(Node::new(
Statement::BinaryOperation {
left: Box::new(left_node),
operator,
right: Box::new(right_node),
},
(left_start, right_end),
));
}
_ => {} _ => {}
} }
} }
@ -539,6 +556,7 @@ impl<'src> Parser<'src> {
fn current_precedence(&self) -> u8 { fn current_precedence(&self) -> u8 {
match self.current.0 { match self.current.0 {
Token::DoubleEqual => 6,
Token::Greater | Token::GreaterEqual | Token::Less | Token::LessEqual => 5, Token::Greater | Token::GreaterEqual | Token::Less | Token::LessEqual => 5,
Token::Dot => 4, Token::Dot => 4,
Token::Percent => 3, Token::Percent => 3,
@ -613,6 +631,26 @@ mod tests {
use super::*; use super::*;
#[test]
fn equal() {
let input = "42 == 42";
assert_eq!(
parse(input),
Ok(AbstractSyntaxTree {
nodes: [Node::new(
Statement::BinaryOperation {
left: Box::new(Node::new(Statement::Constant(Value::integer(42)), (0, 2))),
operator: Node::new(BinaryOperator::Equal, (3, 5)),
right: Box::new(Node::new(Statement::Constant(Value::integer(42)), (6, 8)))
},
(0, 8)
)]
.into()
})
);
}
#[test] #[test]
fn modulo() { fn modulo() {
let input = "42 % 2"; let input = "42 % 2";

View File

@ -27,6 +27,7 @@ pub enum Token<'src> {
Comma, Comma,
Dot, Dot,
DoubleAmpersand, DoubleAmpersand,
DoubleEqual,
DoublePipe, DoublePipe,
Equal, Equal,
Greater, Greater,
@ -53,6 +54,7 @@ impl<'src> Token<'src> {
Token::Comma => TokenOwned::Comma, Token::Comma => TokenOwned::Comma,
Token::Dot => TokenOwned::Dot, Token::Dot => TokenOwned::Dot,
Token::DoubleAmpersand => TokenOwned::DoubleAmpersand, Token::DoubleAmpersand => TokenOwned::DoubleAmpersand,
Token::DoubleEqual => TokenOwned::DoubleEqual,
Token::DoublePipe => TokenOwned::DoublePipe, Token::DoublePipe => TokenOwned::DoublePipe,
Token::Eof => TokenOwned::Eof, Token::Eof => TokenOwned::Eof,
Token::Equal => TokenOwned::Equal, Token::Equal => TokenOwned::Equal,
@ -89,6 +91,7 @@ impl<'src> Token<'src> {
Token::Comma => ",", Token::Comma => ",",
Token::Dot => ".", Token::Dot => ".",
Token::DoubleAmpersand => "&&", Token::DoubleAmpersand => "&&",
Token::DoubleEqual => "==",
Token::DoublePipe => "||", Token::DoublePipe => "||",
Token::Eof => "EOF", Token::Eof => "EOF",
Token::Equal => "=", Token::Equal => "=",
@ -136,6 +139,9 @@ impl<'src> PartialEq for Token<'src> {
(Token::Boolean(left), Token::Boolean(right)) => left == right, (Token::Boolean(left), Token::Boolean(right)) => left == right,
(Token::Comma, Token::Comma) => true, (Token::Comma, Token::Comma) => true,
(Token::Dot, Token::Dot) => true, (Token::Dot, Token::Dot) => true,
(Token::DoubleAmpersand, Token::DoubleAmpersand) => true,
(Token::DoubleEqual, Token::DoubleEqual) => true,
(Token::DoublePipe, Token::DoublePipe) => true,
(Token::Eof, Token::Eof) => true, (Token::Eof, Token::Eof) => true,
(Token::Equal, Token::Equal) => true, (Token::Equal, Token::Equal) => true,
(Token::Greater, Token::Greater) => true, (Token::Greater, Token::Greater) => true,
@ -192,6 +198,7 @@ pub enum TokenOwned {
Comma, Comma,
Dot, Dot,
DoubleAmpersand, DoubleAmpersand,
DoubleEqual,
DoublePipe, DoublePipe,
Equal, Equal,
Greater, Greater,
@ -218,6 +225,7 @@ impl Display for TokenOwned {
TokenOwned::Comma => Token::Comma.fmt(f), TokenOwned::Comma => Token::Comma.fmt(f),
TokenOwned::Dot => Token::Dot.fmt(f), TokenOwned::Dot => Token::Dot.fmt(f),
TokenOwned::DoubleAmpersand => Token::DoubleAmpersand.fmt(f), TokenOwned::DoubleAmpersand => Token::DoubleAmpersand.fmt(f),
TokenOwned::DoubleEqual => Token::DoubleEqual.fmt(f),
TokenOwned::DoublePipe => Token::DoublePipe.fmt(f), TokenOwned::DoublePipe => Token::DoublePipe.fmt(f),
TokenOwned::Eof => Token::Eof.fmt(f), TokenOwned::Eof => Token::Eof.fmt(f),
TokenOwned::Equal => Token::Equal.fmt(f), TokenOwned::Equal => Token::Equal.fmt(f),

View File

@ -96,6 +96,7 @@ impl Vm {
BinaryOperator::Add => left_value.add(&right_value), BinaryOperator::Add => left_value.add(&right_value),
BinaryOperator::And => left_value.and(&right_value), BinaryOperator::And => left_value.and(&right_value),
BinaryOperator::Divide => left_value.divide(&right_value), BinaryOperator::Divide => left_value.divide(&right_value),
BinaryOperator::Equal => Ok(Value::boolean(left_value == right_value)),
BinaryOperator::Greater => left_value.greater_than(&right_value), BinaryOperator::Greater => left_value.greater_than(&right_value),
BinaryOperator::GreaterOrEqual => { BinaryOperator::GreaterOrEqual => {
left_value.greater_than_or_equal(&right_value) left_value.greater_than_or_equal(&right_value)
@ -433,6 +434,26 @@ impl Display for VmError {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn map_equal() {
let input = "{ y = 'foo' } == { y = 'foo' }";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test]
fn integer_equal() {
let input = "42 == 42";
assert_eq!(
run(input, &mut HashMap::new()),
Ok(Some(Value::boolean(true)))
);
}
#[test] #[test]
fn modulo() { fn modulo() {
let input = "42 % 2"; let input = "42 % 2";