Implement augmented assignment operators
Add support for +=, -=, *=, and /= operators. This is basically just
syntactic sugar, but it's still nice to have
a += 1
compiles to the equivalent of
a = a + 1
with all the same implications of scoping rules.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -178,17 +178,31 @@ impl Lexer {
|
||||
} else if STRING_START_CHARS.contains(self.current()) {
|
||||
return self.string();
|
||||
} else if self.mat('+') {
|
||||
return Ok(self.make_token(TokenKind::Plus));
|
||||
if self.mat('=') {
|
||||
return Ok(self.make_token(TokenKind::PlusEq));
|
||||
} else {
|
||||
return Ok(self.make_token(TokenKind::Plus));
|
||||
}
|
||||
} else if self.mat('-') {
|
||||
if self.mat('>') {
|
||||
return Ok(self.make_token(TokenKind::Arrow));
|
||||
} else if self.mat('=') {
|
||||
return Ok(self.make_token(TokenKind::MinusEq));
|
||||
} else {
|
||||
return Ok(self.make_token(TokenKind::Minus));
|
||||
}
|
||||
} else if self.mat('*') {
|
||||
return Ok(self.make_token(TokenKind::Star));
|
||||
if self.mat('=') {
|
||||
return Ok(self.make_token(TokenKind::StarEq));
|
||||
} else {
|
||||
return Ok(self.make_token(TokenKind::Star));
|
||||
}
|
||||
} else if self.mat('/') {
|
||||
return Ok(self.make_token(TokenKind::Slash));
|
||||
if self.mat('=') {
|
||||
return Ok(self.make_token(TokenKind::SlashEq));
|
||||
} else {
|
||||
return Ok(self.make_token(TokenKind::Slash));
|
||||
}
|
||||
} else if self.mat('&') {
|
||||
if self.mat('&') {
|
||||
return Ok(self.make_token(TokenKind::And));
|
||||
@@ -561,7 +575,13 @@ impl Parser {
|
||||
stmts,
|
||||
rbrace,
|
||||
}) as Box<dyn Stmt + 'static>)
|
||||
} else if self.current.kind == TokenKind::Name && self.next.kind == TokenKind::Eq {
|
||||
} else if self.current.kind == TokenKind::Name
|
||||
&& (self.next.kind == TokenKind::Eq
|
||||
|| self.next.kind == TokenKind::PlusEq
|
||||
|| self.next.kind == TokenKind::MinusEq
|
||||
|| self.next.kind == TokenKind::StarEq
|
||||
|| self.next.kind == TokenKind::SlashEq)
|
||||
{
|
||||
self.assign_stmt()
|
||||
} else {
|
||||
let expr = self.expr()?;
|
||||
@@ -745,7 +765,15 @@ impl Parser {
|
||||
let name = self
|
||||
.expect("expect name for assign statement", TokenKind::Name)?
|
||||
.clone();
|
||||
self.expect("expect '=' after name", TokenKind::Eq)?;
|
||||
let op = expect!(
|
||||
self,
|
||||
"expected '=' or augmented assign after name",
|
||||
TokenKind::Eq,
|
||||
TokenKind::PlusEq,
|
||||
TokenKind::MinusEq,
|
||||
TokenKind::StarEq,
|
||||
TokenKind::SlashEq
|
||||
)?;
|
||||
let expr = self.expr()?;
|
||||
if !self.check(TokenKind::RBrace) {
|
||||
expect!(
|
||||
@@ -757,6 +785,7 @@ impl Parser {
|
||||
}
|
||||
Ok(Box::new(AssignStmt {
|
||||
lhs: name,
|
||||
op,
|
||||
rhs: expr,
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user