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 NULL, 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() and Assignment::is_compound() relies on */ \
57 : /* this block of enum values being contiguous and sorted in the */ \
58 : /* same order! */ \
59 : T(INIT, "=init", 2) /* AST-use only. */ \
60 : T(ASSIGN, "=", 2) \
61 : T(ASSIGN_BIT_OR, "|=", 2) \
62 : T(ASSIGN_BIT_XOR, "^=", 2) \
63 : T(ASSIGN_BIT_AND, "&=", 2) \
64 : T(ASSIGN_SHL, "<<=", 2) \
65 : T(ASSIGN_SAR, ">>=", 2) \
66 : T(ASSIGN_SHR, ">>>=", 2) \
67 : T(ASSIGN_ADD, "+=", 2) \
68 : T(ASSIGN_SUB, "-=", 2) \
69 : T(ASSIGN_MUL, "*=", 2) \
70 : T(ASSIGN_DIV, "/=", 2) \
71 : T(ASSIGN_MOD, "%=", 2) \
72 : T(ASSIGN_EXP, "**=", 2) \
73 : \
74 : /* Binary operators sorted by precedence. */ \
75 : /* IsBinaryOp() relies on this block of enum values */ \
76 : /* being contiguous and sorted in the same order! */ \
77 : T(COMMA, ",", 1) \
78 : T(OR, "||", 4) \
79 : T(AND, "&&", 5) \
80 : T(BIT_OR, "|", 6) \
81 : T(BIT_XOR, "^", 7) \
82 : T(BIT_AND, "&", 8) \
83 : T(SHL, "<<", 11) \
84 : T(SAR, ">>", 11) \
85 : T(SHR, ">>>", 11) \
86 : T(ROR, "rotate right", 11) /* only used by Crankshaft */ \
87 : T(ADD, "+", 12) \
88 : T(SUB, "-", 12) \
89 : T(MUL, "*", 13) \
90 : T(DIV, "/", 13) \
91 : T(MOD, "%", 13) \
92 : T(EXP, "**", 14) \
93 : \
94 : /* Compare operators sorted by precedence. */ \
95 : /* IsCompareOp() relies on this block of enum values */ \
96 : /* being contiguous and sorted in the same order! */ \
97 : T(EQ, "==", 9) \
98 : T(NE, "!=", 9) \
99 : T(EQ_STRICT, "===", 9) \
100 : T(NE_STRICT, "!==", 9) \
101 : T(LT, "<", 10) \
102 : T(GT, ">", 10) \
103 : T(LTE, "<=", 10) \
104 : T(GTE, ">=", 10) \
105 : K(INSTANCEOF, "instanceof", 10) \
106 : K(IN, "in", 10) \
107 : \
108 : /* Unary operators. */ \
109 : /* IsUnaryOp() relies on this block of enum values */ \
110 : /* being contiguous and sorted in the same order! */ \
111 : T(NOT, "!", 0) \
112 : T(BIT_NOT, "~", 0) \
113 : K(DELETE, "delete", 0) \
114 : K(TYPEOF, "typeof", 0) \
115 : K(VOID, "void", 0) \
116 : \
117 : /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
118 : K(BREAK, "break", 0) \
119 : K(CASE, "case", 0) \
120 : K(CATCH, "catch", 0) \
121 : K(CONTINUE, "continue", 0) \
122 : K(DEBUGGER, "debugger", 0) \
123 : K(DEFAULT, "default", 0) \
124 : /* DELETE */ \
125 : K(DO, "do", 0) \
126 : K(ELSE, "else", 0) \
127 : K(FINALLY, "finally", 0) \
128 : K(FOR, "for", 0) \
129 : K(FUNCTION, "function", 0) \
130 : K(IF, "if", 0) \
131 : /* IN */ \
132 : /* INSTANCEOF */ \
133 : K(NEW, "new", 0) \
134 : K(RETURN, "return", 0) \
135 : K(SWITCH, "switch", 0) \
136 : K(THIS, "this", 0) \
137 : K(THROW, "throw", 0) \
138 : K(TRY, "try", 0) \
139 : /* TYPEOF */ \
140 : K(VAR, "var", 0) \
141 : /* VOID */ \
142 : K(WHILE, "while", 0) \
143 : K(WITH, "with", 0) \
144 : \
145 : /* Literals (ECMA-262, section 7.8, page 16). */ \
146 : K(NULL_LITERAL, "null", 0) \
147 : K(TRUE_LITERAL, "true", 0) \
148 : K(FALSE_LITERAL, "false", 0) \
149 : T(NUMBER, NULL, 0) \
150 : T(SMI, NULL, 0) \
151 : T(STRING, NULL, 0) \
152 : \
153 : /* Identifiers (not keywords or future reserved words). */ \
154 : T(IDENTIFIER, NULL, 0) \
155 : \
156 : /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
157 : T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
158 : K(ASYNC, "async", 0) \
159 : /* `await` is a reserved word in module code only */ \
160 : K(AWAIT, "await", 0) \
161 : K(CLASS, "class", 0) \
162 : K(CONST, "const", 0) \
163 : K(ENUM, "enum", 0) \
164 : K(EXPORT, "export", 0) \
165 : K(EXTENDS, "extends", 0) \
166 : K(IMPORT, "import", 0) \
167 : K(LET, "let", 0) \
168 : K(STATIC, "static", 0) \
169 : K(YIELD, "yield", 0) \
170 : K(SUPER, "super", 0) \
171 : \
172 : /* Illegal token - not able to scan. */ \
173 : T(ILLEGAL, "ILLEGAL", 0) \
174 : T(ESCAPED_KEYWORD, NULL, 0) \
175 : T(ESCAPED_STRICT_RESERVED_WORD, NULL, 0) \
176 : \
177 : /* Scanner-internal use only. */ \
178 : T(WHITESPACE, NULL, 0) \
179 : T(UNINITIALIZED, NULL, 0) \
180 : T(REGEXP_LITERAL, NULL, 0) \
181 : \
182 : /* ES6 Template Literals */ \
183 : T(TEMPLATE_SPAN, NULL, 0) \
184 : T(TEMPLATE_TAIL, NULL, 0) \
185 : \
186 : /* Contextual keyword tokens */ \
187 : C(GET, "get", 0) \
188 : C(SET, "set", 0) \
189 : C(OF, "of", 0) \
190 : C(TARGET, "target", 0) \
191 : C(SENT, "sent", 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 658253 : return name_[tok];
215 : }
216 :
217 : // Predicates
218 : static bool IsKeyword(Value tok) {
219 81017 : return token_type[tok] == 'K';
220 : }
221 437502499 : static bool IsContextualKeyword(Value tok) { return token_type[tok] == 'C'; }
222 :
223 249832 : static bool IsIdentifier(Value tok, LanguageMode language_mode,
224 : bool is_generator, bool disallow_await) {
225 249832 : 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 1814 : return is_sloppy(language_mode);
234 : case YIELD:
235 355 : return !is_generator && is_sloppy(language_mode);
236 : case AWAIT:
237 1302 : return !disallow_await;
238 : default:
239 7536 : return false;
240 : }
241 : UNREACHABLE();
242 : return false;
243 : }
244 :
245 : static bool IsAssignmentOp(Value tok) {
246 137021872 : return INIT <= tok && tok <= ASSIGN_EXP;
247 : }
248 :
249 : static bool IsBinaryOp(Value op) { return COMMA <= op && op <= EXP; }
250 :
251 : static bool IsTruncatingBinaryOp(Value op) {
252 1735220 : return BIT_OR <= op && op <= ROR;
253 : }
254 :
255 : static bool IsCompareOp(Value op) {
256 17069564 : return EQ <= op && op <= IN;
257 : }
258 :
259 : static bool IsOrderedRelationalCompareOp(Value op) {
260 141986 : return op == LT || op == LTE || op == GT || op == GTE;
261 : }
262 :
263 : static bool IsEqualityOp(Value op) {
264 643091 : return op == EQ || op == EQ_STRICT;
265 : }
266 :
267 : static bool IsInequalityOp(Value op) {
268 : return op == NE || op == NE_STRICT;
269 : }
270 :
271 : static bool IsArithmeticCompareOp(Value op) {
272 : return IsOrderedRelationalCompareOp(op) ||
273 : IsEqualityOp(op) || IsInequalityOp(op);
274 : }
275 :
276 149331 : static Value NegateCompareOp(Value op) {
277 : DCHECK(IsArithmeticCompareOp(op));
278 149331 : switch (op) {
279 : case EQ: return NE;
280 13565 : case NE: return EQ;
281 15388 : case EQ_STRICT: return NE_STRICT;
282 0 : case NE_STRICT: return EQ_STRICT;
283 32617 : case LT: return GTE;
284 32220 : case GT: return LTE;
285 4755 : case LTE: return GT;
286 5047 : case GTE: return LT;
287 : default:
288 0 : UNREACHABLE();
289 : return op;
290 : }
291 : }
292 :
293 298662 : static Value ReverseCompareOp(Value op) {
294 : DCHECK(IsArithmeticCompareOp(op));
295 298662 : switch (op) {
296 : case EQ: return EQ;
297 59304 : case NE: return NE;
298 15388 : case EQ_STRICT: return EQ_STRICT;
299 15388 : case NE_STRICT: return NE_STRICT;
300 37664 : case LT: return GT;
301 36975 : case GT: return LT;
302 36975 : case LTE: return GTE;
303 37664 : case GTE: return LTE;
304 : default:
305 0 : UNREACHABLE();
306 : return op;
307 : }
308 : }
309 :
310 9145 : static bool EvalComparison(Value op, double op1, double op2) {
311 : DCHECK(IsArithmeticCompareOp(op));
312 9145 : switch (op) {
313 : case Token::EQ:
314 8267 : case Token::EQ_STRICT: return (op1 == op2);
315 0 : case Token::NE: return (op1 != op2);
316 336 : case Token::LT: return (op1 < op2);
317 156 : case Token::GT: return (op1 > op2);
318 207 : case Token::LTE: return (op1 <= op2);
319 179 : case Token::GTE: return (op1 >= op2);
320 : default:
321 0 : UNREACHABLE();
322 : return false;
323 : }
324 : }
325 :
326 : static bool IsBitOp(Value op) {
327 : return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
328 : }
329 :
330 : static bool IsUnaryOp(Value op) {
331 89648375 : return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
332 : }
333 :
334 : static bool IsCountOp(Value op) {
335 169016338 : return op == INC || op == DEC;
336 : }
337 :
338 : static bool IsShiftOp(Value op) {
339 : return (SHL <= op) && (op <= SHR);
340 : }
341 :
342 : // Returns a string corresponding to the JS token string
343 : // (.e., "<" for the token LT) or NULL if the token doesn't
344 : // have a (unique) string (e.g. an IDENTIFIER).
345 : static const char* String(Value tok) {
346 : DCHECK(tok < NUM_TOKENS); // tok is unsigned.
347 201689593 : return string_[tok];
348 : }
349 :
350 : static uint8_t StringLength(Value tok) {
351 : DCHECK(tok < NUM_TOKENS);
352 4878832 : return string_length_[tok];
353 : }
354 :
355 : // Returns the precedence > 0 for binary and compare
356 : // operators; returns 0 otherwise.
357 : static int Precedence(Value tok) {
358 : DCHECK(tok < NUM_TOKENS); // tok is unsigned.
359 193810554 : return precedence_[tok];
360 : }
361 :
362 : private:
363 : static const char* const name_[NUM_TOKENS];
364 : static const char* const string_[NUM_TOKENS];
365 : static const uint8_t string_length_[NUM_TOKENS];
366 : static const int8_t precedence_[NUM_TOKENS];
367 : static const char token_type[NUM_TOKENS];
368 : };
369 :
370 : } // namespace internal
371 : } // namespace v8
372 :
373 : #endif // V8_PARSING_TOKEN_H_
|