don't use a null sentinel

main
Alpha Chen 2 years ago
parent 02abf5ca96
commit 7baa16ee8e
Signed by: alpha
SSH Key Fingerprint: SHA256:3fOT8fiYQG/aK9ntivV3Bqtg8AYQ7q4nV6ZgihOA20g

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

Loading…
Cancel
Save