1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef frontend_TokenKind_h
8 #define frontend_TokenKind_h
9
10 #include <stdint.h>
11
12 /*
13 * List of token kinds and their ranges.
14 *
15 * The format for each line is:
16 *
17 * MACRO(<TOKEN_KIND_NAME>, <DESCRIPTION>)
18 *
19 * or
20 *
21 * RANGE(<TOKEN_RANGE_NAME>, <TOKEN_KIND_NAME>)
22 *
23 * where ;
24 * <TOKEN_KIND_NAME> is a legal C identifier of the token, that will be used in
25 * the JS engine source.
26 *
27 * <DESCRIPTION> is a string that describe about the token, and will be used in
28 * error message.
29 *
30 * <TOKEN_RANGE_NAME> is a legal C identifier of the range that will be used to
31 * JS engine source. It should end with `First` or `Last`. This is used to check
32 * TokenKind by range-testing:
33 * BinOpFirst <= tt && tt <= BinOpLast
34 *
35 * Second argument of `RANGE` is the actual value of the <TOKEN_RANGE_NAME>,
36 * should be same as one of <TOKEN_KIND_NAME> in other `MACRO`s.
37 *
38 * To use this macro, define two macros for `MACRO` and `RANGE`, and pass them
39 * as arguments.
40 *
41 * #define EMIT_TOKEN(name, desc) ...
42 * #define EMIT_RANGE(name, value) ...
43 * FOR_EACH_TOKEN_KIND_WITH_RANGE(EMIT_TOKEN, EMIT_RANGE)
44 * #undef EMIT_TOKEN
45 * #undef EMIT_RANGE
46 *
47 * If you don't need range data, use FOR_EACH_TOKEN_KIND instead.
48 *
49 * #define EMIT_TOKEN(name, desc) ...
50 * FOR_EACH_TOKEN_KIND(EMIT_TOKEN)
51 * #undef EMIT_TOKEN
52 *
53 * Note that this list does not contain ERROR and LIMIT.
54 */
55 #define FOR_EACH_TOKEN_KIND_WITH_RANGE(MACRO, RANGE) \
56 MACRO(Eof, "end of script") \
57 \
58 /* only returned by peekTokenSameLine() */ \
59 MACRO(Eol, "line terminator") \
60 \
61 MACRO(Semi, "';'") \
62 MACRO(Comma, "','") \
63 MACRO(Hook, "'?'") /* conditional */ \
64 MACRO(Colon, "':'") /* conditional */ \
65 MACRO(Inc, "'++'") /* increment */ \
66 MACRO(Dec, "'--'") /* decrement */ \
67 MACRO(Dot, "'.'") /* member operator */ \
68 MACRO(TripleDot, "'...'") /* rest arguments and spread operator */ \
69 MACRO(OptionalChain, "'?.'") \
70 MACRO(LeftBracket, "'['") \
71 MACRO(RightBracket, "']'") \
72 MACRO(LeftCurly, "'{'") \
73 MACRO(RightCurly, "'}'") \
74 MACRO(LeftParen, "'('") \
75 MACRO(RightParen, "')'") \
76 MACRO(Name, "identifier") \
77 MACRO(PrivateName, "private identifier") \
78 MACRO(Number, "numeric literal") \
79 MACRO(String, "string literal") \
80 MACRO(BigInt, "bigint literal") \
81 \
82 /* start of template literal with substitutions */ \
83 MACRO(TemplateHead, "'${'") \
84 /* template literal without substitutions */ \
85 MACRO(NoSubsTemplate, "template literal") \
86 \
87 MACRO(RegExp, "regular expression literal") \
88 MACRO(True, "boolean literal 'true'") \
89 RANGE(ReservedWordLiteralFirst, True) \
90 MACRO(False, "boolean literal 'false'") \
91 MACRO(Null, "null literal") \
92 RANGE(ReservedWordLiteralLast, Null) \
93 MACRO(This, "keyword 'this'") \
94 RANGE(KeywordFirst, This) \
95 MACRO(Function, "keyword 'function'") \
96 MACRO(If, "keyword 'if'") \
97 MACRO(Else, "keyword 'else'") \
98 MACRO(Switch, "keyword 'switch'") \
99 MACRO(Case, "keyword 'case'") \
100 MACRO(Default, "keyword 'default'") \
101 MACRO(While, "keyword 'while'") \
102 MACRO(Do, "keyword 'do'") \
103 MACRO(For, "keyword 'for'") \
104 MACRO(Break, "keyword 'break'") \
105 MACRO(Continue, "keyword 'continue'") \
106 MACRO(Var, "keyword 'var'") \
107 MACRO(Const, "keyword 'const'") \
108 MACRO(With, "keyword 'with'") \
109 MACRO(Return, "keyword 'return'") \
110 MACRO(New, "keyword 'new'") \
111 MACRO(Delete, "keyword 'delete'") \
112 MACRO(Try, "keyword 'try'") \
113 MACRO(Catch, "keyword 'catch'") \
114 MACRO(Finally, "keyword 'finally'") \
115 MACRO(Throw, "keyword 'throw'") \
116 MACRO(Debugger, "keyword 'debugger'") \
117 MACRO(Export, "keyword 'export'") \
118 MACRO(Import, "keyword 'import'") \
119 MACRO(Class, "keyword 'class'") \
120 MACRO(Extends, "keyword 'extends'") \
121 MACRO(Super, "keyword 'super'") \
122 RANGE(KeywordLast, Super) \
123 \
124 /* contextual keywords */ \
125 MACRO(As, "'as'") \
126 RANGE(ContextualKeywordFirst, As) \
127 MACRO(Async, "'async'") \
128 MACRO(Await, "'await'") \
129 MACRO(Each, "'each'") \
130 MACRO(From, "'from'") \
131 MACRO(Get, "'get'") \
132 MACRO(Let, "'let'") \
133 MACRO(Meta, "'meta'") \
134 MACRO(Of, "'of'") \
135 MACRO(Set, "'set'") \
136 MACRO(Static, "'static'") \
137 MACRO(Target, "'target'") \
138 MACRO(Yield, "'yield'") \
139 RANGE(ContextualKeywordLast, Yield) \
140 \
141 /* future reserved words */ \
142 MACRO(Enum, "reserved word 'enum'") \
143 RANGE(FutureReservedKeywordFirst, Enum) \
144 RANGE(FutureReservedKeywordLast, Enum) \
145 \
146 /* reserved words in strict mode */ \
147 MACRO(Implements, "reserved word 'implements'") \
148 RANGE(StrictReservedKeywordFirst, Implements) \
149 MACRO(Interface, "reserved word 'interface'") \
150 MACRO(Package, "reserved word 'package'") \
151 MACRO(Private, "reserved word 'private'") \
152 MACRO(Protected, "reserved word 'protected'") \
153 MACRO(Public, "reserved word 'public'") \
154 RANGE(StrictReservedKeywordLast, Public) \
155 \
156 /* \
157 * The following token types occupy contiguous ranges to enable easy \
158 * range-testing. \
159 */ \
160 /* \
161 * Binary operators. \
162 * This list must be kept in the same order in several places: \
163 * - the binary operators in ParseNode.h \
164 * - the precedence list in Parser.cpp \
165 * - the JSOp code list in BytecodeEmitter.cpp \
166 */ \
167 MACRO(Pipeline, "'|>'") \
168 RANGE(BinOpFirst, Pipeline) \
169 MACRO(Coalesce, "'\?\?'") /* escapes to avoid trigraphs warning */ \
170 MACRO(Or, "'||'") /* logical or */ \
171 MACRO(And, "'&&'") /* logical and */ \
172 MACRO(BitOr, "'|'") /* bitwise-or */ \
173 MACRO(BitXor, "'^'") /* bitwise-xor */ \
174 MACRO(BitAnd, "'&'") /* bitwise-and */ \
175 \
176 /* Equality operation tokens, per TokenKindIsEquality. */ \
177 MACRO(StrictEq, "'==='") \
178 RANGE(EqualityStart, StrictEq) \
179 MACRO(Eq, "'=='") \
180 MACRO(StrictNe, "'!=='") \
181 MACRO(Ne, "'!='") \
182 RANGE(EqualityLast, Ne) \
183 \
184 /* Relational ops, per TokenKindIsRelational. */ \
185 MACRO(Lt, "'<'") \
186 RANGE(RelOpStart, Lt) \
187 MACRO(Le, "'<='") \
188 MACRO(Gt, "'>'") \
189 MACRO(Ge, "'>='") \
190 RANGE(RelOpLast, Ge) \
191 \
192 MACRO(InstanceOf, "keyword 'instanceof'") \
193 RANGE(KeywordBinOpFirst, InstanceOf) \
194 MACRO(In, "keyword 'in'") \
195 RANGE(KeywordBinOpLast, In) \
196 \
197 /* Shift ops, per TokenKindIsShift. */ \
198 MACRO(Lsh, "'<<'") \
199 RANGE(ShiftOpStart, Lsh) \
200 MACRO(Rsh, "'>>'") \
201 MACRO(Ursh, "'>>>'") \
202 RANGE(ShiftOpLast, Ursh) \
203 \
204 MACRO(Add, "'+'") \
205 MACRO(Sub, "'-'") \
206 MACRO(Mul, "'*'") \
207 MACRO(Div, "'/'") \
208 MACRO(Mod, "'%'") \
209 MACRO(Pow, "'**'") \
210 RANGE(BinOpLast, Pow) \
211 \
212 /* Unary operation tokens. */ \
213 MACRO(TypeOf, "keyword 'typeof'") \
214 RANGE(KeywordUnOpFirst, TypeOf) \
215 MACRO(Void, "keyword 'void'") \
216 RANGE(KeywordUnOpLast, Void) \
217 MACRO(Not, "'!'") \
218 MACRO(BitNot, "'~'") \
219 \
220 MACRO(Arrow, "'=>'") /* function arrow */ \
221 \
222 /* Assignment ops, per TokenKindIsAssignment */ \
223 MACRO(Assign, "'='") \
224 RANGE(AssignmentStart, Assign) \
225 MACRO(AddAssign, "'+='") \
226 MACRO(SubAssign, "'-='") \
227 MACRO(CoalesceAssign, "'\?\?='") /* avoid trigraphs warning */ \
228 MACRO(OrAssign, "'||='") \
229 MACRO(AndAssign, "'&&='") \
230 MACRO(BitOrAssign, "'|='") \
231 MACRO(BitXorAssign, "'^='") \
232 MACRO(BitAndAssign, "'&='") \
233 MACRO(LshAssign, "'<<='") \
234 MACRO(RshAssign, "'>>='") \
235 MACRO(UrshAssign, "'>>>='") \
236 MACRO(MulAssign, "'*='") \
237 MACRO(DivAssign, "'/='") \
238 MACRO(ModAssign, "'%='") \
239 MACRO(PowAssign, "'**='") \
240 RANGE(AssignmentLast, PowAssign)
241
242 #define TOKEN_KIND_RANGE_EMIT_NONE(name, value)
243 #define FOR_EACH_TOKEN_KIND(MACRO) \
244 FOR_EACH_TOKEN_KIND_WITH_RANGE(MACRO, TOKEN_KIND_RANGE_EMIT_NONE)
245
246 namespace js {
247 namespace frontend {
248
249 // Values of this type are used to index into arrays such as isExprEnding[],
250 // so the first value must be zero.
251 enum class TokenKind : uint8_t {
252 #define EMIT_ENUM(name, desc) name,
253 #define EMIT_ENUM_RANGE(name, value) name = value,
254 FOR_EACH_TOKEN_KIND_WITH_RANGE(EMIT_ENUM, EMIT_ENUM_RANGE)
255 #undef EMIT_ENUM
256 #undef EMIT_ENUM_RANGE
257 Limit // domain size
258 };
259
TokenKindIsBinaryOp(TokenKind tt)260 inline bool TokenKindIsBinaryOp(TokenKind tt) {
261 return TokenKind::BinOpFirst <= tt && tt <= TokenKind::BinOpLast;
262 }
263
TokenKindIsEquality(TokenKind tt)264 inline bool TokenKindIsEquality(TokenKind tt) {
265 return TokenKind::EqualityStart <= tt && tt <= TokenKind::EqualityLast;
266 }
267
TokenKindIsRelational(TokenKind tt)268 inline bool TokenKindIsRelational(TokenKind tt) {
269 return TokenKind::RelOpStart <= tt && tt <= TokenKind::RelOpLast;
270 }
271
TokenKindIsShift(TokenKind tt)272 inline bool TokenKindIsShift(TokenKind tt) {
273 return TokenKind::ShiftOpStart <= tt && tt <= TokenKind::ShiftOpLast;
274 }
275
TokenKindIsAssignment(TokenKind tt)276 inline bool TokenKindIsAssignment(TokenKind tt) {
277 return TokenKind::AssignmentStart <= tt && tt <= TokenKind::AssignmentLast;
278 }
279
TokenKindIsKeyword(TokenKind tt)280 inline MOZ_MUST_USE bool TokenKindIsKeyword(TokenKind tt) {
281 return (TokenKind::KeywordFirst <= tt && tt <= TokenKind::KeywordLast) ||
282 (TokenKind::KeywordBinOpFirst <= tt &&
283 tt <= TokenKind::KeywordBinOpLast) ||
284 (TokenKind::KeywordUnOpFirst <= tt &&
285 tt <= TokenKind::KeywordUnOpLast);
286 }
287
TokenKindIsContextualKeyword(TokenKind tt)288 inline MOZ_MUST_USE bool TokenKindIsContextualKeyword(TokenKind tt) {
289 return TokenKind::ContextualKeywordFirst <= tt &&
290 tt <= TokenKind::ContextualKeywordLast;
291 }
292
TokenKindIsFutureReservedWord(TokenKind tt)293 inline MOZ_MUST_USE bool TokenKindIsFutureReservedWord(TokenKind tt) {
294 return TokenKind::FutureReservedKeywordFirst <= tt &&
295 tt <= TokenKind::FutureReservedKeywordLast;
296 }
297
TokenKindIsStrictReservedWord(TokenKind tt)298 inline MOZ_MUST_USE bool TokenKindIsStrictReservedWord(TokenKind tt) {
299 return TokenKind::StrictReservedKeywordFirst <= tt &&
300 tt <= TokenKind::StrictReservedKeywordLast;
301 }
302
TokenKindIsReservedWordLiteral(TokenKind tt)303 inline MOZ_MUST_USE bool TokenKindIsReservedWordLiteral(TokenKind tt) {
304 return TokenKind::ReservedWordLiteralFirst <= tt &&
305 tt <= TokenKind::ReservedWordLiteralLast;
306 }
307
TokenKindIsReservedWord(TokenKind tt)308 inline MOZ_MUST_USE bool TokenKindIsReservedWord(TokenKind tt) {
309 return TokenKindIsKeyword(tt) || TokenKindIsFutureReservedWord(tt) ||
310 TokenKindIsReservedWordLiteral(tt);
311 }
312
TokenKindIsPossibleIdentifier(TokenKind tt)313 inline MOZ_MUST_USE bool TokenKindIsPossibleIdentifier(TokenKind tt) {
314 return tt == TokenKind::Name || tt == TokenKind::PrivateName ||
315 TokenKindIsContextualKeyword(tt) || TokenKindIsStrictReservedWord(tt);
316 }
317
TokenKindIsPossibleIdentifierName(TokenKind tt)318 inline MOZ_MUST_USE bool TokenKindIsPossibleIdentifierName(TokenKind tt) {
319 return TokenKindIsPossibleIdentifier(tt) || TokenKindIsReservedWord(tt);
320 }
321
322 } // namespace frontend
323 } // namespace js
324
325 #endif /* frontend_TokenKind_h */
326