mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 15:15:47 +03:00
impl add assign operator
This commit is contained in:
parent
a2862f8894
commit
d71788e8a4
@ -19,7 +19,7 @@ use super::*;
|
||||
use leo_errors::{ParserError, Result};
|
||||
use leo_span::sym;
|
||||
|
||||
const ASSIGN_TOKENS: &[Token] = &[Token::Assign];
|
||||
const ASSIGN_TOKENS: &[Token] = &[Token::Assign, Token::AddAssign];
|
||||
|
||||
impl ParserContext<'_> {
|
||||
/// Returns a [`Statement`] AST node if the next tokens represent a statement.
|
||||
@ -40,13 +40,18 @@ impl ParserContext<'_> {
|
||||
let place = self.parse_expression()?;
|
||||
|
||||
if self.eat_any(ASSIGN_TOKENS) {
|
||||
let operation = match &self.prev_token.token {
|
||||
Token::Assign => AssignOperation::Assign,
|
||||
Token::AddAssign => AssignOperation::Add,
|
||||
_ => unreachable!("`parse_assign_statement` shouldn't produce this"),
|
||||
};
|
||||
|
||||
let value = self.parse_expression()?;
|
||||
self.expect(&Token::Semicolon)?;
|
||||
Ok(Statement::Assign(Box::new(AssignStatement {
|
||||
span: place.span() + value.span(),
|
||||
place,
|
||||
// Currently only `=` so this is alright.
|
||||
operation: AssignOperation::Assign,
|
||||
operation,
|
||||
value,
|
||||
})))
|
||||
} else {
|
||||
|
@ -185,34 +185,41 @@ impl Token {
|
||||
let input_str = input;
|
||||
let mut input = input.chars().peekable();
|
||||
|
||||
// Consumes a single character token.
|
||||
let single = |input: &mut Peekable<_>, token| {
|
||||
// Returns one token matching one character.
|
||||
let match_one = |input: &mut Peekable<_>, token| {
|
||||
input.next();
|
||||
Ok((1, token))
|
||||
};
|
||||
// Consumes a character followed by `on` with `then` if found or `els` otherwise.
|
||||
let followed_by = |input: &mut Peekable<_>, on, then, els| {
|
||||
|
||||
// Returns one token matching one or two characters.
|
||||
// If the `second` character matches, return the `second_token` that matches both characters.
|
||||
// Otherwise, return the `first_token` that matches the single character.
|
||||
let match_two = |input: &mut Peekable<_>, first_token, second_char, second_token| {
|
||||
input.next();
|
||||
Ok(if input.next_if_eq(&on).is_some() {
|
||||
(2, then)
|
||||
Ok(if input.next_if_eq(&second_char).is_some() {
|
||||
(2, second_token)
|
||||
} else {
|
||||
(1, els)
|
||||
(1, first_token)
|
||||
})
|
||||
};
|
||||
// Consumes a character followed by `on_1`, `on_2` or none. Outputs case_1, case_2, or els.
|
||||
let three_cases = |input: &mut Peekable<_>, on_1, case_1, on_2, case_2, els| {
|
||||
|
||||
// Returns one token matching one or two characters.
|
||||
// If the `second` character matches, return the `second_token` that matches both characters.
|
||||
// If the `third` character matches, return the `third_token` that matches both characters.
|
||||
// Otherwise, return the `first_token` that matches the single character.
|
||||
let match_three = |input: &mut Peekable<_>, first_token, second_char, second_token, third_char, third_token| {
|
||||
input.next();
|
||||
Ok(if input.next_if_eq(&on_1).is_some() {
|
||||
(2, case_1)
|
||||
} else if input.next_if_eq(&on_2).is_some() {
|
||||
(2, case_2)
|
||||
Ok(if input.next_if_eq(&second_char).is_some() {
|
||||
(2, second_token)
|
||||
} else if input.next_if_eq(&third_char).is_some() {
|
||||
(2, third_token)
|
||||
} else {
|
||||
(1, els)
|
||||
(1, first_token)
|
||||
})
|
||||
};
|
||||
|
||||
match *input.peek().ok_or_else(ParserError::lexer_empty_input)? {
|
||||
x if x.is_ascii_whitespace() => return single(&mut input, Token::WhiteSpace),
|
||||
x if x.is_ascii_whitespace() => return match_one(&mut input, Token::WhiteSpace),
|
||||
'"' => {
|
||||
// Find end string quotation mark.
|
||||
// Instead of checking each `char` and pushing, we can avoid reallocations.
|
||||
@ -228,17 +235,17 @@ impl Token {
|
||||
return Ok((string.len() + 2, Token::StaticString(string)));
|
||||
}
|
||||
x if x.is_ascii_digit() => return Self::eat_integer(&mut input),
|
||||
'!' => return followed_by(&mut input, '=', Token::NotEq, Token::Not),
|
||||
'?' => return single(&mut input, Token::Question),
|
||||
'&' => return followed_by(&mut input, '&', Token::And, Token::BitwiseAnd),
|
||||
'(' => return single(&mut input, Token::LeftParen),
|
||||
')' => return single(&mut input, Token::RightParen),
|
||||
'_' => return single(&mut input, Token::Underscore),
|
||||
'*' => return followed_by(&mut input, '*', Token::Exp, Token::Mul),
|
||||
'+' => return single(&mut input, Token::Add),
|
||||
',' => return single(&mut input, Token::Comma),
|
||||
'-' => return followed_by(&mut input, '>', Token::Arrow, Token::Minus),
|
||||
'.' => return followed_by(&mut input, '.', Token::DotDot, Token::Dot),
|
||||
'!' => return match_two(&mut input, Token::Not, '=', Token::NotEq),
|
||||
'?' => return match_one(&mut input, Token::Question),
|
||||
'&' => return match_two(&mut input, Token::BitwiseAnd, '&', Token::And),
|
||||
'(' => return match_one(&mut input, Token::LeftParen),
|
||||
')' => return match_one(&mut input, Token::RightParen),
|
||||
'_' => return match_one(&mut input, Token::Underscore),
|
||||
'*' => return match_two(&mut input, Token::Mul, '*', Token::Exp),
|
||||
'+' => return match_two(&mut input, Token::Add, '=', Token::AddAssign),
|
||||
',' => return match_one(&mut input, Token::Comma),
|
||||
'-' => return match_two(&mut input, Token::Minus, '>', Token::Arrow),
|
||||
'.' => return match_two(&mut input, Token::Dot, '.', Token::DotDot),
|
||||
'/' => {
|
||||
input.next();
|
||||
if input.next_if_eq(&'/').is_some() {
|
||||
@ -276,17 +283,17 @@ impl Token {
|
||||
}
|
||||
return Ok((1, Token::Div));
|
||||
}
|
||||
':' => return followed_by(&mut input, ':', Token::DoubleColon, Token::Colon),
|
||||
';' => return single(&mut input, Token::Semicolon),
|
||||
'<' => return three_cases(&mut input, '=', Token::LtEq, '<', Token::Shl, Token::Lt),
|
||||
'>' => return three_cases(&mut input, '=', Token::GtEq, '>', Token::Shr, Token::Gt),
|
||||
'=' => return followed_by(&mut input, '=', Token::Eq, Token::Assign),
|
||||
'[' => return single(&mut input, Token::LeftSquare),
|
||||
']' => return single(&mut input, Token::RightSquare),
|
||||
'{' => return single(&mut input, Token::LeftCurly),
|
||||
'}' => return single(&mut input, Token::RightCurly),
|
||||
'|' => return followed_by(&mut input, '|', Token::Or, Token::BitwiseOr),
|
||||
'^' => return single(&mut input, Token::Xor),
|
||||
':' => return match_two(&mut input, Token::Colon, ':', Token::DoubleColon),
|
||||
';' => return match_one(&mut input, Token::Semicolon),
|
||||
'<' => return match_three(&mut input, Token::Lt, '=', Token::LtEq, '<', Token::Shl),
|
||||
'>' => return match_three(&mut input, Token::Gt, '=', Token::GtEq, '>', Token::Shr),
|
||||
'=' => return match_two(&mut input, Token::Assign, '=', Token::Eq),
|
||||
'[' => return match_one(&mut input, Token::LeftSquare),
|
||||
']' => return match_one(&mut input, Token::RightSquare),
|
||||
'{' => return match_one(&mut input, Token::LeftCurly),
|
||||
'}' => return match_one(&mut input, Token::RightCurly),
|
||||
'|' => return match_two(&mut input, Token::BitwiseOr, '|', Token::Or),
|
||||
'^' => return match_one(&mut input, Token::Xor),
|
||||
_ => (),
|
||||
}
|
||||
if let Some(ident) = eat_identifier(&mut input) {
|
||||
|
@ -47,6 +47,7 @@ pub enum Token {
|
||||
Gt,
|
||||
GtEq,
|
||||
Add,
|
||||
AddAssign,
|
||||
Minus,
|
||||
Mul,
|
||||
Div,
|
||||
@ -230,6 +231,7 @@ impl fmt::Display for Token {
|
||||
Gt => write!(f, ">"),
|
||||
GtEq => write!(f, ">="),
|
||||
Add => write!(f, "+"),
|
||||
AddAssign => write!(f, "+="),
|
||||
Minus => write!(f, "-"),
|
||||
Mul => write!(f, "*"),
|
||||
Div => write!(f, "/"),
|
||||
|
@ -1,5 +1,2 @@
|
||||
[main]
|
||||
a: u8 = 1u8;
|
||||
|
||||
[registers]
|
||||
r0: bool = true;
|
||||
a: u8 = 1u8;
|
12
tests/compiler/statements/operations/add_assign.leo
Normal file
12
tests/compiler/statements/operations/add_assign.leo
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_files: ../inputs/u8.in
|
||||
*/
|
||||
|
||||
function main(a: u8) -> u8 {
|
||||
let b: u8 = 1u8;
|
||||
b += a;
|
||||
|
||||
return b;
|
||||
}
|
Loading…
Reference in New Issue
Block a user