blob: fae9ea8bffb7f07feff5fe25fd851a79631e7a38 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
11namespace v8 {
12namespace 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
23// IGNORE_TOKEN is a convenience macro that can be supplied as
24// an argument (at any position) for a TOKEN_LIST call. It does
25// nothing with tokens belonging to the respective category.
26
27#define IGNORE_TOKEN(name, string, precedence)
28
29#define TOKEN_LIST(T, K) \
30 /* End of source indicator. */ \
31 T(EOS, "EOS", 0) \
32 \
33 /* Punctuators (ECMA-262, section 7.7, page 15). */ \
34 T(LPAREN, "(", 0) \
35 T(RPAREN, ")", 0) \
36 T(LBRACK, "[", 0) \
37 T(RBRACK, "]", 0) \
38 T(LBRACE, "{", 0) \
39 T(RBRACE, "}", 0) \
40 T(COLON, ":", 0) \
41 T(SEMICOLON, ";", 0) \
42 T(PERIOD, ".", 0) \
43 T(ELLIPSIS, "...", 0) \
44 T(CONDITIONAL, "?", 3) \
45 T(INC, "++", 0) \
46 T(DEC, "--", 0) \
47 T(ARROW, "=>", 0) \
48 \
49 /* Assignment operators. */ \
50 /* IsAssignmentOp() and Assignment::is_compound() relies on */ \
51 /* this block of enum values being contiguous and sorted in the */ \
52 /* same order! */ \
53 T(INIT, "=init", 2) /* AST-use only. */ \
54 T(ASSIGN, "=", 2) \
55 T(ASSIGN_BIT_OR, "|=", 2) \
56 T(ASSIGN_BIT_XOR, "^=", 2) \
57 T(ASSIGN_BIT_AND, "&=", 2) \
58 T(ASSIGN_SHL, "<<=", 2) \
59 T(ASSIGN_SAR, ">>=", 2) \
60 T(ASSIGN_SHR, ">>>=", 2) \
61 T(ASSIGN_ADD, "+=", 2) \
62 T(ASSIGN_SUB, "-=", 2) \
63 T(ASSIGN_MUL, "*=", 2) \
64 T(ASSIGN_DIV, "/=", 2) \
65 T(ASSIGN_MOD, "%=", 2) \
Ben Murdochda12d292016-06-02 14:46:10 +010066 T(ASSIGN_EXP, "**=", 2) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 \
68 /* Binary operators sorted by precedence. */ \
69 /* IsBinaryOp() relies on this block of enum values */ \
70 /* being contiguous and sorted in the same order! */ \
71 T(COMMA, ",", 1) \
72 T(OR, "||", 4) \
73 T(AND, "&&", 5) \
74 T(BIT_OR, "|", 6) \
75 T(BIT_XOR, "^", 7) \
76 T(BIT_AND, "&", 8) \
77 T(SHL, "<<", 11) \
78 T(SAR, ">>", 11) \
79 T(SHR, ">>>", 11) \
80 T(ROR, "rotate right", 11) /* only used by Crankshaft */ \
81 T(ADD, "+", 12) \
82 T(SUB, "-", 12) \
83 T(MUL, "*", 13) \
84 T(DIV, "/", 13) \
85 T(MOD, "%", 13) \
Ben Murdochda12d292016-06-02 14:46:10 +010086 T(EXP, "**", 14) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 \
88 /* Compare operators sorted by precedence. */ \
89 /* IsCompareOp() relies on this block of enum values */ \
90 /* being contiguous and sorted in the same order! */ \
91 T(EQ, "==", 9) \
92 T(NE, "!=", 9) \
93 T(EQ_STRICT, "===", 9) \
94 T(NE_STRICT, "!==", 9) \
95 T(LT, "<", 10) \
96 T(GT, ">", 10) \
97 T(LTE, "<=", 10) \
98 T(GTE, ">=", 10) \
99 K(INSTANCEOF, "instanceof", 10) \
100 K(IN, "in", 10) \
101 \
102 /* Unary operators. */ \
103 /* IsUnaryOp() relies on this block of enum values */ \
104 /* being contiguous and sorted in the same order! */ \
105 T(NOT, "!", 0) \
106 T(BIT_NOT, "~", 0) \
107 K(DELETE, "delete", 0) \
108 K(TYPEOF, "typeof", 0) \
109 K(VOID, "void", 0) \
110 \
111 /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
112 K(BREAK, "break", 0) \
113 K(CASE, "case", 0) \
114 K(CATCH, "catch", 0) \
115 K(CONTINUE, "continue", 0) \
116 K(DEBUGGER, "debugger", 0) \
117 K(DEFAULT, "default", 0) \
118 /* DELETE */ \
119 K(DO, "do", 0) \
120 K(ELSE, "else", 0) \
121 K(FINALLY, "finally", 0) \
122 K(FOR, "for", 0) \
123 K(FUNCTION, "function", 0) \
124 K(IF, "if", 0) \
125 /* IN */ \
126 /* INSTANCEOF */ \
127 K(NEW, "new", 0) \
128 K(RETURN, "return", 0) \
129 K(SWITCH, "switch", 0) \
130 K(THIS, "this", 0) \
131 K(THROW, "throw", 0) \
132 K(TRY, "try", 0) \
133 /* TYPEOF */ \
134 K(VAR, "var", 0) \
135 /* VOID */ \
136 K(WHILE, "while", 0) \
137 K(WITH, "with", 0) \
138 \
139 /* Literals (ECMA-262, section 7.8, page 16). */ \
140 K(NULL_LITERAL, "null", 0) \
141 K(TRUE_LITERAL, "true", 0) \
142 K(FALSE_LITERAL, "false", 0) \
143 T(NUMBER, NULL, 0) \
144 T(SMI, NULL, 0) \
145 T(STRING, NULL, 0) \
146 \
147 /* Identifiers (not keywords or future reserved words). */ \
148 T(IDENTIFIER, NULL, 0) \
149 \
150 /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
151 T(FUTURE_RESERVED_WORD, NULL, 0) \
152 T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
153 K(CLASS, "class", 0) \
154 K(CONST, "const", 0) \
155 K(EXPORT, "export", 0) \
156 K(EXTENDS, "extends", 0) \
157 K(IMPORT, "import", 0) \
158 K(LET, "let", 0) \
159 K(STATIC, "static", 0) \
160 K(YIELD, "yield", 0) \
161 K(SUPER, "super", 0) \
162 \
163 /* Illegal token - not able to scan. */ \
164 T(ILLEGAL, "ILLEGAL", 0) \
165 T(ESCAPED_KEYWORD, NULL, 0) \
166 T(ESCAPED_STRICT_RESERVED_WORD, NULL, 0) \
167 \
168 /* Scanner-internal use only. */ \
169 T(WHITESPACE, NULL, 0) \
170 T(UNINITIALIZED, NULL, 0) \
171 \
172 /* ES6 Template Literals */ \
173 T(TEMPLATE_SPAN, NULL, 0) \
174 T(TEMPLATE_TAIL, NULL, 0)
175
176
177class Token {
178 public:
179 // All token values.
180#define T(name, string, precedence) name,
181 enum Value {
182 TOKEN_LIST(T, T)
183 NUM_TOKENS
184 };
185#undef T
186
187 // Returns a string corresponding to the C++ token name
188 // (e.g. "LT" for the token LT).
189 static const char* Name(Value tok) {
190 DCHECK(tok < NUM_TOKENS); // tok is unsigned
191 return name_[tok];
192 }
193
194 // Predicates
195 static bool IsKeyword(Value tok) {
196 return token_type[tok] == 'K';
197 }
198
199 static bool IsIdentifier(Value tok, LanguageMode language_mode,
200 bool is_generator) {
201 switch (tok) {
202 case IDENTIFIER:
203 return true;
204 case ESCAPED_STRICT_RESERVED_WORD:
205 case FUTURE_STRICT_RESERVED_WORD:
206 case LET:
207 case STATIC:
208 return is_sloppy(language_mode);
209 case YIELD:
210 return !is_generator && is_sloppy(language_mode);
211 default:
212 return false;
213 }
214 UNREACHABLE();
215 return false;
216 }
217
218 static bool IsAssignmentOp(Value tok) {
Ben Murdochda12d292016-06-02 14:46:10 +0100219 return INIT <= tok && tok <= ASSIGN_EXP;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 }
221
Ben Murdochda12d292016-06-02 14:46:10 +0100222 static bool IsBinaryOp(Value op) { return COMMA <= op && op <= EXP; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223
224 static bool IsTruncatingBinaryOp(Value op) {
225 return BIT_OR <= op && op <= ROR;
226 }
227
228 static bool IsCompareOp(Value op) {
229 return EQ <= op && op <= IN;
230 }
231
232 static bool IsOrderedRelationalCompareOp(Value op) {
233 return op == LT || op == LTE || op == GT || op == GTE;
234 }
235
236 static bool IsEqualityOp(Value op) {
237 return op == EQ || op == EQ_STRICT;
238 }
239
240 static bool IsInequalityOp(Value op) {
241 return op == NE || op == NE_STRICT;
242 }
243
244 static bool IsArithmeticCompareOp(Value op) {
245 return IsOrderedRelationalCompareOp(op) ||
246 IsEqualityOp(op) || IsInequalityOp(op);
247 }
248
249 static Value NegateCompareOp(Value op) {
250 DCHECK(IsArithmeticCompareOp(op));
251 switch (op) {
252 case EQ: return NE;
253 case NE: return EQ;
254 case EQ_STRICT: return NE_STRICT;
255 case NE_STRICT: return EQ_STRICT;
256 case LT: return GTE;
257 case GT: return LTE;
258 case LTE: return GT;
259 case GTE: return LT;
260 default:
261 UNREACHABLE();
262 return op;
263 }
264 }
265
266 static Value ReverseCompareOp(Value op) {
267 DCHECK(IsArithmeticCompareOp(op));
268 switch (op) {
269 case EQ: return EQ;
270 case NE: return NE;
271 case EQ_STRICT: return EQ_STRICT;
272 case NE_STRICT: return NE_STRICT;
273 case LT: return GT;
274 case GT: return LT;
275 case LTE: return GTE;
276 case GTE: return LTE;
277 default:
278 UNREACHABLE();
279 return op;
280 }
281 }
282
Ben Murdoch097c5b22016-05-18 11:27:45 +0100283 static bool EvalComparison(Value op, double op1, double op2) {
284 DCHECK(IsArithmeticCompareOp(op));
285 switch (op) {
286 case Token::EQ:
287 case Token::EQ_STRICT: return (op1 == op2);
288 case Token::NE: return (op1 != op2);
289 case Token::LT: return (op1 < op2);
290 case Token::GT: return (op1 > op2);
291 case Token::LTE: return (op1 <= op2);
292 case Token::GTE: return (op1 >= op2);
293 default:
294 UNREACHABLE();
295 return false;
296 }
297 }
298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 static bool IsBitOp(Value op) {
300 return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
301 }
302
303 static bool IsUnaryOp(Value op) {
304 return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
305 }
306
307 static bool IsCountOp(Value op) {
308 return op == INC || op == DEC;
309 }
310
311 static bool IsShiftOp(Value op) {
312 return (SHL <= op) && (op <= SHR);
313 }
314
315 // Returns a string corresponding to the JS token string
316 // (.e., "<" for the token LT) or NULL if the token doesn't
317 // have a (unique) string (e.g. an IDENTIFIER).
318 static const char* String(Value tok) {
319 DCHECK(tok < NUM_TOKENS); // tok is unsigned.
320 return string_[tok];
321 }
322
323 // Returns the precedence > 0 for binary and compare
324 // operators; returns 0 otherwise.
325 static int Precedence(Value tok) {
326 DCHECK(tok < NUM_TOKENS); // tok is unsigned.
327 return precedence_[tok];
328 }
329
330 private:
331 static const char* const name_[NUM_TOKENS];
332 static const char* const string_[NUM_TOKENS];
333 static const int8_t precedence_[NUM_TOKENS];
334 static const char token_type[NUM_TOKENS];
335};
336
337} // namespace internal
338} // namespace v8
339
340#endif // V8_PARSING_TOKEN_H_