Implement equality operation
This commit is contained in:
parent
24a2642f17
commit
f389f7e422
@ -238,6 +238,7 @@ pub enum BinaryOperator {
|
||||
Subtract,
|
||||
|
||||
// Comparison
|
||||
Equal,
|
||||
Greater,
|
||||
GreaterOrEqual,
|
||||
Less,
|
||||
@ -254,6 +255,7 @@ impl Display for BinaryOperator {
|
||||
BinaryOperator::Add => write!(f, "+"),
|
||||
BinaryOperator::And => write!(f, "&&"),
|
||||
BinaryOperator::Divide => write!(f, "/"),
|
||||
BinaryOperator::Equal => write!(f, "=="),
|
||||
BinaryOperator::Greater => write!(f, ">"),
|
||||
BinaryOperator::GreaterOrEqual => write!(f, ">="),
|
||||
BinaryOperator::Less => write!(f, "<"),
|
||||
|
@ -143,9 +143,15 @@ impl Lexer {
|
||||
(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;
|
||||
@ -435,6 +441,21 @@ impl From<ParseIntError> for LexError {
|
||||
mod tests {
|
||||
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]
|
||||
fn modulo() {
|
||||
let input = "42 % 2";
|
||||
|
@ -319,6 +319,23 @@ impl<'src> Parser<'src> {
|
||||
(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 {
|
||||
match self.current.0 {
|
||||
Token::DoubleEqual => 6,
|
||||
Token::Greater | Token::GreaterEqual | Token::Less | Token::LessEqual => 5,
|
||||
Token::Dot => 4,
|
||||
Token::Percent => 3,
|
||||
@ -613,6 +631,26 @@ mod tests {
|
||||
|
||||
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]
|
||||
fn modulo() {
|
||||
let input = "42 % 2";
|
||||
|
@ -27,6 +27,7 @@ pub enum Token<'src> {
|
||||
Comma,
|
||||
Dot,
|
||||
DoubleAmpersand,
|
||||
DoubleEqual,
|
||||
DoublePipe,
|
||||
Equal,
|
||||
Greater,
|
||||
@ -53,6 +54,7 @@ impl<'src> Token<'src> {
|
||||
Token::Comma => TokenOwned::Comma,
|
||||
Token::Dot => TokenOwned::Dot,
|
||||
Token::DoubleAmpersand => TokenOwned::DoubleAmpersand,
|
||||
Token::DoubleEqual => TokenOwned::DoubleEqual,
|
||||
Token::DoublePipe => TokenOwned::DoublePipe,
|
||||
Token::Eof => TokenOwned::Eof,
|
||||
Token::Equal => TokenOwned::Equal,
|
||||
@ -89,6 +91,7 @@ impl<'src> Token<'src> {
|
||||
Token::Comma => ",",
|
||||
Token::Dot => ".",
|
||||
Token::DoubleAmpersand => "&&",
|
||||
Token::DoubleEqual => "==",
|
||||
Token::DoublePipe => "||",
|
||||
Token::Eof => "EOF",
|
||||
Token::Equal => "=",
|
||||
@ -136,6 +139,9 @@ impl<'src> PartialEq for Token<'src> {
|
||||
(Token::Boolean(left), Token::Boolean(right)) => left == right,
|
||||
(Token::Comma, Token::Comma) => 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::Equal, Token::Equal) => true,
|
||||
(Token::Greater, Token::Greater) => true,
|
||||
@ -192,6 +198,7 @@ pub enum TokenOwned {
|
||||
Comma,
|
||||
Dot,
|
||||
DoubleAmpersand,
|
||||
DoubleEqual,
|
||||
DoublePipe,
|
||||
Equal,
|
||||
Greater,
|
||||
@ -218,6 +225,7 @@ impl Display for TokenOwned {
|
||||
TokenOwned::Comma => Token::Comma.fmt(f),
|
||||
TokenOwned::Dot => Token::Dot.fmt(f),
|
||||
TokenOwned::DoubleAmpersand => Token::DoubleAmpersand.fmt(f),
|
||||
TokenOwned::DoubleEqual => Token::DoubleEqual.fmt(f),
|
||||
TokenOwned::DoublePipe => Token::DoublePipe.fmt(f),
|
||||
TokenOwned::Eof => Token::Eof.fmt(f),
|
||||
TokenOwned::Equal => Token::Equal.fmt(f),
|
||||
|
@ -96,6 +96,7 @@ impl Vm {
|
||||
BinaryOperator::Add => left_value.add(&right_value),
|
||||
BinaryOperator::And => left_value.and(&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::GreaterOrEqual => {
|
||||
left_value.greater_than_or_equal(&right_value)
|
||||
@ -433,6 +434,26 @@ impl Display for VmError {
|
||||
mod tests {
|
||||
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]
|
||||
fn modulo() {
|
||||
let input = "42 % 2";
|
||||
|
Loading…
Reference in New Issue
Block a user