|
|
@ -18,7 +18,7 @@ macro_rules! vop { |
|
|
|
let preview = $this.preview_next().unwrap(); |
|
|
|
let preview = $this.preview_next().unwrap(); |
|
|
|
match preview { |
|
|
|
match preview { |
|
|
|
'=' => { |
|
|
|
'=' => { |
|
|
|
$this.next()?; |
|
|
|
$this.next(); |
|
|
|
$assign_op |
|
|
|
$assign_op |
|
|
|
} |
|
|
|
} |
|
|
|
_ => $op, |
|
|
|
_ => $op, |
|
|
@ -28,11 +28,11 @@ macro_rules! vop { |
|
|
|
let preview = $this.preview_next().unwrap(); |
|
|
|
let preview = $this.preview_next().unwrap(); |
|
|
|
match preview { |
|
|
|
match preview { |
|
|
|
'=' => { |
|
|
|
'=' => { |
|
|
|
$this.next()?; |
|
|
|
$this.next(); |
|
|
|
$assign_op |
|
|
|
$assign_op |
|
|
|
}, |
|
|
|
}, |
|
|
|
$($case => { |
|
|
|
$($case => { |
|
|
|
$this.next()?; |
|
|
|
$this.next(); |
|
|
|
$block |
|
|
|
$block |
|
|
|
})+, |
|
|
|
})+, |
|
|
|
_ => $op |
|
|
|
_ => $op |
|
|
@ -143,10 +143,10 @@ impl<'a> Lexer<'a> { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// next fetches the next token and return it, or a LexerError if there are no more.
|
|
|
|
/// next fetches the next token and return it, or a LexerError if there are no more.
|
|
|
|
fn next(&mut self) -> Result<char, LexerError> { |
|
|
|
fn next(&mut self) -> char { |
|
|
|
match self.buffer.next() { |
|
|
|
match self.buffer.next() { |
|
|
|
Some(ch) => Ok(ch), |
|
|
|
Some(ch) => ch, |
|
|
|
None => Err(LexerError::new("finished")), |
|
|
|
None => panic!("No more more characters to consume from input stream, use preview_next() first to check before calling next()"), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -154,7 +154,7 @@ impl<'a> Lexer<'a> { |
|
|
|
fn read_line(&mut self) -> Result<String, LexerError> { |
|
|
|
fn read_line(&mut self) -> Result<String, LexerError> { |
|
|
|
let mut buf = String::new(); |
|
|
|
let mut buf = String::new(); |
|
|
|
while self.preview_next().is_some() { |
|
|
|
while self.preview_next().is_some() { |
|
|
|
let ch = self.next()?; |
|
|
|
let ch = self.next(); |
|
|
|
match ch { |
|
|
|
match ch { |
|
|
|
_ if ch.is_ascii_control() => { |
|
|
|
_ if ch.is_ascii_control() => { |
|
|
|
break; |
|
|
|
break; |
|
|
@ -164,7 +164,6 @@ impl<'a> Lexer<'a> { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ok(buf) |
|
|
|
Ok(buf) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -183,7 +182,7 @@ impl<'a> Lexer<'a> { |
|
|
|
while self.buffer.peek().is_some() |
|
|
|
while self.buffer.peek().is_some() |
|
|
|
&& f(self.preview_next().expect("Could not preview next value")) |
|
|
|
&& f(self.preview_next().expect("Could not preview next value")) |
|
|
|
{ |
|
|
|
{ |
|
|
|
s.push(self.next()?); |
|
|
|
s.push(self.next()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ok(s) |
|
|
|
Ok(s) |
|
|
@ -205,12 +204,12 @@ impl<'a> Lexer<'a> { |
|
|
|
return Ok(()); |
|
|
|
return Ok(()); |
|
|
|
} |
|
|
|
} |
|
|
|
self.column_number += 1; |
|
|
|
self.column_number += 1; |
|
|
|
let ch = self.next()?; |
|
|
|
let ch = self.next(); |
|
|
|
match ch { |
|
|
|
match ch { |
|
|
|
'"' | '\'' => { |
|
|
|
'"' | '\'' => { |
|
|
|
let mut buf = String::new(); |
|
|
|
let mut buf = String::new(); |
|
|
|
loop { |
|
|
|
loop { |
|
|
|
match self.next()? { |
|
|
|
match self.next() { |
|
|
|
'\'' if ch == '\'' => { |
|
|
|
'\'' if ch == '\'' => { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -218,7 +217,7 @@ impl<'a> Lexer<'a> { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
'\\' => { |
|
|
|
'\\' => { |
|
|
|
let escape = self.next()?; |
|
|
|
let escape = self.next(); |
|
|
|
if escape != '\n' { |
|
|
|
if escape != '\n' { |
|
|
|
let escaped_ch = match escape { |
|
|
|
let escaped_ch = match escape { |
|
|
|
'n' => '\n', |
|
|
|
'n' => '\n', |
|
|
@ -230,7 +229,7 @@ impl<'a> Lexer<'a> { |
|
|
|
'x' => { |
|
|
|
'x' => { |
|
|
|
let mut nums = String::with_capacity(2); |
|
|
|
let mut nums = String::with_capacity(2); |
|
|
|
for _ in 0_u8..2 { |
|
|
|
for _ in 0_u8..2 { |
|
|
|
nums.push(self.next()?); |
|
|
|
nums.push(self.next()); |
|
|
|
} |
|
|
|
} |
|
|
|
self.column_number += 2; |
|
|
|
self.column_number += 2; |
|
|
|
let as_num = match u64::from_str_radix(&nums, 16) { |
|
|
|
let as_num = match u64::from_str_radix(&nums, 16) { |
|
|
@ -265,7 +264,7 @@ impl<'a> Lexer<'a> { |
|
|
|
let c = from_u32(as_num) |
|
|
|
let c = from_u32(as_num) |
|
|
|
.expect("Invalid Unicode escape sequence"); |
|
|
|
.expect("Invalid Unicode escape sequence"); |
|
|
|
|
|
|
|
|
|
|
|
self.next()?; // '}'
|
|
|
|
self.next(); // '}'
|
|
|
|
self.column_number += |
|
|
|
self.column_number += |
|
|
|
(s.len() as u64).wrapping_add(3); |
|
|
|
(s.len() as u64).wrapping_add(3); |
|
|
|
c |
|
|
|
c |
|
|
@ -326,7 +325,7 @@ impl<'a> Lexer<'a> { |
|
|
|
let num = if self.next_is('x') { |
|
|
|
let num = if self.next_is('x') { |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
if ch.is_digit(16) { |
|
|
|
if ch.is_digit(16) { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -335,7 +334,7 @@ impl<'a> Lexer<'a> { |
|
|
|
} else if self.next_is('b') { |
|
|
|
} else if self.next_is('b') { |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
if ch.is_digit(2) { |
|
|
|
if ch.is_digit(2) { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -348,15 +347,15 @@ impl<'a> Lexer<'a> { |
|
|
|
match next_ch { |
|
|
|
match next_ch { |
|
|
|
c if next_ch.is_digit(8) => { |
|
|
|
c if next_ch.is_digit(8) => { |
|
|
|
buf.push(c); |
|
|
|
buf.push(c); |
|
|
|
self.next()?; |
|
|
|
self.next(); |
|
|
|
} |
|
|
|
} |
|
|
|
'O' | 'o' => { |
|
|
|
'O' | 'o' => { |
|
|
|
self.next()?; |
|
|
|
self.next(); |
|
|
|
} |
|
|
|
} |
|
|
|
'8' | '9' | '.' => { |
|
|
|
'8' | '9' | '.' => { |
|
|
|
gone_decimal = true; |
|
|
|
gone_decimal = true; |
|
|
|
buf.push(next_ch); |
|
|
|
buf.push(next_ch); |
|
|
|
self.next()?; |
|
|
|
self.next(); |
|
|
|
} |
|
|
|
} |
|
|
|
_ => break, |
|
|
|
_ => break, |
|
|
|
} |
|
|
|
} |
|
|
@ -376,7 +375,7 @@ impl<'a> Lexer<'a> { |
|
|
|
'digitloop: while let Some(ch) = self.preview_next() { |
|
|
|
'digitloop: while let Some(ch) = self.preview_next() { |
|
|
|
match ch { |
|
|
|
match ch { |
|
|
|
'.' => loop { |
|
|
|
'.' => loop { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
|
|
|
|
|
|
|
|
let c = match self.preview_next() { |
|
|
|
let c = match self.preview_next() { |
|
|
|
Some(ch) => ch, |
|
|
|
Some(ch) => ch, |
|
|
@ -388,10 +387,10 @@ impl<'a> Lexer<'a> { |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
'e' | '+' | '-' => { |
|
|
|
'e' | '+' | '-' => { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
} |
|
|
|
} |
|
|
|
_ if ch.is_digit(10) => { |
|
|
|
_ if ch.is_digit(10) => { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
} |
|
|
|
} |
|
|
|
_ => break, |
|
|
|
_ => break, |
|
|
|
} |
|
|
|
} |
|
|
@ -405,7 +404,7 @@ impl<'a> Lexer<'a> { |
|
|
|
let mut buf = ch.to_string(); |
|
|
|
let mut buf = ch.to_string(); |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
while let Some(ch) = self.preview_next() { |
|
|
|
if ch.is_alphabetic() || ch.is_digit(10) || ch == '_' { |
|
|
|
if ch.is_alphabetic() || ch.is_digit(10) || ch == '_' { |
|
|
|
buf.push(self.next()?); |
|
|
|
buf.push(self.next()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -463,7 +462,7 @@ impl<'a> Lexer<'a> { |
|
|
|
'*' => { |
|
|
|
'*' => { |
|
|
|
let mut buf = String::new(); |
|
|
|
let mut buf = String::new(); |
|
|
|
loop { |
|
|
|
loop { |
|
|
|
match self.next()? { |
|
|
|
match self.next() { |
|
|
|
'*' => { |
|
|
|
'*' => { |
|
|
|
if self.next_is('/') { |
|
|
|
if self.next_is('/') { |
|
|
|
break; |
|
|
|
break; |
|
|
@ -497,7 +496,7 @@ impl<'a> Lexer<'a> { |
|
|
|
// escape sequence
|
|
|
|
// escape sequence
|
|
|
|
Some('\\') => { |
|
|
|
Some('\\') => { |
|
|
|
body.push('\\'); |
|
|
|
body.push('\\'); |
|
|
|
match self.next()? { |
|
|
|
match self.next() { |
|
|
|
// newline not allowed in regex literal
|
|
|
|
// newline not allowed in regex literal
|
|
|
|
'\n' | '\r' | '\u{2028}' | '\u{2029}' => break, |
|
|
|
'\n' | '\r' | '\u{2028}' | '\u{2029}' => break, |
|
|
|
ch => body.push(ch), |
|
|
|
ch => body.push(ch), |
|
|
|