|
|
@ -183,51 +183,35 @@ impl<'a> Scanner<'a> {
|
|
|
|
|
|
|
|
|
|
|
|
fn identifier_type(&self) -> TokenKind {
|
|
|
|
fn identifier_type(&self) -> TokenKind {
|
|
|
|
match self.source[0] as char {
|
|
|
|
match self.source[0] as char {
|
|
|
|
'a' => self.check_keyword(1, "nd", TokenKind::And),
|
|
|
|
'a' if &self.source[1..self.current] == "nd".as_bytes() => TokenKind::And,
|
|
|
|
'c' => self.check_keyword(1, "lass", TokenKind::Class),
|
|
|
|
'c' if &self.source[1..self.current] == "lass".as_bytes() => TokenKind::Class,
|
|
|
|
'e' => self.check_keyword(1, "lse", TokenKind::Else),
|
|
|
|
'e' if &self.source[1..self.current] == "lse".as_bytes() => TokenKind::Else,
|
|
|
|
'i' => self.check_keyword(1, "f", TokenKind::If),
|
|
|
|
'i' if &self.source[1..self.current] == "f".as_bytes() => TokenKind::If,
|
|
|
|
'n' => self.check_keyword(1, "il", TokenKind::Nil),
|
|
|
|
'n' if &self.source[1..self.current] == "il".as_bytes() => TokenKind::Nil,
|
|
|
|
'o' => self.check_keyword(1, "r", TokenKind::Or),
|
|
|
|
'o' if &self.source[1..self.current] == "r".as_bytes() => TokenKind::Or,
|
|
|
|
'p' => self.check_keyword(1, "rint", TokenKind::Print),
|
|
|
|
'p' if &self.source[1..self.current] == "rint".as_bytes() => TokenKind::Print,
|
|
|
|
'r' => self.check_keyword(1, "eturn", TokenKind::Return),
|
|
|
|
'r' if &self.source[1..self.current] == "eturn".as_bytes() => TokenKind::Return,
|
|
|
|
's' => self.check_keyword(1, "uper", TokenKind::Super),
|
|
|
|
's' if &self.source[1..self.current] == "uper".as_bytes() => TokenKind::Super,
|
|
|
|
'v' => self.check_keyword(1, "ar", TokenKind::Var),
|
|
|
|
'v' if &self.source[1..self.current] == "ar".as_bytes() => TokenKind::Var,
|
|
|
|
'w' => self.check_keyword(1, "hile", TokenKind::While),
|
|
|
|
'w' if &self.source[1..self.current] == "hile".as_bytes() => TokenKind::While,
|
|
|
|
'f' => {
|
|
|
|
'f' if self.current > 1 => {
|
|
|
|
if self.current > 1 {
|
|
|
|
match self.source[1] as char {
|
|
|
|
match self.source[1] as char {
|
|
|
|
'a' if &self.source[2..self.current] == "lse".as_bytes() => TokenKind::False,
|
|
|
|
'a' => self.check_keyword(2, "lse", TokenKind::False),
|
|
|
|
'o' if &self.source[2..self.current] == "r".as_bytes() => TokenKind::For,
|
|
|
|
'o' => self.check_keyword(2, "r", TokenKind::For),
|
|
|
|
'u' if &self.source[2..self.current] == "n".as_bytes() => TokenKind::Fun,
|
|
|
|
'u' => self.check_keyword(2, "n", TokenKind::Fun),
|
|
|
|
_ => TokenKind::Identifier,
|
|
|
|
_ => TokenKind::Identifier
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
TokenKind::Identifier
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
't' => {
|
|
|
|
't' if self.current > 1 => {
|
|
|
|
if self.current > 1 {
|
|
|
|
match self.source[1] as char {
|
|
|
|
match self.source[1] as char {
|
|
|
|
'h' if &self.source[2..self.current] == "is".as_bytes() => TokenKind::This,
|
|
|
|
'h' => self.check_keyword(2, "is", TokenKind::This),
|
|
|
|
'r' if &self.source[2..self.current] == "ue".as_bytes() => TokenKind::True,
|
|
|
|
'r' => self.check_keyword(2, "ue", TokenKind::True),
|
|
|
|
_ => TokenKind::Identifier,
|
|
|
|
_ => TokenKind::Identifier
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
TokenKind::Identifier
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => TokenKind::Identifier,
|
|
|
|
_ => TokenKind::Identifier,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn check_keyword(&self, start: usize, rest: &str, kind: TokenKind) -> TokenKind {
|
|
|
|
|
|
|
|
if &self.source[start..self.current] == rest.as_bytes() {
|
|
|
|
|
|
|
|
kind
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
TokenKind::Identifier
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn is_alpha(c: char) -> bool {
|
|
|
|
fn is_alpha(c: char) -> bool {
|
|
|
@ -311,8 +295,12 @@ mod tests {
|
|
|
|
assert_scan_token("1a", TokenKind::Number);
|
|
|
|
assert_scan_token("1a", TokenKind::Number);
|
|
|
|
assert_scan_token("1.1", TokenKind::Number);
|
|
|
|
assert_scan_token("1.1", TokenKind::Number);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_scan_token("a", TokenKind::Identifier);
|
|
|
|
|
|
|
|
assert_scan_token("an", TokenKind::Identifier);
|
|
|
|
assert_scan_token("and", TokenKind::And);
|
|
|
|
assert_scan_token("and", TokenKind::And);
|
|
|
|
assert_scan_token("andy", TokenKind::Identifier);
|
|
|
|
assert_scan_token("andy", TokenKind::Identifier);
|
|
|
|
|
|
|
|
assert_scan_token("false", TokenKind::False);
|
|
|
|
|
|
|
|
assert_scan_token("fa", TokenKind::Identifier);
|
|
|
|
|
|
|
|
|
|
|
|
assert_scan_token("@", TokenKind::Error);
|
|
|
|
assert_scan_token("@", TokenKind::Error);
|
|
|
|
assert_scan_token("", TokenKind::Eof);
|
|
|
|
assert_scan_token("", TokenKind::Eof);
|
|
|
|