Line data Source code
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 :
8 : #include "src/base/logging.h"
9 : #include "src/globals.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : // TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
15 : // same signature M(name, string, precedence), where name is the
16 : // symbolic token name, string is the corresponding syntactic symbol
17 : // (or nullptr, for literals), and precedence is the precedence (or 0).
18 : // The parameters are invoked for token categories as follows:
19 : //
20 : // T: Non-keyword tokens
21 : // K: Keyword tokens
22 : // C: Contextual keyword token
23 : //
24 : // Contextual keyword tokens are tokens that are scanned as Token::IDENTIFIER,
25 : // but that in some contexts are treated as keywords. This mostly happens
26 : // when ECMAScript introduces new keywords, but for backwards compatibility
27 : // allows them to still be used as indentifiers in most contexts.
28 :
29 : // IGNORE_TOKEN is a convenience macro that can be supplied as
30 : // an argument (at any position) for a TOKEN_LIST call. It does
31 : // nothing with tokens belonging to the respective category.
32 :
33 : #define IGNORE_TOKEN(name, string, precedence)
34 :
35 : #define TOKEN_LIST(T, K, C) \
36 : /* End of source indicator. */ \
37 : T(EOS, "EOS", 0) \
38 : \
39 : /* Punctuators (ECMA-262, section 7.7, page 15). */ \
40 : T(LPAREN, "(", 0) \
41 : T(RPAREN, ")", 0) \
42 : T(LBRACK, "[", 0) \
43 : T(RBRACK, "]", 0) \
44 : T(LBRACE, "{", 0) \
45 : T(RBRACE, "}", 0) \
46 : T(COLON, ":", 0) \
47 : T(SEMICOLON, ";", 0) \
48 : T(PERIOD, ".", 0) \
49 : T(ELLIPSIS, "...", 0) \
50 : T(CONDITIONAL, "?", 3) \
51 : T(INC, "++", 0) \
52 : T(DEC, "--", 0) \
53 : T(ARROW, "=>", 0) \
54 : \
55 : /* Assignment operators. */ \
56 : /* IsAssignmentOp() relies on this block of enum values being */ \
57 : /* contiguous and sorted in the same order! */ \
58 : T(INIT, "=init", 2) /* AST-use only. */ \
59 : T(ASSIGN, "=", 2) \
60 : T(ASSIGN_BIT_OR, "|=", 2) \
61 : T(ASSIGN_BIT_XOR, "^=", 2) \
62 : T(ASSIGN_BIT_AND, "&=", 2) \
63 : T(ASSIGN_SHL, "<<=", 2) \
64 : T(ASSIGN_SAR, ">>=", 2) \
65 : T(ASSIGN_SHR, ">>>=", 2) \
66 : T(ASSIGN_ADD, "+=", 2) \
67 : T(ASSIGN_SUB, "-=", 2) \
68 : T(ASSIGN_MUL, "*=", 2) \
69 : T(ASSIGN_DIV, "/=", 2) \
70 : T(ASSIGN_MOD, "%=", 2) \
71 : T(ASSIGN_EXP, "**=", 2) \
72 : \
73 : /* Binary operators sorted by precedence. */ \
74 : /* IsBinaryOp() relies on this block of enum values */ \
75 : /* being contiguous and sorted in the same order! */ \
76 : T(COMMA, ",", 1) \
77 : T(OR, "||", 4) \
78 : T(AND, "&&", 5) \
79 : T(BIT_OR, "|", 6) \
80 : T(BIT_XOR, "^", 7) \
81 : T(BIT_AND, "&", 8) \
82 : T(SHL, "<<", 11) \
83 : T(SAR, ">>", 11) \
84 : T(SHR, ">>>", 11) \
85 : T(ADD, "+", 12) \
86 : T(SUB, "-", 12) \
87 : T(MUL, "*", 13) \
88 : T(DIV, "/", 13) \
89 : T(MOD, "%", 13) \
90 : T(EXP, "**", 14) \
91 : \
92 : /* Compare operators sorted by precedence. */ \
93 : /* IsCompareOp() relies on this block of enum values */ \
94 : /* being contiguous and sorted in the same order! */ \
95 : T(EQ, "==", 9) \
96 : T(NE, "!=", 9) \
97 : T(EQ_STRICT, "===", 9) \
98 : T(NE_STRICT, "!==", 9) \
99 : T(LT, "<", 10) \
100 : T(GT, ">", 10) \
101 : T(LTE, "<=", 10) \
102 : T(GTE, ">=", 10) \
103 : K(INSTANCEOF, "instanceof", 10) \
104 : K(IN, "in", 10) \
105 : \
106 : /* Unary operators. */ \
107 : /* IsUnaryOp() relies on this block of enum values */ \
108 : /* being contiguous and sorted in the same order! */ \
109 : T(NOT, "!", 0) \
110 : T(BIT_NOT, "~", 0) \
111 : K(DELETE, "delete", 0) \
112 : K(TYPEOF, "typeof", 0) \
113 : K(VOID, "void", 0) \
114 : \
115 : /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
116 : K(BREAK, "break", 0) \
117 : K(CASE, "case", 0) \
118 : K(CATCH, "catch", 0) \
119 : K(CONTINUE, "continue", 0) \
120 : K(DEBUGGER, "debugger", 0) \
121 : K(DEFAULT, "default", 0) \
122 : /* DELETE */ \
123 : K(DO, "do", 0) \
124 : K(ELSE, "else", 0) \
125 : K(FINALLY, "finally", 0) \
126 : K(FOR, "for", 0) \
127 : K(FUNCTION, "function", 0) \
128 : K(IF, "if", 0) \
129 : /* IN */ \
130 : /* INSTANCEOF */ \
131 : K(NEW, "new", 0) \
132 : K(RETURN, "return", 0) \
133 : K(SWITCH, "switch", 0) \
134 : K(THIS, "this", 0) \
135 : K(THROW, "throw", 0) \
136 : K(TRY, "try", 0) \
137 : /* TYPEOF */ \
138 : K(VAR, "var", 0) \
139 : /* VOID */ \
140 : K(WHILE, "while", 0) \
141 : K(WITH, "with", 0) \
142 : \
143 : /* Literals (ECMA-262, section 7.8, page 16). */ \
144 : K(NULL_LITERAL, "null", 0) \
145 : K(TRUE_LITERAL, "true", 0) \
146 : K(FALSE_LITERAL, "false", 0) \
147 : T(NUMBER, nullptr, 0) \
148 : T(SMI, nullptr, 0) \
149 : T(STRING, nullptr, 0) \
150 : T(BIGINT, nullptr, 0) \
151 : \
152 : /* Identifiers (not keywords or future reserved words). */ \
153 : T(IDENTIFIER, nullptr, 0) \
154 : \
155 : /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
156 : T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \
157 : K(ASYNC, "async", 0) \
158 : /* `await` is a reserved word in module code only */ \
159 : K(AWAIT, "await", 0) \
160 : K(CLASS, "class", 0) \
161 : K(CONST, "const", 0) \
162 : K(ENUM, "enum", 0) \
163 : K(EXPORT, "export", 0) \
164 : K(EXTENDS, "extends", 0) \
165 : K(IMPORT, "import", 0) \
166 : K(LET, "let", 0) \
167 : K(STATIC, "static", 0) \
168 : K(YIELD, "yield", 0) \
169 : K(SUPER, "super", 0) \
170 : \
171 : /* Illegal token - not able to scan. */ \
172 : T(ILLEGAL, "ILLEGAL", 0) \
173 : T(ESCAPED_KEYWORD, nullptr, 0) \
174 : T(ESCAPED_STRICT_RESERVED_WORD, nullptr, 0) \
175 : \
176 : /* Scanner-internal use only. */ \
177 : T(WHITESPACE, nullptr, 0) \
178 : T(UNINITIALIZED, nullptr, 0) \
179 : T(REGEXP_LITERAL, nullptr, 0) \
180 : \
181 : /* ES6 Template Literals */ \
182 : T(TEMPLATE_SPAN, nullptr, 0) \
183 : T(TEMPLATE_TAIL, nullptr, 0) \
184 : \
185 : /* Contextual keyword tokens */ \
186 : C(GET, "get", 0) \
187 : C(SET, "set", 0) \
188 : C(OF, "of", 0) \
189 : C(TARGET, "target", 0) \
190 : C(SENT, "sent", 0) \
191 : C(META, "meta", 0) \
192 : C(AS, "as", 0) \
193 : C(FROM, "from", 0) \
194 : C(NAME, "name", 0) \
195 : C(PROTO_UNDERSCORED, "__proto__", 0) \
196 : C(CONSTRUCTOR, "constructor", 0) \
197 : C(PROTOTYPE, "prototype", 0) \
198 : C(EVAL, "eval", 0) \
199 : C(ARGUMENTS, "arguments", 0) \
200 : C(UNDEFINED, "undefined", 0) \
201 : C(ANONYMOUS, "anonymous", 0)
202 :
203 : class Token {
204 : public:
205 : // All token values.
206 : #define T(name, string, precedence) name,
207 : enum Value { TOKEN_LIST(T, T, T) NUM_TOKENS };
208 : #undef T
209 :
210 : // Returns a string corresponding to the C++ token name
211 : // (e.g. "LT" for the token LT).
212 : static const char* Name(Value tok) {
213 : DCHECK(tok < NUM_TOKENS); // tok is unsigned
214 5646 : return name_[tok];
215 : }
216 :
217 : // Predicates
218 : static bool IsKeyword(Value tok) {
219 115621 : return token_type[tok] == 'K';
220 : }
221 313646376 : static bool IsContextualKeyword(Value tok) { return token_type[tok] == 'C'; }
222 :
223 184353 : static bool IsIdentifier(Value tok, LanguageMode language_mode,
224 : bool is_generator, bool disallow_await) {
225 184353 : switch (tok) {
226 : case IDENTIFIER:
227 : case ASYNC:
228 : return true;
229 : case ESCAPED_STRICT_RESERVED_WORD:
230 : case FUTURE_STRICT_RESERVED_WORD:
231 : case LET:
232 : case STATIC:
233 1510 : return is_sloppy(language_mode);
234 : case YIELD:
235 295 : return !is_generator && is_sloppy(language_mode);
236 : case AWAIT:
237 1725 : return !disallow_await;
238 : default:
239 6253 : return false;
240 : }
241 : UNREACHABLE();
242 : }
243 :
244 : static bool IsAssignmentOp(Value tok) {
245 96220888 : return INIT <= tok && tok <= ASSIGN_EXP;
246 : }
247 :
248 : static bool IsBinaryOp(Value op) { return COMMA <= op && op <= EXP; }
249 :
250 : static bool IsTruncatingBinaryOp(Value op) {
251 : return BIT_OR <= op && op <= SHR;
252 : }
253 :
254 : static bool IsCompareOp(Value op) {
255 11503759 : return EQ <= op && op <= IN;
256 : }
257 :
258 : static bool IsOrderedRelationalCompareOp(Value op) {
259 1296 : return op == LT || op == LTE || op == GT || op == GTE;
260 : }
261 :
262 : static bool IsEqualityOp(Value op) {
263 281979 : return op == EQ || op == EQ_STRICT;
264 : }
265 :
266 : static bool IsInequalityOp(Value op) {
267 : return op == NE || op == NE_STRICT;
268 : }
269 :
270 : static bool IsArithmeticCompareOp(Value op) {
271 : return IsOrderedRelationalCompareOp(op) ||
272 : IsEqualityOp(op) || IsInequalityOp(op);
273 : }
274 :
275 : static Value NegateCompareOp(Value op) {
276 : DCHECK(IsArithmeticCompareOp(op));
277 : switch (op) {
278 : case EQ: return NE;
279 : case NE: return EQ;
280 : case EQ_STRICT: return NE_STRICT;
281 : case NE_STRICT: return EQ_STRICT;
282 : case LT: return GTE;
283 : case GT: return LTE;
284 : case LTE: return GT;
285 : case GTE: return LT;
286 : default:
287 : UNREACHABLE();
288 : }
289 : }
290 :
291 : static Value ReverseCompareOp(Value op) {
292 : DCHECK(IsArithmeticCompareOp(op));
293 : switch (op) {
294 : case EQ: return EQ;
295 : case NE: return NE;
296 : case EQ_STRICT: return EQ_STRICT;
297 : case NE_STRICT: return NE_STRICT;
298 : case LT: return GT;
299 : case GT: return LT;
300 : case LTE: return GTE;
301 : case GTE: return LTE;
302 : default:
303 : UNREACHABLE();
304 : }
305 : }
306 :
307 : static bool EvalComparison(Value op, double op1, double op2) {
308 : DCHECK(IsArithmeticCompareOp(op));
309 : switch (op) {
310 : case Token::EQ:
311 : case Token::EQ_STRICT: return (op1 == op2);
312 : case Token::NE: return (op1 != op2);
313 : case Token::LT: return (op1 < op2);
314 : case Token::GT: return (op1 > op2);
315 : case Token::LTE: return (op1 <= op2);
316 : case Token::GTE: return (op1 >= op2);
317 : default:
318 : UNREACHABLE();
319 : }
320 : }
321 :
322 332182 : static Value BinaryOpForAssignment(Value op) {
323 : DCHECK(IsAssignmentOp(op));
324 332182 : switch (op) {
325 : case Token::ASSIGN_BIT_OR:
326 : return Token::BIT_OR;
327 : case Token::ASSIGN_BIT_XOR:
328 2967 : return Token::BIT_XOR;
329 : case Token::ASSIGN_BIT_AND:
330 2764 : return Token::BIT_AND;
331 : case Token::ASSIGN_SHL:
332 2438 : return Token::SHL;
333 : case Token::ASSIGN_SAR:
334 2691 : return Token::SAR;
335 : case Token::ASSIGN_SHR:
336 2652 : return Token::SHR;
337 : case Token::ASSIGN_ADD:
338 302329 : return Token::ADD;
339 : case Token::ASSIGN_SUB:
340 4859 : return Token::SUB;
341 : case Token::ASSIGN_MUL:
342 2993 : return Token::MUL;
343 : case Token::ASSIGN_DIV:
344 2641 : return Token::DIV;
345 : case Token::ASSIGN_MOD:
346 3053 : return Token::MOD;
347 : default:
348 0 : UNREACHABLE();
349 : }
350 : }
351 :
352 : static bool IsBitOp(Value op) {
353 : return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
354 : }
355 :
356 : static bool IsUnaryOp(Value op) {
357 61833500 : return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
358 : }
359 :
360 : static bool IsCountOp(Value op) {
361 116871194 : return op == INC || op == DEC;
362 : }
363 :
364 : static bool IsShiftOp(Value op) {
365 : return (SHL <= op) && (op <= SHR);
366 : }
367 :
368 : // Returns a string corresponding to the JS token string
369 : // (.e., "<" for the token LT) or nullptr if the token doesn't
370 : // have a (unique) string (e.g. an IDENTIFIER).
371 : static const char* String(Value tok) {
372 : DCHECK(tok < NUM_TOKENS); // tok is unsigned.
373 139864188 : return string_[tok];
374 : }
375 :
376 : static uint8_t StringLength(Value tok) {
377 : DCHECK(tok < NUM_TOKENS);
378 3488722 : return string_length_[tok];
379 : }
380 :
381 : // Returns the precedence > 0 for binary and compare
382 : // operators; returns 0 otherwise.
383 : static int Precedence(Value tok) {
384 : DCHECK(tok < NUM_TOKENS); // tok is unsigned.
385 135253389 : return precedence_[tok];
386 : }
387 :
388 : private:
389 : static const char* const name_[NUM_TOKENS];
390 : static const char* const string_[NUM_TOKENS];
391 : static const uint8_t string_length_[NUM_TOKENS];
392 : static const int8_t precedence_[NUM_TOKENS];
393 : static const char token_type[NUM_TOKENS];
394 : };
395 :
396 : } // namespace internal
397 : } // namespace v8
398 :
399 : #endif // V8_PARSING_TOKEN_H_
|