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