Compare commits

...

2 Commits

7 changed files with 34 additions and 7 deletions
+5
View File
@@ -0,0 +1,5 @@
let a = 7
let b = a % 3
print("b=", b)
a %= 4
print("a=", a)
+2
View File
@@ -106,6 +106,7 @@ pub enum BinaryOp {
Sub, Sub,
Mul, Mul,
Div, Div,
Mod,
Greater, Greater,
GreaterEqual, GreaterEqual,
@@ -129,4 +130,5 @@ pub enum AssignOp {
MinusEqual, // -= MinusEqual, // -=
StarEqual, // *= StarEqual, // *=
SlashEqual, // /= SlashEqual, // /=
PercentEqual, // %=
} }
+1 -4
View File
@@ -3,10 +3,7 @@
use crate::interpreter::Value; use crate::interpreter::Value;
pub fn print(args: Vec<Value>) -> Value { pub fn print(args: Vec<Value>) -> Value {
for (i, arg) in args.iter().enumerate() { for arg in args.iter() {
if i > 0 {
print!(" ");
}
print!("{}", arg); print!("{}", arg);
} }
println!(); println!();
+12
View File
@@ -314,6 +314,13 @@ impl Interpreter {
token: None, token: None,
}), }),
}, },
crate::ast::expr::BinaryOp::Mod => match (l,r) {
(Value::Number(a), Value::Number(b)) => Ok(Value::Number(a%b)),
_ => Err(RuntimeError::RuntimeError {
message: "Invalid '%' operands".to_string(),
token: None,
}),
},
crate::ast::expr::BinaryOp::Greater => Ok(Value::Bool(self.as_number(&l)? > self.as_number(&r)?)), crate::ast::expr::BinaryOp::Greater => Ok(Value::Bool(self.as_number(&l)? > self.as_number(&r)?)),
crate::ast::expr::BinaryOp::GreaterEqual => Ok(Value::Bool(self.as_number(&l)? >= self.as_number(&r)?)), crate::ast::expr::BinaryOp::GreaterEqual => Ok(Value::Bool(self.as_number(&l)? >= self.as_number(&r)?)),
crate::ast::expr::BinaryOp::Less => Ok(Value::Bool(self.as_number(&l)? < self.as_number(&r)?)), crate::ast::expr::BinaryOp::Less => Ok(Value::Bool(self.as_number(&l)? < self.as_number(&r)?)),
@@ -443,6 +450,11 @@ impl Interpreter {
let right_num = self.as_number(&right)?; let right_num = self.as_number(&right)?;
Ok(Value::Number(left_num / right_num)) Ok(Value::Number(left_num / right_num))
} }
AssignOp::PercentEqual => {
let left_num = self.as_number(&left)?;
let right_num = self.as_number(&right)?;
Ok(Value::Number(left_num % right_num))
}
} }
} }
+8
View File
@@ -96,6 +96,14 @@ impl Lexer {
} }
} }
'%' => {
if self.match_char('=') {
TokenKind::PercentEqual
} else {
TokenKind::Percent
}
}
'!' => { '!' => {
if self.match_char('=') { if self.match_char('=') {
TokenKind::BangEqual TokenKind::BangEqual
+2 -2
View File
@@ -9,14 +9,14 @@ pub enum TokenKind {
Colon, Colon,
// 运算符 // 运算符
Plus, Minus, Star, Slash, Plus, Minus, Star, Slash, Percent,
Bang, Bang,
Equal, Equal,
Greater, GreaterEqual, Greater, GreaterEqual,
Less, LessEqual, Less, LessEqual,
EqualEqual, BangEqual, EqualEqual, BangEqual,
AndAnd, OrOr, AndAnd, OrOr,
PlusEqual, MinusEqual, StarEqual, SlashEqual, PlusEqual, MinusEqual, StarEqual, SlashEqual, PercentEqual,
// 字面量 // 字面量
Identifier(String), Identifier(String),
+4 -1
View File
@@ -212,6 +212,8 @@ impl Parser {
Some(AssignOp::StarEqual) Some(AssignOp::StarEqual)
} else if self.match_kind(&[TokenKind::SlashEqual]) { } else if self.match_kind(&[TokenKind::SlashEqual]) {
Some(AssignOp::SlashEqual) Some(AssignOp::SlashEqual)
} else if self.match_kind(&[TokenKind::PercentEqual]) {
Some(AssignOp::PercentEqual)
} else { } else {
None None
}; };
@@ -324,10 +326,11 @@ impl Parser {
fn factor(&mut self) -> Expr { fn factor(&mut self) -> Expr {
let mut expr = self.unary(); let mut expr = self.unary();
while self.match_kind(&[TokenKind::Star, TokenKind::Slash]) { while self.match_kind(&[TokenKind::Star, TokenKind::Slash, TokenKind::Percent]) {
let op = match self.previous().kind { let op = match self.previous().kind {
TokenKind::Star => BinaryOp::Mul, TokenKind::Star => BinaryOp::Mul,
TokenKind::Slash => BinaryOp::Div, TokenKind::Slash => BinaryOp::Div,
TokenKind::Percent => BinaryOp::Mod,
_ => unreachable!(), _ => unreachable!(),
}; };
let right = self.unary(); let right = self.unary();