1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_TOKEN_H_
6#define RUNTIME_VM_TOKEN_H_
7
8#include "platform/assert.h"
9#include "vm/allocation.h"
10
11namespace dart {
12
13// Operator precedence table
14//
15// 14 multiplicative * / ~/ %
16// 13 additive + -
17// 12 shift << >>
18// 11 bitwise and &
19// 10 bitwise xor ^
20// 9 bitwise or |
21// 8 relational >= > <= < is as
22// 7 equality == != === !==
23// 6 logical and &&
24// 5 logical or ||
25// 4 null check ??
26// 3 conditional ?
27// 2 assignment = *= /= ~/= %= += -= <<= >>= &= ^= |= ??=
28// 1 comma ,
29
30// Token definitions.
31// Some operator tokens appear in blocks, e.g. assignment operators.
32// There is code that depends on the values within a block to be
33// contiguous, and on the order of values.
34#define DART_TOKEN_LIST(TOK) \
35 TOK(kEOS, "", 0, kNoAttribute) \
36 \
37 TOK(kLPAREN, "(", 0, kNoAttribute) \
38 TOK(kRPAREN, ")", 0, kNoAttribute) \
39 TOK(kLBRACK, "[", 0, kNoAttribute) \
40 TOK(kRBRACK, "]", 0, kNoAttribute) \
41 TOK(kLBRACE, "{", 0, kNoAttribute) \
42 TOK(kRBRACE, "}", 0, kNoAttribute) \
43 TOK(kARROW, "=>", 0, kNoAttribute) \
44 TOK(kCOLON, ":", 0, kNoAttribute) \
45 TOK(kSEMICOLON, ";", 0, kNoAttribute) \
46 TOK(kPERIOD, ".", 0, kNoAttribute) \
47 TOK(kQM_PERIOD, "?.", 0, kNoAttribute) \
48 TOK(kINCR, "++", 0, kNoAttribute) \
49 TOK(kDECR, "--", 0, kNoAttribute) \
50 \
51 /* Assignment operators. */ \
52 /* Please update IsAssignmentOperator() if you make */ \
53 /* any changes to this block. */ \
54 TOK(kASSIGN, "=", 2, kNoAttribute) \
55 TOK(kASSIGN_OR, "|=", 2, kNoAttribute) \
56 TOK(kASSIGN_XOR, "^=", 2, kNoAttribute) \
57 TOK(kASSIGN_AND, "&=", 2, kNoAttribute) \
58 TOK(kASSIGN_SHL, "<<=", 2, kNoAttribute) \
59 TOK(kASSIGN_SHR, ">>=", 2, kNoAttribute) \
60 TOK(kASSIGN_ADD, "+=", 2, kNoAttribute) \
61 TOK(kASSIGN_SUB, "-=", 2, kNoAttribute) \
62 TOK(kASSIGN_MUL, "*=", 2, kNoAttribute) \
63 TOK(kASSIGN_TRUNCDIV, "~/=", 2, kNoAttribute) \
64 TOK(kASSIGN_DIV, "/=", 2, kNoAttribute) \
65 TOK(kASSIGN_MOD, "%=", 2, kNoAttribute) \
66 /* Avoid trigraph ??= below. */ \
67 TOK(kASSIGN_COND, "?\?=", 2, kNoAttribute) \
68 \
69 TOK(kCASCADE, "..", 2, kNoAttribute) \
70 \
71 TOK(kCOMMA, ",", 1, kNoAttribute) \
72 TOK(kOR, "||", 5, kNoAttribute) \
73 TOK(kAND, "&&", 6, kNoAttribute) \
74 TOK(kBIT_OR, "|", 9, kNoAttribute) \
75 TOK(kBIT_XOR, "^", 10, kNoAttribute) \
76 TOK(kBIT_AND, "&", 11, kNoAttribute) \
77 TOK(kBIT_NOT, "~", 0, kNoAttribute) \
78 \
79 /* Shift operators. */ \
80 TOK(kSHL, "<<", 12, kNoAttribute) \
81 TOK(kSHR, ">>", 12, kNoAttribute) \
82 \
83 /* Additive operators. */ \
84 TOK(kADD, "+", 13, kNoAttribute) \
85 TOK(kSUB, "-", 13, kNoAttribute) \
86 \
87 /* Multiplicative operators */ \
88 TOK(kMUL, "*", 14, kNoAttribute) \
89 TOK(kDIV, "/", 14, kNoAttribute) \
90 TOK(kTRUNCDIV, "~/", 14, kNoAttribute) \
91 TOK(kMOD, "%", 14, kNoAttribute) \
92 \
93 TOK(kNOT, "!", 0, kNoAttribute) \
94 TOK(kCONDITIONAL, "?", 3, kNoAttribute) \
95 TOK(kIFNULL, "??", 4, kNoAttribute) \
96 \
97 /* Equality operators. */ \
98 /* Please update IsEqualityOperator() if you make */ \
99 /* any changes to this block. */ \
100 TOK(kEQ, "==", 7, kNoAttribute) \
101 TOK(kNE, "!=", 7, kNoAttribute) \
102 TOK(kEQ_STRICT, "===", 7, kNoAttribute) \
103 TOK(kNE_STRICT, "!==", 7, kNoAttribute) \
104 \
105 /* Relational operators. */ \
106 /* Please update IsRelationalOperator() if you make */ \
107 /* any changes to this block. */ \
108 TOK(kLT, "<", 8, kNoAttribute) \
109 TOK(kGT, ">", 8, kNoAttribute) \
110 TOK(kLTE, "<=", 8, kNoAttribute) \
111 TOK(kGTE, ">=", 8, kNoAttribute) \
112 \
113 /* Internal token for !(expr is Type) negative type test operator */ \
114 TOK(kISNOT, "", 11, kNoAttribute) \
115 \
116 TOK(kINDEX, "[]", 0, kNoAttribute) \
117 TOK(kASSIGN_INDEX, "[]=", 0, kNoAttribute) \
118 TOK(kNEGATE, "unary-", 0, kNoAttribute) \
119 \
120 TOK(kIDENT, "", 0, kNoAttribute) \
121 TOK(kSTRING, "", 0, kNoAttribute) \
122 TOK(kINTEGER, "", 0, kNoAttribute) \
123 TOK(kDOUBLE, "", 0, kNoAttribute) \
124 \
125 TOK(kINTERPOL_VAR, "$", 0, kNoAttribute) \
126 TOK(kINTERPOL_START, "${", 0, kNoAttribute) \
127 TOK(kINTERPOL_END, "}", 0, kNoAttribute) \
128 \
129 TOK(kAT, "@", 0, kNoAttribute) \
130 TOK(kHASH, "#", 0, kNoAttribute) \
131 \
132 TOK(kNEWLINE, "\n", 0, kNoAttribute) \
133 TOK(kWHITESP, "", 0, kNoAttribute) \
134 TOK(kERROR, "", 0, kNoAttribute) \
135 TOK(kILLEGAL, "", 0, kNoAttribute) \
136 \
137 /* Support for Dart scripts. */ \
138 TOK(kSCRIPTTAG, "#!", 0, kNoAttribute) \
139 \
140 /* Support for optimized code */ \
141 TOK(kREM, "", 0, kNoAttribute)
142
143// List of keywords. The list must be alphabetically ordered. The
144// keyword recognition code depends on the ordering.
145// If you add a keyword at the beginning or end of this list, make sure
146// to update kFirstKeyword and kLastKeyword below.
147#define DART_KEYWORD_LIST(KW) \
148 KW(kABSTRACT, "abstract", 0, kPseudoKeyword) /* == kFirstKeyword */ \
149 KW(kAS, "as", 11, kPseudoKeyword) \
150 KW(kASSERT, "assert", 0, kKeyword) \
151 KW(kBREAK, "break", 0, kKeyword) \
152 KW(kCASE, "case", 0, kKeyword) \
153 KW(kCATCH, "catch", 0, kKeyword) \
154 KW(kCLASS, "class", 0, kKeyword) \
155 KW(kCONST, "const", 0, kKeyword) \
156 KW(kCONTINUE, "continue", 0, kKeyword) \
157 KW(kCOVARIANT, "covariant", 0, kPseudoKeyword) \
158 KW(kDEFAULT, "default", 0, kKeyword) \
159 KW(kDEFERRED, "deferred", 0, kPseudoKeyword) \
160 KW(kDO, "do", 0, kKeyword) \
161 KW(kELSE, "else", 0, kKeyword) \
162 KW(kENUM, "enum", 0, kKeyword) \
163 KW(kEXPORT, "export", 0, kPseudoKeyword) \
164 KW(kEXTENDS, "extends", 0, kKeyword) \
165 KW(kEXTERNAL, "external", 0, kPseudoKeyword) \
166 KW(kFACTORY, "factory", 0, kPseudoKeyword) \
167 KW(kFALSE, "false", 0, kKeyword) \
168 KW(kFINAL, "final", 0, kKeyword) \
169 KW(kFINALLY, "finally", 0, kKeyword) \
170 KW(kFOR, "for", 0, kKeyword) \
171 KW(kGET, "get", 0, kPseudoKeyword) \
172 KW(kIF, "if", 0, kKeyword) \
173 KW(kIMPLEMENTS, "implements", 0, kPseudoKeyword) \
174 KW(kIMPORT, "import", 0, kPseudoKeyword) \
175 KW(kIN, "in", 0, kKeyword) \
176 KW(kIS, "is", 11, kKeyword) \
177 KW(kLIBRARY, "library", 0, kPseudoKeyword) \
178 KW(kNEW, "new", 0, kKeyword) \
179 KW(kNULL, "null", 0, kKeyword) \
180 KW(kOPERATOR, "operator", 0, kPseudoKeyword) \
181 KW(kPART, "part", 0, kPseudoKeyword) \
182 KW(kRETHROW, "rethrow", 0, kKeyword) \
183 KW(kRETURN, "return", 0, kKeyword) \
184 KW(kSET, "set", 0, kPseudoKeyword) \
185 KW(kSTATIC, "static", 0, kPseudoKeyword) \
186 KW(kSUPER, "super", 0, kKeyword) \
187 KW(kSWITCH, "switch", 0, kKeyword) \
188 KW(kTHIS, "this", 0, kKeyword) \
189 KW(kTHROW, "throw", 0, kKeyword) \
190 KW(kTRUE, "true", 0, kKeyword) \
191 KW(kTRY, "try", 0, kKeyword) \
192 KW(kTYPEDEF, "typedef", 0, kPseudoKeyword) \
193 KW(kVAR, "var", 0, kKeyword) \
194 KW(kVOID, "void", 0, kKeyword) \
195 KW(kWHILE, "while", 0, kKeyword) \
196 KW(kWITH, "with", 0, kKeyword) /* == kLastKeyword */
197
198class String;
199
200class Token {
201 public:
202#define T(t, s, p, a) t,
203 enum Kind { DART_TOKEN_LIST(T) DART_KEYWORD_LIST(T) kNumTokens };
204#undef T
205
206 enum Attribute {
207 kNoAttribute = 0,
208 kKeyword = 1 << 0,
209 kPseudoKeyword = 1 << 1,
210 };
211
212 static const Kind kFirstKeyword = kABSTRACT;
213 static const Kind kLastKeyword = kWITH;
214 static const int kNumKeywords = kLastKeyword - kFirstKeyword + 1;
215
216 static bool IsAssignmentOperator(Kind tok) {
217 return kASSIGN <= tok && tok <= kASSIGN_COND;
218 }
219
220 static bool IsRelationalOperator(Kind tok) {
221 return kLT <= tok && tok <= kGTE;
222 }
223
224 static bool IsEqualityOperator(Kind tok) {
225 return kEQ <= tok && tok <= kNE_STRICT;
226 }
227
228 static bool IsStrictEqualityOperator(Kind tok) {
229 return (tok == kEQ_STRICT) || (tok == kNE_STRICT);
230 }
231
232 static bool IsTypeTestOperator(Kind tok) {
233 return (tok == kIS) || (tok == kISNOT);
234 }
235
236 static bool IsTypeCastOperator(Kind tok) { return tok == kAS; }
237
238 static bool IsIndexOperator(Kind tok) {
239 return tok == kINDEX || tok == kASSIGN_INDEX;
240 }
241
242 static bool IsPseudoKeyword(Kind tok) {
243 return (Attributes(tok) & kPseudoKeyword) != 0;
244 }
245
246 static bool IsKeyword(Kind tok) { return (Attributes(tok) & kKeyword) != 0; }
247
248 static bool IsIdentifier(Kind tok) {
249 return (tok == kIDENT) || IsPseudoKeyword(tok);
250 }
251
252 static const char* Name(Kind tok) {
253 ASSERT(tok < kNumTokens);
254 return name_[tok];
255 }
256
257 static const char* Str(Kind tok) {
258 ASSERT(tok < kNumTokens);
259 return tok_str_[tok];
260 }
261
262 static bool FromStr(const char* str, Kind* out) {
263 ASSERT(str != nullptr && out != nullptr);
264#define TOK_CASE(t, s, p, a) \
265 if (strcmp(str, tok_str_[(t)]) == 0) { \
266 *out = (t); \
267 return true; \
268 }
269 DART_TOKEN_LIST(TOK_CASE)
270 DART_KEYWORD_LIST(TOK_CASE)
271#undef TOK_CASE
272 return false;
273 }
274
275 static int Precedence(Kind tok) {
276 ASSERT(tok < kNumTokens);
277 return precedence_[tok];
278 }
279
280 static Attribute Attributes(Kind tok) {
281 ASSERT(tok < kNumTokens);
282 return attributes_[tok];
283 }
284
285 static bool CanBeOverloaded(Kind tok) {
286 ASSERT(tok < kNumTokens);
287 return IsRelationalOperator(tok) || (tok == kEQ) ||
288 (tok >= kADD && tok <= kMOD) || // Arithmetic operations.
289 (tok >= kBIT_OR && tok <= kSHR) || // Bit operations.
290 (tok == kINDEX) || (tok == kASSIGN_INDEX);
291 }
292
293 static bool NeedsLiteralToken(Kind tok) {
294 ASSERT(tok < kNumTokens);
295 return ((tok == Token::kINTEGER) || (tok == Token::kSTRING) ||
296 (tok == Token::kINTERPOL_VAR) || (tok == Token::kERROR) ||
297 (tok == Token::kDOUBLE));
298 }
299
300 static bool IsBinaryOperator(Token::Kind token);
301 static bool IsUnaryOperator(Token::Kind token);
302
303 static bool IsBinaryArithmeticOperator(Token::Kind token);
304 static bool IsUnaryArithmeticOperator(Token::Kind token);
305
306 static bool IsBinaryBitwiseOperator(Token::Kind token);
307
308 // For a comparison operation return an operation for the negated comparison:
309 // !(a (op) b) === a (op') b
310 static Token::Kind NegateComparison(Token::Kind op) {
311 switch (op) {
312 case Token::kEQ:
313 return Token::kNE;
314 case Token::kNE:
315 return Token::kEQ;
316 case Token::kLT:
317 return Token::kGTE;
318 case Token::kGT:
319 return Token::kLTE;
320 case Token::kLTE:
321 return Token::kGT;
322 case Token::kGTE:
323 return Token::kLT;
324 case Token::kEQ_STRICT:
325 return Token::kNE_STRICT;
326 case Token::kNE_STRICT:
327 return Token::kEQ_STRICT;
328 case Token::kIS:
329 return Token::kISNOT;
330 case Token::kISNOT:
331 return Token::kIS;
332 default:
333 UNREACHABLE();
334 return Token::kILLEGAL;
335 }
336 }
337
338 // For a comparison operation return an operation for the equivalent flipped
339 // comparison: a (op) b === b (op') a.
340 static Token::Kind FlipComparison(Token::Kind op) {
341 switch (op) {
342 case Token::kEQ:
343 return Token::kEQ;
344 case Token::kNE:
345 return Token::kNE;
346 case Token::kLT:
347 return Token::kGT;
348 case Token::kGT:
349 return Token::kLT;
350 case Token::kLTE:
351 return Token::kGTE;
352 case Token::kGTE:
353 return Token::kLTE;
354 case Token::kEQ_STRICT:
355 return Token::kEQ_STRICT;
356 case Token::kNE_STRICT:
357 return Token::kNE_STRICT;
358 default:
359 UNREACHABLE();
360 return Token::kILLEGAL;
361 }
362 }
363
364 private:
365 static const char* name_[];
366 static const char* tok_str_[];
367 static const uint8_t precedence_[];
368 static const Attribute attributes_[];
369};
370
371} // namespace dart
372
373#endif // RUNTIME_VM_TOKEN_H_
374