Implement more operators
- Mod - Bitwise Or - Bitwise And - Bitwise Xor - Shift Left - Shift Right
This commit is contained in:
parent
d9246c7ea1
commit
6b91264f84
@ -37,6 +37,12 @@ impl Interpreter {
|
||||
BinOpType::Mul => Value::I64(lhs * rhs),
|
||||
BinOpType::Sub => 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"),
|
||||
}
|
||||
@ -45,8 +51,8 @@ impl Interpreter {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::parser::{Ast, BinOpType};
|
||||
use super::{Interpreter, Value};
|
||||
use crate::parser::{Ast, BinOpType};
|
||||
|
||||
#[test]
|
||||
fn test_interpreter_expr() {
|
||||
|
||||
51
src/lexer.rs
51
src/lexer.rs
@ -19,6 +19,24 @@ pub enum Token {
|
||||
/// Slash (/)
|
||||
Div,
|
||||
|
||||
/// Percent (%)
|
||||
Mod,
|
||||
|
||||
/// Pipe (|)
|
||||
BOr,
|
||||
|
||||
/// Ampersand (&)
|
||||
BAnd,
|
||||
|
||||
/// Circumflex (^)
|
||||
BXor,
|
||||
|
||||
/// Shift Left (<<)
|
||||
Shl,
|
||||
|
||||
/// Shift Right (>>)
|
||||
Shr,
|
||||
|
||||
/// End of file
|
||||
EoF,
|
||||
}
|
||||
@ -57,7 +75,7 @@ impl<'a> Lexer<'a> {
|
||||
sval.push(self.next().unwrap());
|
||||
}
|
||||
// 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()));
|
||||
}
|
||||
|
||||
'>' 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::Sub),
|
||||
'*' => tokens.push(Token::Mul),
|
||||
'/' => 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
|
||||
_ => panic!("Lexer encountered unexpected char: '{}'", ch),
|
||||
@ -102,8 +132,17 @@ impl Token {
|
||||
Some(match self {
|
||||
Token::Add => BinOpType::Add,
|
||||
Token::Sub => BinOpType::Sub,
|
||||
|
||||
Token::Mul => BinOpType::Mul,
|
||||
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,
|
||||
})
|
||||
}
|
||||
@ -115,7 +154,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_lexer() {
|
||||
let code = "33 +5*2 + 4456467*2334+3";
|
||||
let code = "33 +5*2 + 4456467*2334+3 % - / << ^ | & >>";
|
||||
let expected = vec![
|
||||
Token::I64(33),
|
||||
Token::Add,
|
||||
@ -128,6 +167,14 @@ mod tests {
|
||||
Token::I64(2334),
|
||||
Token::Add,
|
||||
Token::I64(3),
|
||||
Token::Mod,
|
||||
Token::Sub,
|
||||
Token::Div,
|
||||
Token::Shl,
|
||||
Token::BXor,
|
||||
Token::BOr,
|
||||
Token::BAnd,
|
||||
Token::Shr,
|
||||
];
|
||||
|
||||
let actual = lex(code);
|
||||
|
||||
@ -16,6 +16,24 @@ pub enum BinOpType {
|
||||
|
||||
/// Divide
|
||||
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)]
|
||||
@ -55,8 +73,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
self.parse_expr_precedence(lhs, 0)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 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 {
|
||||
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.
|
||||
fn precedence(&self) -> u8 {
|
||||
match self {
|
||||
BinOpType::Add | BinOpType::Sub => 0,
|
||||
BinOpType::Mul | BinOpType::Div => 1,
|
||||
BinOpType::BOr => 0,
|
||||
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::Mul,
|
||||
Token::I64(3),
|
||||
Token::Add,
|
||||
Token::Sub,
|
||||
Token::I64(4),
|
||||
];
|
||||
|
||||
let expected = Ast::BinOp(
|
||||
BinOpType::Add,
|
||||
BinOpType::Sub,
|
||||
Ast::BinOp(
|
||||
BinOpType::Add,
|
||||
Ast::I64(1).into(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user