#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum TokenKind {
none,
identifier,
private_identifier,
_first_resword,
rw_function,
rw_for,
rw_if,
rw_in,
rw_var,
rw_break,
rw_continue,
rw_return,
rw_switch,
rw_this,
rw_true,
rw_false,
rw_null,
rw_case,
rw_catch,
rw_const,
rw_debugger,
rw_default,
rw_delete,
rw_do,
rw_else,
rw_finally,
rw_instanceof,
rw_new,
rw_throw,
rw_try,
rw_typeof,
rw_void,
rw_while,
rw_with,
rw_export,
rw_import,
rw_class,
rw_static,
rw_extends,
rw_super,
rw_enum,
rw_implements,
rw_interface,
rw_package,
rw_private,
rw_protected,
rw_public,
rw_yield,
_last_resword,
l_brace,
l_bracepipe,
r_brace,
piper_brace,
l_paren,
r_paren,
l_square,
r_square,
period,
questiondot,
dotdotdot,
semi,
comma,
plusplus,
minusminus,
_first_binary,
starstar,
star,
percent,
slash,
plus,
minus,
lessless,
greatergreater,
greatergreatergreater,
less,
greater,
lessequal,
greaterequal,
equalequal,
exclaimequal,
equalequalequal,
exclaimequalequal,
amp,
caret,
pipe,
ampamp,
pipepipe,
questionquestion,
_last_binary,
exclaim,
tilde,
question,
colon,
equal,
plusequal,
minusequal,
starequal,
starstarequal,
percentequal,
slashequal,
lesslessequal,
greatergreaterequal,
greatergreatergreaterequal,
ampequal,
pipeequal,
ampampequal,
pipepipeequal,
questionquestionequal,
caretequal,
equalgreater,
at,
as_operator,
numeric_literal,
string_literal,
regexp_literal,
jsx_text,
bigint_literal,
no_substitution_template,
template_head,
template_middle,
template_tail,
eof,
_last_token,
}
pub const NUM_JS_TOKENS: usize = TokenKind::_last_token as usize + 1;
const TOKEN_NAMES: [&str; NUM_JS_TOKENS] = [
"<none>",
"identifier",
"private identifier",
"<_first_resword>",
"function",
"for",
"if",
"in",
"var",
"break",
"continue",
"return",
"switch",
"this",
"true",
"false",
"null",
"case",
"catch",
"const",
"debugger",
"default",
"delete",
"do",
"else",
"finally",
"instanceof",
"new",
"throw",
"try",
"typeof",
"void",
"while",
"with",
"export",
"import",
"class",
"static",
"extends",
"super",
"enum",
"implements",
"interface",
"package",
"private",
"protected",
"public",
"yield",
"<_last_resword>",
"{",
"{|",
"}",
"|}",
"(",
")",
"[",
"]",
".",
"?.",
"...",
";",
",",
"++",
"--",
"<_first_binary>",
"**",
"*",
"%",
"/",
"+",
"-",
"<<",
">>",
">>>",
"<",
">",
"<=",
">=",
"==",
"!=",
"===",
"!==",
"&",
"^",
"|",
"&&",
"||",
"??",
"<_last_binary>",
"!",
"~",
"?",
":",
"=",
"+=",
"-=",
"*=",
"**=",
"%=",
"/=",
"<<=",
">>=",
">>>=",
"&=",
"|=",
"&&=",
"||=",
"??=",
"^=",
"=>",
"@",
"as",
"number",
"string",
"regexp",
"JSX text",
"bigint",
"template literal",
"template literal start",
"template literal resume",
"template literal end",
"<eof>",
"<_last_token>",
];
const TOKEN_VARIANT_NAMES: [&str; NUM_JS_TOKENS] = [
"none",
"identifier",
"private_identifier",
"_first_resword",
"rw_function",
"rw_for",
"rw_if",
"rw_in",
"rw_var",
"rw_break",
"rw_continue",
"rw_return",
"rw_switch",
"rw_this",
"rw_true",
"rw_false",
"rw_null",
"rw_case",
"rw_catch",
"rw_const",
"rw_debugger",
"rw_default",
"rw_delete",
"rw_do",
"rw_else",
"rw_finally",
"rw_instanceof",
"rw_new",
"rw_throw",
"rw_try",
"rw_typeof",
"rw_void",
"rw_while",
"rw_with",
"rw_export",
"rw_import",
"rw_class",
"rw_static",
"rw_extends",
"rw_super",
"rw_enum",
"rw_implements",
"rw_interface",
"rw_package",
"rw_private",
"rw_protected",
"rw_public",
"rw_yield",
"_last_resword",
"l_brace",
"l_bracepipe",
"r_brace",
"piper_brace",
"l_paren",
"r_paren",
"l_square",
"r_square",
"period",
"questiondot",
"dotdotdot",
"semi",
"comma",
"plusplus",
"minusminus",
"_first_binary",
"starstar",
"star",
"percent",
"slash",
"plus",
"minus",
"lessless",
"greatergreater",
"greatergreatergreater",
"less",
"greater",
"lessequal",
"greaterequal",
"equalequal",
"exclaimequal",
"equalequalequal",
"exclaimequalequal",
"amp",
"caret",
"pipe",
"ampamp",
"pipepipe",
"questionquestion",
"_last_binary",
"exclaim",
"tilde",
"question",
"colon",
"equal",
"plusequal",
"minusequal",
"starequal",
"starstarequal",
"percentequal",
"slashequal",
"lesslessequal",
"greatergreaterequal",
"greatergreatergreaterequal",
"ampequal",
"pipeequal",
"ampampequal",
"pipepipeequal",
"questionquestionequal",
"caretequal",
"equalgreater",
"at",
"as_operator",
"numeric_literal",
"string_literal",
"regexp_literal",
"jsx_text",
"bigint_literal",
"no_substitution_template",
"template_head",
"template_middle",
"template_tail",
"eof",
"_last_token",
];
#[inline]
pub fn variant_name(kind: TokenKind) -> &'static str {
TOKEN_VARIANT_NAMES[kind as usize]
}
const TOKEN_PREC: [u8; NUM_JS_TOKENS] = [
0,
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
12, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8,
0, 0, 0, 0, 0,
0, 0, 0, 0,
0,
0,
];
#[inline]
pub const fn ord(kind: TokenKind) -> i32 {
kind as u16 as i32
}
#[inline]
pub fn token_kind_str(kind: TokenKind) -> &'static str {
TOKEN_NAMES[kind as usize]
}
#[inline]
pub fn token_kind_str_by_ord(ord: i32) -> &'static str {
TOKEN_NAMES[ord as usize]
}
#[inline]
pub fn binop_precedence(kind: TokenKind) -> Option<u8> {
if kind.in_binary_range() {
Some(TOKEN_PREC[kind as usize])
} else {
None
}
}
impl TokenKind {
#[inline]
pub fn is_res_word(self) -> bool {
(self as u16) > (TokenKind::_first_resword as u16)
&& (self as u16) < (TokenKind::_last_resword as u16)
}
#[inline]
fn in_binary_range(self) -> bool {
(self as u16) > (TokenKind::_first_binary as u16)
&& (self as u16) < (TokenKind::_last_binary as u16)
}
#[inline]
pub fn is_punctuator(self) -> bool {
let v = self as u16;
v >= (TokenKind::l_brace as u16)
&& v <= (TokenKind::at as u16)
&& v != (TokenKind::_first_binary as u16)
&& v != (TokenKind::_last_binary as u16)
}
}
pub fn match_reserved_word(bytes: &[u8]) -> TokenKind {
match bytes {
b"function" => TokenKind::rw_function,
b"for" => TokenKind::rw_for,
b"if" => TokenKind::rw_if,
b"in" => TokenKind::rw_in,
b"var" => TokenKind::rw_var,
b"break" => TokenKind::rw_break,
b"continue" => TokenKind::rw_continue,
b"return" => TokenKind::rw_return,
b"switch" => TokenKind::rw_switch,
b"this" => TokenKind::rw_this,
b"true" => TokenKind::rw_true,
b"false" => TokenKind::rw_false,
b"null" => TokenKind::rw_null,
b"case" => TokenKind::rw_case,
b"catch" => TokenKind::rw_catch,
b"const" => TokenKind::rw_const,
b"debugger" => TokenKind::rw_debugger,
b"default" => TokenKind::rw_default,
b"delete" => TokenKind::rw_delete,
b"do" => TokenKind::rw_do,
b"else" => TokenKind::rw_else,
b"finally" => TokenKind::rw_finally,
b"instanceof" => TokenKind::rw_instanceof,
b"new" => TokenKind::rw_new,
b"throw" => TokenKind::rw_throw,
b"try" => TokenKind::rw_try,
b"typeof" => TokenKind::rw_typeof,
b"void" => TokenKind::rw_void,
b"while" => TokenKind::rw_while,
b"with" => TokenKind::rw_with,
b"export" => TokenKind::rw_export,
b"import" => TokenKind::rw_import,
b"class" => TokenKind::rw_class,
b"static" => TokenKind::rw_static,
b"extends" => TokenKind::rw_extends,
b"super" => TokenKind::rw_super,
b"enum" => TokenKind::rw_enum,
b"implements" => TokenKind::rw_implements,
b"interface" => TokenKind::rw_interface,
b"package" => TokenKind::rw_package,
b"private" => TokenKind::rw_private,
b"protected" => TokenKind::rw_protected,
b"public" => TokenKind::rw_public,
b"yield" => TokenKind::rw_yield,
_ => TokenKind::identifier,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ordinals_and_count() {
assert_eq!(TokenKind::none as u16, 0);
assert_eq!(TokenKind::identifier as u16, 1);
assert_eq!(TokenKind::private_identifier as u16, 2);
assert_eq!(TokenKind::_last_token as u16, 122);
assert_eq!(NUM_JS_TOKENS, 123);
assert_eq!(ord(TokenKind::eof), TokenKind::eof as u16 as i32);
}
#[test]
fn resword_range() {
assert!(TokenKind::rw_function.is_res_word());
assert!(TokenKind::rw_yield.is_res_word());
assert!(!TokenKind::identifier.is_res_word());
assert!(!TokenKind::l_brace.is_res_word());
assert!(!TokenKind::_first_resword.is_res_word());
assert!(!TokenKind::_last_resword.is_res_word());
}
#[test]
fn names_match_def() {
assert_eq!(token_kind_str(TokenKind::none), "<none>");
assert_eq!(token_kind_str(TokenKind::identifier), "identifier");
assert_eq!(token_kind_str(TokenKind::private_identifier), "private identifier");
assert_eq!(token_kind_str(TokenKind::rw_function), "function");
assert_eq!(token_kind_str(TokenKind::l_brace), "{");
assert_eq!(token_kind_str(TokenKind::starstar), "**");
assert_eq!(token_kind_str(TokenKind::as_operator), "as");
assert_eq!(token_kind_str(TokenKind::eof), "<eof>");
assert_eq!(token_kind_str(TokenKind::_first_resword), "<_first_resword>");
}
#[test]
fn token_kind_str_by_ord_keywords() {
assert_eq!(token_kind_str_by_ord(ord(TokenKind::rw_function)), "function");
assert_eq!(token_kind_str_by_ord(ord(TokenKind::rw_yield)), "yield");
assert_eq!(
token_kind_str_by_ord(ord(TokenKind::identifier)),
"identifier"
);
}
#[test]
fn variant_names_match_def() {
assert_eq!(variant_name(TokenKind::none), "none");
assert_eq!(variant_name(TokenKind::l_brace), "l_brace");
assert_eq!(variant_name(TokenKind::starstar), "starstar");
assert_eq!(variant_name(TokenKind::rw_function), "rw_function");
assert_eq!(variant_name(TokenKind::questionquestionequal), "questionquestionequal");
assert_eq!(variant_name(TokenKind::eof), "eof");
assert_eq!(variant_name(TokenKind::_last_token), "_last_token");
}
#[test]
fn binop_precedence_table() {
assert_eq!(binop_precedence(TokenKind::starstar), Some(12));
assert_eq!(binop_precedence(TokenKind::star), Some(11));
assert_eq!(binop_precedence(TokenKind::plus), Some(10));
assert_eq!(binop_precedence(TokenKind::lessless), Some(9));
assert_eq!(binop_precedence(TokenKind::less), Some(8));
assert_eq!(binop_precedence(TokenKind::equalequal), Some(7));
assert_eq!(binop_precedence(TokenKind::amp), Some(6));
assert_eq!(binop_precedence(TokenKind::caret), Some(5));
assert_eq!(binop_precedence(TokenKind::pipe), Some(4));
assert_eq!(binop_precedence(TokenKind::ampamp), Some(3));
assert_eq!(binop_precedence(TokenKind::pipepipe), Some(2));
assert_eq!(binop_precedence(TokenKind::questionquestion), Some(1));
assert_eq!(binop_precedence(TokenKind::l_brace), None);
assert_eq!(binop_precedence(TokenKind::eof), None);
assert_eq!(binop_precedence(TokenKind::_first_binary), None);
assert_eq!(binop_precedence(TokenKind::_last_binary), None);
assert_eq!(binop_precedence(TokenKind::as_operator), None);
}
#[test]
fn punctuator_predicate() {
assert!(TokenKind::l_brace.is_punctuator());
assert!(TokenKind::starstar.is_punctuator());
assert!(TokenKind::at.is_punctuator());
assert!(!TokenKind::identifier.is_punctuator());
assert!(!TokenKind::rw_function.is_punctuator());
assert!(!TokenKind::numeric_literal.is_punctuator());
assert!(!TokenKind::as_operator.is_punctuator());
assert!(!TokenKind::_first_binary.is_punctuator());
assert!(!TokenKind::_last_binary.is_punctuator());
assert!(TokenKind::l_bracepipe.is_punctuator());
assert!(TokenKind::piper_brace.is_punctuator());
}
#[test]
fn reserved_words() {
assert_eq!(match_reserved_word(b"function"), TokenKind::rw_function);
assert_eq!(match_reserved_word(b"yield"), TokenKind::rw_yield);
assert_eq!(match_reserved_word(b"static"), TokenKind::rw_static);
assert_eq!(match_reserved_word(b"extends"), TokenKind::rw_extends);
assert_eq!(match_reserved_word(b"fora"), TokenKind::identifier);
assert_eq!(match_reserved_word(b"Function"), TokenKind::identifier);
assert_eq!(match_reserved_word(b""), TokenKind::identifier);
assert_eq!(match_reserved_word(b"let"), TokenKind::identifier);
}
}