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