Implement div & sub

This commit is contained in:
Kai-Philipp Nosper 2022-01-27 22:29:06 +01:00
parent ed2ae144dd
commit 0b75c30784
3 changed files with 32 additions and 2 deletions

View File

@ -35,6 +35,8 @@ impl Interpreter {
(Value::I64(lhs), Value::I64(rhs)) => match bo { (Value::I64(lhs), Value::I64(rhs)) => match bo {
BinOpType::Add => Value::I64(lhs + rhs), BinOpType::Add => Value::I64(lhs + rhs),
BinOpType::Mul => Value::I64(lhs * rhs), BinOpType::Mul => Value::I64(lhs * rhs),
BinOpType::Sub => Value::I64(lhs - rhs),
BinOpType::Div => Value::I64(lhs / rhs),
}, },
// _ => panic!("Value types are not compatible"), // _ => panic!("Value types are not compatible"),
} }

View File

@ -10,9 +10,15 @@ pub enum Token {
/// Plus (+) /// Plus (+)
Add, Add,
/// Minus (-)
Sub,
/// Asterisk (*) /// Asterisk (*)
Mul, Mul,
/// Slash (/)
Div,
/// End of file /// End of file
EoF, EoF,
} }
@ -60,7 +66,9 @@ impl<'a> Lexer<'a> {
} }
'+' => tokens.push(Token::Add), '+' => tokens.push(Token::Add),
'-' => tokens.push(Token::Sub),
'*' => tokens.push(Token::Mul), '*' => tokens.push(Token::Mul),
'/' => tokens.push(Token::Div),
//TODO: Don't panic, keep calm //TODO: Don't panic, keep calm
_ => panic!("Lexer encountered unexpected char: '{}'", ch), _ => panic!("Lexer encountered unexpected char: '{}'", ch),
@ -93,7 +101,9 @@ impl Token {
pub fn try_to_binop(&self) -> Option<BinOpType> { pub fn try_to_binop(&self) -> Option<BinOpType> {
Some(match self { Some(match self {
Token::Add => BinOpType::Add, Token::Add => BinOpType::Add,
Token::Sub => BinOpType::Sub,
Token::Mul => BinOpType::Mul, Token::Mul => BinOpType::Mul,
Token::Div => BinOpType::Div,
_ => return None, _ => return None,
}) })
} }

View File

@ -8,8 +8,14 @@ pub enum BinOpType {
/// Addition /// Addition
Add, Add,
/// Subtraction
Sub,
/// Multiplication /// Multiplication
Mul, Mul,
/// Divide
Div,
} }
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
@ -20,6 +26,15 @@ pub enum Ast {
BinOp(BinOpType, Box<Ast>, Box<Ast>), BinOp(BinOpType, Box<Ast>, Box<Ast>),
} }
/*
## Grammar
### Expressions
`expr_primary = LITERAL` \
`expr_mul = expr_primary (("*" | "/") expr_primary)*` \
`expr_add = expr_mul (("+" | "-") expr_mul)*` \
`expr = expr_add` \
*/
struct Parser<T: Iterator<Item = Token>> { struct Parser<T: Iterator<Item = Token>> {
tokens: Peekable<T>, tokens: Peekable<T>,
} }
@ -40,9 +55,12 @@ 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() {
// Stop if the next operator has a lower binding power
if !(binop.precedence() >= min_prec) { if !(binop.precedence() >= min_prec) {
break; break;
} }
@ -97,8 +115,8 @@ 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 => 0, BinOpType::Add | BinOpType::Sub => 0,
BinOpType::Mul => 1, BinOpType::Mul | BinOpType::Div => 1,
} }
} }
} }