Implement more operators
- Mod - Bitwise Or - Bitwise And - Bitwise Xor - Shift Left - Shift Right
This commit is contained in:
parent
0b75c30784
commit
a569781691
@ -37,6 +37,12 @@ impl Interpreter {
|
|||||||
BinOpType::Mul => Value::I64(lhs * rhs),
|
BinOpType::Mul => Value::I64(lhs * rhs),
|
||||||
BinOpType::Sub => Value::I64(lhs - rhs),
|
BinOpType::Sub => Value::I64(lhs - rhs),
|
||||||
BinOpType::Div => Value::I64(lhs / rhs),
|
BinOpType::Div => Value::I64(lhs / rhs),
|
||||||
|
BinOpType::Mod => Value::I64(lhs % rhs),
|
||||||
|
BinOpType::BOr => Value::I64(lhs | rhs),
|
||||||
|
BinOpType::BAnd => Value::I64(lhs & rhs),
|
||||||
|
BinOpType::BXor => Value::I64(lhs ^ rhs),
|
||||||
|
BinOpType::Shr => Value::I64(lhs >> rhs),
|
||||||
|
BinOpType::Shl => Value::I64(lhs << rhs),
|
||||||
},
|
},
|
||||||
// _ => panic!("Value types are not compatible"),
|
// _ => panic!("Value types are not compatible"),
|
||||||
}
|
}
|
||||||
@ -45,8 +51,8 @@ impl Interpreter {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::parser::{Ast, BinOpType};
|
|
||||||
use super::{Interpreter, Value};
|
use super::{Interpreter, Value};
|
||||||
|
use crate::parser::{Ast, BinOpType};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_interpreter_expr() {
|
fn test_interpreter_expr() {
|
||||||
|
|||||||
51
src/lexer.rs
51
src/lexer.rs
@ -19,6 +19,24 @@ pub enum Token {
|
|||||||
/// Slash (/)
|
/// Slash (/)
|
||||||
Div,
|
Div,
|
||||||
|
|
||||||
|
/// Percent (%)
|
||||||
|
Mod,
|
||||||
|
|
||||||
|
/// Pipe (|)
|
||||||
|
BOr,
|
||||||
|
|
||||||
|
/// Ampersand (&)
|
||||||
|
BAnd,
|
||||||
|
|
||||||
|
/// Circumflex (^)
|
||||||
|
BXor,
|
||||||
|
|
||||||
|
/// Shift Left (<<)
|
||||||
|
Shl,
|
||||||
|
|
||||||
|
/// Shift Right (>>)
|
||||||
|
Shr,
|
||||||
|
|
||||||
/// End of file
|
/// End of file
|
||||||
EoF,
|
EoF,
|
||||||
}
|
}
|
||||||
@ -57,7 +75,7 @@ impl<'a> Lexer<'a> {
|
|||||||
sval.push(self.next().unwrap());
|
sval.push(self.next().unwrap());
|
||||||
}
|
}
|
||||||
// Next char is not a number, so stop and finish the number token
|
// Next char is not a number, so stop and finish the number token
|
||||||
_ => break
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,10 +83,22 @@ impl<'a> Lexer<'a> {
|
|||||||
tokens.push(Token::I64(sval.parse().unwrap()));
|
tokens.push(Token::I64(sval.parse().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
'>' if matches!(self.peek(), Some('>')) => {
|
||||||
|
self.next();
|
||||||
|
tokens.push(Token::Shr);
|
||||||
|
}
|
||||||
|
'<' if matches!(self.peek(), Some('<')) => {
|
||||||
|
self.next();
|
||||||
|
tokens.push(Token::Shl);
|
||||||
|
}
|
||||||
'+' => tokens.push(Token::Add),
|
'+' => tokens.push(Token::Add),
|
||||||
'-' => tokens.push(Token::Sub),
|
'-' => tokens.push(Token::Sub),
|
||||||
'*' => tokens.push(Token::Mul),
|
'*' => tokens.push(Token::Mul),
|
||||||
'/' => tokens.push(Token::Div),
|
'/' => tokens.push(Token::Div),
|
||||||
|
'%' => tokens.push(Token::Mod),
|
||||||
|
'|' => tokens.push(Token::BOr),
|
||||||
|
'&' => tokens.push(Token::BAnd),
|
||||||
|
'^' => tokens.push(Token::BXor),
|
||||||
|
|
||||||
//TODO: Don't panic, keep calm
|
//TODO: Don't panic, keep calm
|
||||||
_ => panic!("Lexer encountered unexpected char: '{}'", ch),
|
_ => panic!("Lexer encountered unexpected char: '{}'", ch),
|
||||||
@ -102,8 +132,17 @@ impl Token {
|
|||||||
Some(match self {
|
Some(match self {
|
||||||
Token::Add => BinOpType::Add,
|
Token::Add => BinOpType::Add,
|
||||||
Token::Sub => BinOpType::Sub,
|
Token::Sub => BinOpType::Sub,
|
||||||
|
|
||||||
Token::Mul => BinOpType::Mul,
|
Token::Mul => BinOpType::Mul,
|
||||||
Token::Div => BinOpType::Div,
|
Token::Div => BinOpType::Div,
|
||||||
|
Token::Mod => BinOpType::Mod,
|
||||||
|
|
||||||
|
Token::BAnd => BinOpType::BAnd,
|
||||||
|
Token::BOr => BinOpType::BOr,
|
||||||
|
Token::BXor => BinOpType::BXor,
|
||||||
|
|
||||||
|
Token::Shl => BinOpType::Shl,
|
||||||
|
Token::Shr => BinOpType::Shr,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -115,7 +154,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lexer() {
|
fn test_lexer() {
|
||||||
let code = "33 +5*2 + 4456467*2334+3";
|
let code = "33 +5*2 + 4456467*2334+3 % - / << ^ | & >>";
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Token::I64(33),
|
Token::I64(33),
|
||||||
Token::Add,
|
Token::Add,
|
||||||
@ -128,6 +167,14 @@ mod tests {
|
|||||||
Token::I64(2334),
|
Token::I64(2334),
|
||||||
Token::Add,
|
Token::Add,
|
||||||
Token::I64(3),
|
Token::I64(3),
|
||||||
|
Token::Mod,
|
||||||
|
Token::Sub,
|
||||||
|
Token::Div,
|
||||||
|
Token::Shl,
|
||||||
|
Token::BXor,
|
||||||
|
Token::BOr,
|
||||||
|
Token::BAnd,
|
||||||
|
Token::Shr,
|
||||||
];
|
];
|
||||||
|
|
||||||
let actual = lex(code);
|
let actual = lex(code);
|
||||||
|
|||||||
@ -16,6 +16,24 @@ pub enum BinOpType {
|
|||||||
|
|
||||||
/// Divide
|
/// Divide
|
||||||
Div,
|
Div,
|
||||||
|
|
||||||
|
/// Modulo
|
||||||
|
Mod,
|
||||||
|
|
||||||
|
/// Bitwise OR (inclusive or)
|
||||||
|
BOr,
|
||||||
|
|
||||||
|
/// Bitwise And
|
||||||
|
BAnd,
|
||||||
|
|
||||||
|
/// Bitwise Xor (exclusive or)
|
||||||
|
BXor,
|
||||||
|
|
||||||
|
/// Shift Left
|
||||||
|
Shl,
|
||||||
|
|
||||||
|
/// Shift Right
|
||||||
|
Shr,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
@ -55,8 +73,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
self.parse_expr_precedence(lhs, 0)
|
self.parse_expr_precedence(lhs, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Parse binary expressions with a precedence equal to or higher than min_prec
|
/// Parse binary expressions with a precedence equal to or higher than min_prec
|
||||||
fn parse_expr_precedence(&mut self, mut lhs: Ast, min_prec: u8) -> Ast {
|
fn parse_expr_precedence(&mut self, mut lhs: Ast, min_prec: u8) -> Ast {
|
||||||
while let Some(binop) = &self.peek().try_to_binop() {
|
while let Some(binop) = &self.peek().try_to_binop() {
|
||||||
@ -115,8 +131,12 @@ impl BinOpType {
|
|||||||
/// For example Multiplication is stronger than addition, so Mul has higher precedence than Add.
|
/// For example Multiplication is stronger than addition, so Mul has higher precedence than Add.
|
||||||
fn precedence(&self) -> u8 {
|
fn precedence(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
BinOpType::Add | BinOpType::Sub => 0,
|
BinOpType::BOr => 0,
|
||||||
BinOpType::Mul | BinOpType::Div => 1,
|
BinOpType::BXor => 1,
|
||||||
|
BinOpType::BAnd => 2,
|
||||||
|
BinOpType::Shl | BinOpType::Shr => 3,
|
||||||
|
BinOpType::Add | BinOpType::Sub => 4,
|
||||||
|
BinOpType::Mul | BinOpType::Div | BinOpType::Mod => 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,12 +156,12 @@ mod tests {
|
|||||||
Token::I64(2),
|
Token::I64(2),
|
||||||
Token::Mul,
|
Token::Mul,
|
||||||
Token::I64(3),
|
Token::I64(3),
|
||||||
Token::Add,
|
Token::Sub,
|
||||||
Token::I64(4),
|
Token::I64(4),
|
||||||
];
|
];
|
||||||
|
|
||||||
let expected = Ast::BinOp(
|
let expected = Ast::BinOp(
|
||||||
BinOpType::Add,
|
BinOpType::Sub,
|
||||||
Ast::BinOp(
|
Ast::BinOp(
|
||||||
BinOpType::Add,
|
BinOpType::Add,
|
||||||
Ast::I64(1).into(),
|
Ast::I64(1).into(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user