v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
token.h
Go to the documentation of this file.
1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_PARSING_TOKEN_H_
6#define V8_PARSING_TOKEN_H_
7
9#include "src/base/bounds.h"
10#include "src/base/logging.h"
11#include "src/common/globals.h"
12
13namespace v8 {
14namespace internal {
15
16// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
17// same signature M(name, string, precedence), where name is the
18// symbolic token name, string is the corresponding syntactic symbol
19// (or nullptr, for literals), and precedence is the precedence (or 0).
20// The parameters are invoked for token categories as follows:
21//
22// T: Non-keyword tokens
23// K: Keyword tokens
24
25// IGNORE_TOKEN is a convenience macro that can be supplied as
26// an argument (at any position) for a TOKEN_LIST call. It does
27// nothing with tokens belonging to the respective category.
28
29#define IGNORE_TOKEN(name, string, precedence)
30
31/* Binary operators */
32/* kAdd and kSub are at the end since they are UnaryOp */
33#define BINARY_OP_TOKEN_LIST(T, E) \
34 E(T, Nullish, "??", 3) \
35 E(T, Or, "||", 4) \
36 E(T, And, "&&", 5) \
37 E(T, BitOr, "|", 6) \
38 E(T, BitXor, "^", 7) \
39 E(T, BitAnd, "&", 8) \
40 E(T, Shl, "<<", 11) \
41 E(T, Sar, ">>", 11) \
42 E(T, Shr, ">>>", 11) \
43 E(T, Mul, "*", 13) \
44 E(T, Div, "/", 13) \
45 E(T, Mod, "%", 13) \
46 E(T, Exp, "**", 14) \
47 E(T, Add, "+", 12) \
48 E(T, Sub, "-", 12)
49
50#define EXPAND_BINOP_ASSIGN_TOKEN(T, name, string, precedence) \
51 T(kAssign##name, string "=", 2)
52
53#define EXPAND_BINOP_TOKEN(T, name, string, precedence) \
54 T(k##name, string, precedence)
55
56#define TOKEN_LIST(T, K) \
57 \
58 /* BEGIN PropertyOrCall */ \
59 /* BEGIN Member */ \
60 /* BEGIN Template */ \
61 /* ES6 Template Literals */ \
62 T(kTemplateSpan, nullptr, 0) \
63 T(kTemplateTail, nullptr, 0) \
64 /* END Template */ \
65 \
66 /* Punctuators (ECMA-262, section 7.7, page 15). */ \
67 /* BEGIN Property */ \
68 T(kPeriod, ".", 0) \
69 T(kLeftBracket, "[", 0) \
70 /* END Property */ \
71 /* END Member */ \
72 T(kQuestionPeriod, "?.", 0) \
73 T(kLeftParen, "(", 0) \
74 /* END PropertyOrCall */ \
75 T(kRightParen, ")", 0) \
76 T(kRightBracket, "]", 0) \
77 T(kLeftBrace, "{", 0) \
78 T(kColon, ":", 0) \
79 T(kEllipsis, "...", 0) \
80 T(kConditional, "?", 3) \
81 /* BEGIN AutoSemicolon */ \
82 T(kSemicolon, ";", 0) \
83 T(kRightBrace, "}", 0) \
84 /* End of source indicator. */ \
85 T(kEos, "EOS", 0) \
86 /* END AutoSemicolon */ \
87 \
88 /* BEGIN ArrowOrAssignmentOp */ \
89 T(kArrow, "=>", 0) \
90 /* BEGIN AssignmentOp */ \
91 /* IsAssignmentOp() relies on this block of enum values being */ \
92 /* contiguous and sorted in the same order! */ \
93 T(kInit, "=init", 2) /* AST-use only. */ \
94 T(kAssign, "=", 2) \
95 BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_ASSIGN_TOKEN) \
96 /* END AssignmentOp */ \
97 /* END ArrowOrAssignmentOp */ \
98 \
99 /* Binary operators sorted by precedence. */ \
100 /* IsBinaryOp() relies on this block of enum values */ \
101 /* being contiguous and sorted in the same order! */ \
102 T(kComma, ",", 1) \
103 \
104 /* Unary operators, starting at kAdd in BINARY_OP_TOKEN_LIST */ \
105 /* IsUnaryOp() relies on this block of enum values */ \
106 /* being contiguous and sorted in the same order! */ \
107 BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_TOKEN) \
108 \
109 T(kNot, "!", 0) \
110 T(kBitNot, "~", 0) \
111 K(kDelete, "delete", 0) \
112 K(kTypeOf, "typeof", 0) \
113 K(kVoid, "void", 0) \
114 \
115 /* BEGIN IsCountOp */ \
116 T(kInc, "++", 0) \
117 T(kDec, "--", 0) \
118 /* END IsCountOp */ \
119 /* END IsUnaryOrCountOp */ \
120 \
121 /* Compare operators sorted by precedence. */ \
122 /* IsCompareOp() relies on this block of enum values */ \
123 /* being contiguous and sorted in the same order! */ \
124 T(kEq, "==", 9) \
125 T(kEqStrict, "===", 9) \
126 T(kNotEq, "!=", 9) \
127 T(kNotEqStrict, "!==", 9) \
128 T(kLessThan, "<", 10) \
129 T(kGreaterThan, ">", 10) \
130 T(kLessThanEq, "<=", 10) \
131 T(kGreaterThanEq, ">=", 10) \
132 K(kInstanceOf, "instanceof", 10) \
133 K(kIn, "in", 10) \
134 \
135 /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
136 K(kBreak, "break", 0) \
137 K(kCase, "case", 0) \
138 K(kCatch, "catch", 0) \
139 K(kContinue, "continue", 0) \
140 K(kDebugger, "debugger", 0) \
141 K(kDefault, "default", 0) \
142 /* kDelete */ \
143 K(kDo, "do", 0) \
144 K(kElse, "else", 0) \
145 K(kFinally, "finally", 0) \
146 K(kFor, "for", 0) \
147 K(kFunction, "function", 0) \
148 K(kIf, "if", 0) \
149 /* kIn */ \
150 /* kInstanceOf */ \
151 K(kNew, "new", 0) \
152 K(kReturn, "return", 0) \
153 K(kSwitch, "switch", 0) \
154 K(kThrow, "throw", 0) \
155 K(kTry, "try", 0) \
156 /* kTypeOf */ \
157 K(kVar, "var", 0) \
158 /* kVoid */ \
159 K(kWhile, "while", 0) \
160 K(kWith, "with", 0) \
161 K(kThis, "this", 0) \
162 \
163 /* Literals (ECMA-262, section 7.8, page 16). */ \
164 K(kNullLiteral, "null", 0) \
165 K(kTrueLiteral, "true", 0) \
166 K(kFalseLiteral, "false", 0) \
167 T(kNumber, nullptr, 0) \
168 T(kSmi, nullptr, 0) \
169 T(kBigInt, nullptr, 0) \
170 T(kString, nullptr, 0) \
171 \
172 /* BEGIN Callable */ \
173 K(kSuper, "super", 0) \
174 /* BEGIN AnyIdentifier */ \
175 /* Identifiers (not keywords or future reserved words). */ \
176 /* TODO(rezvan): Add remaining contextual keywords (meta, target, as, from) \
177 * to tokens. */ \
178 T(kIdentifier, nullptr, 0) \
179 K(kGet, "get", 0) \
180 K(kSet, "set", 0) \
181 K(kUsing, "using", 0) \
182 K(kOf, "of", 0) \
183 K(kAccessor, "accessor", 0) \
184 K(kAsync, "async", 0) \
185 /* `await` is a reserved word in module code only */ \
186 K(kAwait, "await", 0) \
187 K(kYield, "yield", 0) \
188 K(kLet, "let", 0) \
189 K(kStatic, "static", 0) \
190 /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
191 T(kFutureStrictReservedWord, nullptr, 0) \
192 T(kEscapedStrictReservedWord, nullptr, 0) \
193 /* END AnyIdentifier */ \
194 /* END Callable */ \
195 K(kEnum, "enum", 0) \
196 K(kClass, "class", 0) \
197 K(kConst, "const", 0) \
198 K(kExport, "export", 0) \
199 K(kExtends, "extends", 0) \
200 K(kImport, "import", 0) \
201 T(kPrivateName, nullptr, 0) \
202 \
203 /* Illegal token - not able to scan. */ \
204 T(kIllegal, "ILLEGAL", 0) \
205 T(kEscapedKeyword, nullptr, 0) \
206 \
207 /* Scanner-internal use only. */ \
208 T(kWhitespace, nullptr, 0) \
209 T(kUninitialized, nullptr, 0) \
210 T(kRegExpLiteral, nullptr, 0)
213 public:
214 // All token values.
215#define T(name, string, precedence) name,
216 enum Value : uint8_t { TOKEN_LIST(T, T) kNumTokens };
217#undef T
218
219 // Returns a string corresponding to the C++ token name
220 // (e.g. "kLessThan" for the token kLessThan).
221 static const char* Name(Value token) {
222 DCHECK_GT(kNumTokens, token); // token is unsigned
223 return name_[token];
224 }
228
229 // Predicates
230 static bool IsKeyword(Value token) {
231 return IsKeywordBits::decode(token_flags[token]);
232 }
234 static bool IsPropertyName(Value token) {
235 return IsPropertyNameBits::decode(token_flags[token]);
236 }
238 V8_INLINE static bool IsValidIdentifier(Value token,
239 LanguageMode language_mode,
240 bool is_generator,
241 bool disallow_await) {
242 if (V8_LIKELY(base::IsInRange(token, kIdentifier, kAsync))) return true;
243 if (token == kAwait) return !disallow_await;
244 if (token == kYield) return !is_generator && is_sloppy(language_mode);
245 return IsStrictReservedWord(token) && is_sloppy(language_mode);
246 }
248 static bool IsCallable(Value token) {
249 return base::IsInRange(token, kSuper, kEscapedStrictReservedWord);
250 }
252 static bool IsAutoSemicolon(Value token) {
253 return base::IsInRange(token, kSemicolon, kEos);
254 }
256 static bool IsAnyIdentifier(Value token) {
257 return base::IsInRange(token, kIdentifier, kEscapedStrictReservedWord);
258 }
260 static bool IsStrictReservedWord(Value token) {
261 return base::IsInRange(token, kYield, kEscapedStrictReservedWord);
262 }
264 static bool IsLiteral(Value token) {
265 return base::IsInRange(token, kNullLiteral, kString);
266 }
268 static bool IsTemplate(Value token) {
269 return base::IsInRange(token, kTemplateSpan, kTemplateTail);
270 }
272 static bool IsMember(Value token) {
273 return base::IsInRange(token, kTemplateSpan, kLeftBracket);
274 }
276 static bool IsProperty(Value token) {
277 return base::IsInRange(token, kPeriod, kLeftBracket);
278 }
280 static bool IsPropertyOrCall(Value token) {
281 return base::IsInRange(token, kTemplateSpan, kLeftParen);
282 }
284 static bool IsArrowOrAssignmentOp(Value token) {
285 return base::IsInRange(token, kArrow, kAssignSub);
286 }
288 static bool IsAssignmentOp(Value token) {
289 return base::IsInRange(token, kInit, kAssignSub);
290 }
292 static bool IsLogicalAssignmentOp(Value token) {
293 return base::IsInRange(token, kAssignNullish, kAssignAnd);
294 }
296 static bool IsBinaryOp(Value op) { return base::IsInRange(op, kComma, kSub); }
298 static bool IsCompareOp(Value op) { return base::IsInRange(op, kEq, kIn); }
300 static bool IsOrderedRelationalCompareOp(Value op) {
301 return base::IsInRange(op, kLessThan, kGreaterThanEq);
302 }
304 static bool IsEqualityOp(Value op) {
305 return base::IsInRange(op, kEq, kEqStrict);
306 }
308 static Value BinaryOpForAssignment(Value op) {
309 DCHECK(base::IsInRange(op, kAssignNullish, kAssignSub));
310 Value result = static_cast<Value>(op - kAssignNullish + kNullish);
311 DCHECK(IsBinaryOp(result));
312 return result;
313 }
315 static bool IsBitOp(Value op) {
316 return base::IsInRange(op, kBitOr, kShr) || op == kBitNot;
317 }
319 static bool IsUnaryOp(Value op) { return base::IsInRange(op, kAdd, kVoid); }
320 static bool IsCountOp(Value op) { return base::IsInRange(op, kInc, kDec); }
321 static bool IsUnaryOrCountOp(Value op) {
322 return base::IsInRange(op, kAdd, kDec);
324 static bool IsShiftOp(Value op) { return base::IsInRange(op, kShl, kShr); }
325
326 // Returns a string corresponding to the JS token string
327 // (.e., "<" for the token kLessThan) or nullptr if the token doesn't
328 // have a (unique) string (e.g. a kIdentifier).
329 static const char* String(Value token) {
330 DCHECK_GT(kNumTokens, token); // token is unsigned
331 return string_[token];
332 }
334 static uint8_t StringLength(Value token) {
335 DCHECK_GT(kNumTokens, token); // token is unsigned
336 return string_length_[token];
337 }
338
339 // Returns the precedence > 0 for binary and compare
340 // operators; returns 0 otherwise.
341 static int Precedence(Value token, bool accept_IN) {
342 DCHECK_GT(kNumTokens, token); // token is unsigned
343 return precedence_[accept_IN][token];
344 }
345
346 private:
347 static const char* const name_[kNumTokens];
348 static const char* const string_[kNumTokens];
349 static const uint8_t string_length_[kNumTokens];
350 static const int8_t precedence_[2][kNumTokens];
351 static const uint8_t token_flags[kNumTokens];
352};
353
354} // namespace internal
355} // namespace v8
356
357#endif // V8_PARSING_TOKEN_H_
DirectHandle< String > string_
ZoneVector< RpoNumber > & result
const char * name_
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define TOKEN_LIST(T, K)
Definition token.h:56
#define V8_INLINE
Definition v8config.h:500
#define V8_LIKELY(condition)
Definition v8config.h:661