3 // The assignment of fine-grained, information-carrying type objects
4 // allows the tokenizer to store the information it has about a
5 // token in a way that is very cheap for the parser to look up.
7 // All token type variables start with an underscore, to make them
10 // The `beforeExpr` property is used to disambiguate between regular
11 // expressions and divisions. It is set on all token types that can
12 // be followed by an expression (thus, a slash after them would be a
13 // regular expression).
15 // The `startsExpr` property is used to check if the token ends a
16 // `yield` expression. It is set on all token types that either can
17 // directly start an expression (like a quotation mark) or can
18 // continue an expression (like the body of a string).
20 // `isLoop` marks a keyword as starting a loop, which is important
21 // to know when parsing a label, in order to allow or disallow
22 // continue jumps to that label.
24 export class TokenType {
25 constructor(label, conf = {}) {
27 this.keyword = conf.keyword
28 this.beforeExpr = !!conf.beforeExpr
29 this.startsExpr = !!conf.startsExpr
30 this.isLoop = !!conf.isLoop
31 this.isAssign = !!conf.isAssign
32 this.prefix = !!conf.prefix
33 this.postfix = !!conf.postfix
34 this.binop = conf.binop || null
35 this.updateContext = null
39 function binop(name, prec) {
40 return new TokenType(name, {beforeExpr: true, binop: prec})
42 const beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}
44 // Map keyword names to token types.
46 export const keywords = {}
48 // Succinct definitions of keyword token types
49 function kw(name, options = {}) {
50 options.keyword = name
51 return keywords[name] = new TokenType(name, options)
54 export const types = {
55 num: new TokenType("num", startsExpr),
56 regexp: new TokenType("regexp", startsExpr),
57 string: new TokenType("string", startsExpr),
58 name: new TokenType("name", startsExpr),
59 privateId: new TokenType("privateId", startsExpr),
60 eof: new TokenType("eof"),
62 // Punctuation token types.
63 bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
64 bracketR: new TokenType("]"),
65 braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
66 braceR: new TokenType("}"),
67 parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
68 parenR: new TokenType(")"),
69 comma: new TokenType(",", beforeExpr),
70 semi: new TokenType(";", beforeExpr),
71 colon: new TokenType(":", beforeExpr),
72 dot: new TokenType("."),
73 hash: new TokenType("#"), // Nick
74 question: new TokenType("?", beforeExpr),
75 questionDot: new TokenType("?."),
76 arrow: new TokenType("=>", beforeExpr),
77 template: new TokenType("template"),
78 invalidTemplate: new TokenType("invalidTemplate"),
79 ellipsis: new TokenType("...", beforeExpr),
80 backQuote: new TokenType("`", startsExpr),
81 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
83 // Operators. These carry several kinds of properties to help the
84 // parser use them properly (the presence of these properties is
85 // what categorizes them as operators).
87 // `binop`, when present, specifies that this operator is a binary
88 // operator, and will refer to its precedence.
90 // `prefix` and `postfix` mark the operator as a prefix or postfix
93 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
94 // binary operators with a very low precedence, that should result
95 // in AssignmentExpression nodes.
97 eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
98 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
99 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
100 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
101 logicalOR: binop("||", 1),
102 logicalAND: binop("&&", 2),
103 bitwiseOR: binop("|", 3),
104 bitwiseXOR: binop("^", 4),
105 bitwiseAND: binop("&", 5),
106 equality: binop("==/!=/===/!==", 6),
107 relational: binop("</>/<=/>=", 7),
108 bitShift: binop("<</>>/>>>", 8),
109 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
110 modulo: binop("%", 10),
111 star: binop("*", 10),
112 slash: binop("/", 10),
113 starstar: new TokenType("**", {beforeExpr: true}),
114 coalesce: binop("??", 1),
116 // Keyword token types.
118 _case: kw("case", beforeExpr),
120 _continue: kw("continue"),
121 _debugger: kw("debugger"),
122 _default: kw("default", beforeExpr),
123 _do: kw("do", {isLoop: true, beforeExpr: true}),
124 _else: kw("else", beforeExpr),
125 _finally: kw("finally"),
126 _for: kw("for", {isLoop: true}),
127 _function: kw("function", startsExpr),
129 _return: kw("return", beforeExpr),
130 _switch: kw("switch"),
131 _throw: kw("throw", beforeExpr),
135 _while: kw("while", {isLoop: true}),
137 _new: kw("new", {beforeExpr: true, startsExpr: true}),
138 _this: kw("this", startsExpr),
139 _super: kw("super", startsExpr),
140 _class: kw("class", startsExpr),
141 _extends: kw("extends", beforeExpr),
142 _export: kw("export"),
143 _import: kw("import", startsExpr),
144 _null: kw("null", startsExpr),
145 _true: kw("true", startsExpr),
146 _false: kw("false", startsExpr),
147 _in: kw("in", {beforeExpr: true, binop: 7}),
148 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
149 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
150 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
151 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})