|
|
|
@ -76,7 +76,7 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_at_end(&self) -> bool {
|
|
|
|
|
self.source[self.current] == 0
|
|
|
|
|
self.current == self.source.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_token(&self, kind: TokenKind) -> Result<Token> {
|
|
|
|
@ -115,20 +115,19 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
|
|
|
|
|
fn skip_whitespace(&mut self) {
|
|
|
|
|
loop {
|
|
|
|
|
let c = self.peek();
|
|
|
|
|
match c {
|
|
|
|
|
' ' | '\r' | '\t' => {
|
|
|
|
|
match self.peek() {
|
|
|
|
|
Some(' ') | Some('\r') | Some('\t') => {
|
|
|
|
|
self.advance();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
'\n' => {
|
|
|
|
|
Some('\n') => {
|
|
|
|
|
self.line += 1;
|
|
|
|
|
self.advance();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
'/' => {
|
|
|
|
|
if self.peek_next() == '/' {
|
|
|
|
|
while self.peek() != '\n' && !self.is_at_end() {
|
|
|
|
|
Some('/') => {
|
|
|
|
|
if matches!(self.peek_next(), Some(c) if c == '/') {
|
|
|
|
|
while matches!(self.peek(), Some(c) if c != '\n') {
|
|
|
|
|
self.advance();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -142,21 +141,21 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn peek(&self) -> char {
|
|
|
|
|
self.source[self.current] as char
|
|
|
|
|
fn peek(&self) -> Option<char> {
|
|
|
|
|
self.source.get(self.current).map(|&x| x as char)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn peek_next(&mut self) -> char {
|
|
|
|
|
fn peek_next(&mut self) -> Option<char> {
|
|
|
|
|
if self.is_at_end() {
|
|
|
|
|
0 as char
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
self.source[self.current + 1] as char
|
|
|
|
|
Some(self.source[self.current + 1] as char)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn string(&mut self) -> Result<Token> {
|
|
|
|
|
while self.peek() != '"' && !self.is_at_end() {
|
|
|
|
|
if self.peek() == '\n' {
|
|
|
|
|
while matches!(self.peek(), Some(c) if c != '"') {
|
|
|
|
|
if self.peek() == Some('\n') {
|
|
|
|
|
self.line += 1;
|
|
|
|
|
}
|
|
|
|
|
self.advance();
|
|
|
|
@ -171,14 +170,14 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn number(&mut self) -> Result<Token> {
|
|
|
|
|
while self.peek().is_ascii_digit() {
|
|
|
|
|
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
|
|
|
self.advance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if self.peek() == '.' && self.peek_next().is_ascii_digit() {
|
|
|
|
|
if self.peek() == Some('.') && matches!(self.peek_next(), Some(c) if c.is_ascii_digit()) {
|
|
|
|
|
self.advance();
|
|
|
|
|
|
|
|
|
|
while self.peek().is_ascii_digit() {
|
|
|
|
|
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
|
|
|
self.advance();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -187,7 +186,7 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn identifier(&mut self) -> Result<Token> {
|
|
|
|
|
while is_alpha(self.peek()) || self.peek().is_ascii_digit() {
|
|
|
|
|
while matches!(self.peek(), Some(c) if is_alpha(c) || c.is_ascii_digit()) {
|
|
|
|
|
self.advance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -339,9 +338,7 @@ mod tests {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn assert_scan_token(source: &str, kind: TokenKind) {
|
|
|
|
|
let mut s = source.to_string();
|
|
|
|
|
s.push(0 as char);
|
|
|
|
|
let mut scanner = Scanner::new(&s);
|
|
|
|
|
let mut scanner = Scanner::new(source);
|
|
|
|
|
let token = scanner.scan().unwrap();
|
|
|
|
|
assert_eq!(token.kind, kind);
|
|
|
|
|
}
|
|
|
|
|