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 | |
11 | namespace 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 | |
198 | class String; |
199 | |
200 | class 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 | |