Reorganize token types and use a map for them (#9645)

This commit is contained in:
Daniel Tschinder 2019-03-06 14:30:04 -08:00 committed by GitHub
parent e53be4b387
commit d8a5329834
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 108 deletions

View File

@ -14,6 +14,8 @@ import { isNewLine } from "../../util/whitespace";
const HEX_NUMBER = /^[\da-fA-F]+$/; const HEX_NUMBER = /^[\da-fA-F]+$/;
const DECIMAL_NUMBER = /^\d+$/; const DECIMAL_NUMBER = /^\d+$/;
// Be aware that this file is always executed and not only when the plugin is enabled.
// Therefore this contexts and tokens do always exist.
tc.j_oTag = new TokContext("<tag", false); tc.j_oTag = new TokContext("<tag", false);
tc.j_cTag = new TokContext("</tag", false); tc.j_cTag = new TokContext("</tag", false);
tc.j_expr = new TokContext("<tag>...</tag>", true, true); tc.j_expr = new TokContext("<tag>...</tag>", true, true);

View File

@ -1329,7 +1329,7 @@ export default class Tokenizer extends LocationParser {
readWord(): void { readWord(): void {
const word = this.readWord1(); const word = this.readWord1();
const type = keywordTypes[word] || tt.name; const type = keywordTypes.get(word) || tt.name;
if (type.keyword && this.state.containsEsc) { if (type.keyword && this.state.containsEsc) {
this.raise(this.state.pos, `Escape sequence in keyword ${word}`); this.raise(this.state.pos, `Escape sequence in keyword ${word}`);

View File

@ -32,7 +32,6 @@ const postfix = true;
type TokenOptions = { type TokenOptions = {
keyword?: string, keyword?: string,
beforeExpr?: boolean, beforeExpr?: boolean,
startsExpr?: boolean, startsExpr?: boolean,
rightAssociative?: boolean, rightAssociative?: boolean,
@ -66,16 +65,21 @@ export class TokenType {
this.isAssign = !!conf.isAssign; this.isAssign = !!conf.isAssign;
this.prefix = !!conf.prefix; this.prefix = !!conf.prefix;
this.postfix = !!conf.postfix; this.postfix = !!conf.postfix;
this.binop = conf.binop === 0 ? 0 : conf.binop || null; this.binop = conf.binop != null ? conf.binop : null;
this.updateContext = null; this.updateContext = null;
} }
} }
function KeywordTokenType(keyword: string, options: TokenOptions = {}) { export const keywords = new Map<string, TokenType>();
return new TokenType(keyword, { ...options, keyword });
function createKeyword(name: string, options: TokenOptions = {}): TokenType {
options.keyword = name;
const token = new TokenType(name, options);
keywords.set(name, token);
return token;
} }
function BinopTokenType(name: string, binop: number) { function createBinop(name: string, binop: number) {
return new TokenType(name, { beforeExpr, binop }); return new TokenType(name, { beforeExpr, binop });
} }
@ -133,74 +137,60 @@ export const types: { [name: string]: TokenType } = {
incDec: new TokenType("++/--", { prefix, postfix, startsExpr }), incDec: new TokenType("++/--", { prefix, postfix, startsExpr }),
bang: new TokenType("!", { beforeExpr, prefix, startsExpr }), bang: new TokenType("!", { beforeExpr, prefix, startsExpr }),
tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }), tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }),
pipeline: BinopTokenType("|>", 0), pipeline: createBinop("|>", 0),
nullishCoalescing: BinopTokenType("??", 1), nullishCoalescing: createBinop("??", 1),
logicalOR: BinopTokenType("||", 1), logicalOR: createBinop("||", 1),
logicalAND: BinopTokenType("&&", 2), logicalAND: createBinop("&&", 2),
bitwiseOR: BinopTokenType("|", 3), bitwiseOR: createBinop("|", 3),
bitwiseXOR: BinopTokenType("^", 4), bitwiseXOR: createBinop("^", 4),
bitwiseAND: BinopTokenType("&", 5), bitwiseAND: createBinop("&", 5),
equality: BinopTokenType("==/!=", 6), equality: createBinop("==/!=", 6),
relational: BinopTokenType("</>", 7), relational: createBinop("</>", 7),
bitShift: BinopTokenType("<</>>", 8), bitShift: createBinop("<</>>", 8),
plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }), plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
modulo: BinopTokenType("%", 10), modulo: createBinop("%", 10),
star: BinopTokenType("*", 10), star: createBinop("*", 10),
slash: BinopTokenType("/", 10), slash: createBinop("/", 10),
exponent: new TokenType("**", { exponent: new TokenType("**", {
beforeExpr, beforeExpr,
binop: 11, binop: 11,
rightAssociative: true, rightAssociative: true,
}), }),
// Keywords
_break: createKeyword("break"),
_case: createKeyword("case", { beforeExpr }),
_catch: createKeyword("catch"),
_continue: createKeyword("continue"),
_debugger: createKeyword("debugger"),
_default: createKeyword("default", { beforeExpr }),
_do: createKeyword("do", { isLoop, beforeExpr }),
_else: createKeyword("else", { beforeExpr }),
_finally: createKeyword("finally"),
_for: createKeyword("for", { isLoop }),
_function: createKeyword("function", { startsExpr }),
_if: createKeyword("if"),
_return: createKeyword("return", { beforeExpr }),
_switch: createKeyword("switch"),
_throw: createKeyword("throw", { beforeExpr, prefix, startsExpr }),
_try: createKeyword("try"),
_var: createKeyword("var"),
_const: createKeyword("const"),
_while: createKeyword("while", { isLoop }),
_with: createKeyword("with"),
_new: createKeyword("new", { beforeExpr, startsExpr }),
_this: createKeyword("this", { startsExpr }),
_super: createKeyword("super", { startsExpr }),
_class: createKeyword("class", { startsExpr }),
_extends: createKeyword("extends", { beforeExpr }),
_export: createKeyword("export"),
_import: createKeyword("import", { startsExpr }),
_null: createKeyword("null", { startsExpr }),
_true: createKeyword("true", { startsExpr }),
_false: createKeyword("false", { startsExpr }),
_in: createKeyword("in", { beforeExpr, binop: 7 }),
_instanceof: createKeyword("instanceof", { beforeExpr, binop: 7 }),
_typeof: createKeyword("typeof", { beforeExpr, prefix, startsExpr }),
_void: createKeyword("void", { beforeExpr, prefix, startsExpr }),
_delete: createKeyword("delete", { beforeExpr, prefix, startsExpr }),
}; };
function makeKeywordProps(
name: string,
conf: any,
): PropertyDescriptor<TokenType> {
return { value: KeywordTokenType(name, conf), enumerable: true };
}
// $FlowIssue
export const keywords = Object.create(null, {
break: makeKeywordProps("break"),
case: makeKeywordProps("case", { beforeExpr }),
catch: makeKeywordProps("catch"),
continue: makeKeywordProps("continue"),
debugger: makeKeywordProps("debugger"),
default: makeKeywordProps("default", { beforeExpr }),
do: makeKeywordProps("do", { isLoop, beforeExpr }),
else: makeKeywordProps("else", { beforeExpr }),
finally: makeKeywordProps("finally"),
for: makeKeywordProps("for", { isLoop }),
function: makeKeywordProps("function", { startsExpr }),
if: makeKeywordProps("if"),
return: makeKeywordProps("return", { beforeExpr }),
switch: makeKeywordProps("switch"),
throw: makeKeywordProps("throw", { beforeExpr, prefix, startsExpr }),
try: makeKeywordProps("try"),
var: makeKeywordProps("var"),
const: makeKeywordProps("const"),
while: makeKeywordProps("while", { isLoop }),
with: makeKeywordProps("with"),
new: makeKeywordProps("new", { beforeExpr, startsExpr }),
this: makeKeywordProps("this", { startsExpr }),
super: makeKeywordProps("super", { startsExpr }),
class: makeKeywordProps("class", { startsExpr }),
extends: makeKeywordProps("extends", { beforeExpr }),
export: makeKeywordProps("export"),
import: makeKeywordProps("import", { startsExpr }),
null: makeKeywordProps("null", { startsExpr }),
true: makeKeywordProps("true", { startsExpr }),
false: makeKeywordProps("false", { startsExpr }),
in: makeKeywordProps("in", { beforeExpr, binop: 7 }),
instanceof: makeKeywordProps("instanceof", { beforeExpr, binop: 7 }),
typeof: makeKeywordProps("typeof", { beforeExpr, prefix, startsExpr }),
void: makeKeywordProps("void", { beforeExpr, prefix, startsExpr }),
delete: makeKeywordProps("delete", { beforeExpr, prefix, startsExpr }),
});
// Map keyword names to token types.
Object.keys(keywords).forEach(name => {
types["_" + name] = keywords[name];
});

View File

@ -3,6 +3,7 @@
// @flow // @flow
import * as charCodes from "charcodes"; import * as charCodes from "charcodes";
import { keywords } from "../tokenizer/types";
const reservedWords = { const reservedWords = {
strict: [ strict: [
@ -52,44 +53,6 @@ export function isStrictBindReservedWord(
return isReservedWord(word, inModule) || reservedWordsStrictBindSet.has(word); return isReservedWord(word, inModule) || reservedWordsStrictBindSet.has(word);
} }
const keywords = new Set([
"break",
"case",
"catch",
"continue",
"debugger",
"default",
"do",
"else",
"finally",
"for",
"function",
"if",
"return",
"switch",
"throw",
"try",
"var",
"while",
"with",
"null",
"true",
"false",
"instanceof",
"typeof",
"void",
"delete",
"new",
"in",
"this",
"const",
"class",
"extends",
"export",
"import",
"super",
]);
export function isKeyword(word: string): boolean { export function isKeyword(word: string): boolean {
return keywords.has(word); return keywords.has(word);
} }