OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 63 matching lines...) Loading... | |
74 // typedef PropertyList; | 74 // typedef PropertyList; |
75 // // For constructing objects returned by the traversing functions. | 75 // // For constructing objects returned by the traversing functions. |
76 // typedef Factory; | 76 // typedef Factory; |
77 // }; | 77 // }; |
78 // // ... | 78 // // ... |
79 // }; | 79 // }; |
80 | 80 |
81 template <typename Traits> | 81 template <typename Traits> |
82 class ParserBase : public Traits { | 82 class ParserBase : public Traits { |
83 public: | 83 public: |
84 // Shorten type names defined by Traits. | |
85 typedef typename Traits::Type::Expression ExpressionT; | |
marja
2014/03/18 16:01:06
Had to use ExpressionT. If this is Expression ever
| |
86 typedef typename Traits::Type::Identifier IdentifierT; | |
87 | |
84 ParserBase(Scanner* scanner, uintptr_t stack_limit, | 88 ParserBase(Scanner* scanner, uintptr_t stack_limit, |
85 v8::Extension* extension, | 89 v8::Extension* extension, |
86 typename Traits::Type::Zone* zone, | 90 typename Traits::Type::Zone* zone, |
87 typename Traits::Type::Parser this_object) | 91 typename Traits::Type::Parser this_object) |
88 : Traits(this_object), | 92 : Traits(this_object), |
89 parenthesized_function_(false), | 93 parenthesized_function_(false), |
90 scope_(NULL), | 94 scope_(NULL), |
91 function_state_(NULL), | 95 function_state_(NULL), |
92 extension_(extension), | 96 extension_(extension), |
93 fni_(NULL), | 97 fni_(NULL), |
(...skipping 262 matching lines...) Loading... | |
356 | 360 |
357 void ReportUnexpectedToken(Token::Value token); | 361 void ReportUnexpectedToken(Token::Value token); |
358 | 362 |
359 // Recursive descent functions: | 363 // Recursive descent functions: |
360 | 364 |
361 // Parses an identifier that is valid for the current scope, in particular it | 365 // Parses an identifier that is valid for the current scope, in particular it |
362 // fails on strict mode future reserved keywords in a strict scope. If | 366 // fails on strict mode future reserved keywords in a strict scope. If |
363 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 367 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
364 // "arguments" as identifier even in strict mode (this is needed in cases like | 368 // "arguments" as identifier even in strict mode (this is needed in cases like |
365 // "var foo = eval;"). | 369 // "var foo = eval;"). |
366 typename Traits::Type::Identifier ParseIdentifier( | 370 IdentifierT ParseIdentifier( |
367 AllowEvalOrArgumentsAsIdentifier, | 371 AllowEvalOrArgumentsAsIdentifier, |
368 bool* ok); | 372 bool* ok); |
369 // Parses an identifier or a strict mode future reserved word, and indicate | 373 // Parses an identifier or a strict mode future reserved word, and indicate |
370 // whether it is strict mode future reserved. | 374 // whether it is strict mode future reserved. |
371 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord( | 375 IdentifierT ParseIdentifierOrStrictReservedWord( |
372 bool* is_strict_reserved, | 376 bool* is_strict_reserved, |
373 bool* ok); | 377 bool* ok); |
374 typename Traits::Type::Identifier ParseIdentifierName(bool* ok); | 378 IdentifierT ParseIdentifierName(bool* ok); |
375 // Parses an identifier and determines whether or not it is 'get' or 'set'. | 379 // Parses an identifier and determines whether or not it is 'get' or 'set'. |
376 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, | 380 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, |
377 bool* is_set, | 381 bool* is_set, |
378 bool* ok); | 382 bool* ok); |
379 | 383 |
380 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, | 384 ExpressionT ParseRegExpLiteral(bool seen_equal, |
Michael Starzinger
2014/03/18 16:12:48
nit: Several occurrences here (above and below) sh
marja
2014/03/18 16:17:39
Done.
| |
381 bool* ok); | 385 bool* ok); |
382 | 386 |
383 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok); | 387 ExpressionT ParsePrimaryExpression(bool* ok); |
384 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok); | 388 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
385 typename Traits::Type::Expression ParseArrayLiteral(bool* ok); | 389 ExpressionT ParseArrayLiteral(bool* ok); |
386 typename Traits::Type::Expression ParseObjectLiteral(bool* ok); | 390 ExpressionT ParseObjectLiteral(bool* ok); |
387 typename Traits::Type::ExpressionList ParseArguments(bool* ok); | 391 typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
388 typename Traits::Type::Expression ParseAssignmentExpression(bool accept_IN, | 392 ExpressionT ParseAssignmentExpression(bool accept_IN, |
389 bool* ok); | 393 bool* ok); |
390 typename Traits::Type::Expression ParseYieldExpression(bool* ok); | 394 ExpressionT ParseYieldExpression(bool* ok); |
391 typename Traits::Type::Expression ParseConditionalExpression(bool accept_IN, | 395 ExpressionT ParseConditionalExpression(bool accept_IN, |
392 bool* ok); | 396 bool* ok); |
393 typename Traits::Type::Expression ParseBinaryExpression(int prec, | 397 ExpressionT ParseBinaryExpression(int prec, |
394 bool accept_IN, | 398 bool accept_IN, |
395 bool* ok); | 399 bool* ok); |
396 | 400 |
397 // Used to detect duplicates in object literals. Each of the values | 401 // Used to detect duplicates in object literals. Each of the values |
398 // kGetterProperty, kSetterProperty and kValueProperty represents | 402 // kGetterProperty, kSetterProperty and kValueProperty represents |
399 // a type of object literal property. When parsing a property, its | 403 // a type of object literal property. When parsing a property, its |
400 // type value is stored in the DuplicateFinder for the property name. | 404 // type value is stored in the DuplicateFinder for the property name. |
401 // Values are chosen so that having intersection bits means the there is | 405 // Values are chosen so that having intersection bits means the there is |
402 // an incompatibility. | 406 // an incompatibility. |
403 // I.e., you can add a getter to a property that already has a setter, since | 407 // I.e., you can add a getter to a property that already has a setter, since |
404 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | 408 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
405 // already has a getter or a value. Adding the getter to an existing | 409 // already has a getter or a value. Adding the getter to an existing |
(...skipping 766 matching lines...) Loading... | |
1172 default: | 1176 default: |
1173 const char* name = Token::String(token); | 1177 const char* name = Token::String(token); |
1174 ASSERT(name != NULL); | 1178 ASSERT(name != NULL); |
1175 Traits::ReportMessageAt( | 1179 Traits::ReportMessageAt( |
1176 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | 1180 source_location, "unexpected_token", Vector<const char*>(&name, 1)); |
1177 } | 1181 } |
1178 } | 1182 } |
1179 | 1183 |
1180 | 1184 |
1181 template<class Traits> | 1185 template<class Traits> |
1182 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( | 1186 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
1183 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 1187 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
1184 bool* ok) { | 1188 bool* ok) { |
1185 Token::Value next = Next(); | 1189 Token::Value next = Next(); |
1186 if (next == Token::IDENTIFIER) { | 1190 if (next == Token::IDENTIFIER) { |
1187 typename Traits::Type::Identifier name = this->GetSymbol(scanner()); | 1191 IdentifierT name = this->GetSymbol(scanner()); |
1188 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 1192 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
1189 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { | 1193 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { |
1190 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | 1194 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); |
1191 *ok = false; | 1195 *ok = false; |
1192 } | 1196 } |
1193 return name; | 1197 return name; |
1194 } else if (strict_mode() == SLOPPY && | 1198 } else if (strict_mode() == SLOPPY && |
1195 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1199 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1196 (next == Token::YIELD && !is_generator()))) { | 1200 (next == Token::YIELD && !is_generator()))) { |
1197 return this->GetSymbol(scanner()); | 1201 return this->GetSymbol(scanner()); |
1198 } else { | 1202 } else { |
1199 this->ReportUnexpectedToken(next); | 1203 this->ReportUnexpectedToken(next); |
1200 *ok = false; | 1204 *ok = false; |
1201 return Traits::EmptyIdentifier(); | 1205 return Traits::EmptyIdentifier(); |
1202 } | 1206 } |
1203 } | 1207 } |
1204 | 1208 |
1205 | 1209 |
1206 template <class Traits> | 1210 template <class Traits> |
1207 typename Traits::Type::Identifier ParserBase< | 1211 typename ParserBase<Traits>::IdentifierT ParserBase< |
1208 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | 1212 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
1209 bool* ok) { | 1213 bool* ok) { |
1210 Token::Value next = Next(); | 1214 Token::Value next = Next(); |
1211 if (next == Token::IDENTIFIER) { | 1215 if (next == Token::IDENTIFIER) { |
1212 *is_strict_reserved = false; | 1216 *is_strict_reserved = false; |
1213 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1217 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1214 (next == Token::YIELD && !this->is_generator())) { | 1218 (next == Token::YIELD && !this->is_generator())) { |
1215 *is_strict_reserved = true; | 1219 *is_strict_reserved = true; |
1216 } else { | 1220 } else { |
1217 ReportUnexpectedToken(next); | 1221 ReportUnexpectedToken(next); |
1218 *ok = false; | 1222 *ok = false; |
1219 return Traits::EmptyIdentifier(); | 1223 return Traits::EmptyIdentifier(); |
1220 } | 1224 } |
1221 return this->GetSymbol(scanner()); | 1225 return this->GetSymbol(scanner()); |
1222 } | 1226 } |
1223 | 1227 |
1224 | 1228 |
1225 template <class Traits> | 1229 template <class Traits> |
1226 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName( | 1230 typename ParserBase<Traits>::IdentifierT |
1227 bool* ok) { | 1231 ParserBase<Traits>::ParseIdentifierName(bool* ok) { |
1228 Token::Value next = Next(); | 1232 Token::Value next = Next(); |
1229 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | 1233 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && |
1230 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | 1234 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { |
1231 this->ReportUnexpectedToken(next); | 1235 this->ReportUnexpectedToken(next); |
1232 *ok = false; | 1236 *ok = false; |
1233 return Traits::EmptyIdentifier(); | 1237 return Traits::EmptyIdentifier(); |
1234 } | 1238 } |
1235 return this->GetSymbol(scanner()); | 1239 return this->GetSymbol(scanner()); |
1236 } | 1240 } |
1237 | 1241 |
1238 | 1242 |
1239 template <class Traits> | 1243 template <class Traits> |
1240 typename Traits::Type::Identifier | 1244 typename ParserBase<Traits>::IdentifierT |
1241 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | 1245 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, |
1242 bool* is_set, | 1246 bool* is_set, |
1243 bool* ok) { | 1247 bool* ok) { |
1244 typename Traits::Type::Identifier result = ParseIdentifierName(ok); | 1248 IdentifierT result = ParseIdentifierName(ok); |
1245 if (!*ok) return Traits::EmptyIdentifier(); | 1249 if (!*ok) return Traits::EmptyIdentifier(); |
1246 scanner()->IsGetOrSet(is_get, is_set); | 1250 scanner()->IsGetOrSet(is_get, is_set); |
1247 return result; | 1251 return result; |
1248 } | 1252 } |
1249 | 1253 |
1250 | 1254 |
1251 template <class Traits> | 1255 template <class Traits> |
1252 typename Traits::Type::Expression | 1256 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( |
1253 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { | 1257 bool seen_equal, bool* ok) { |
1254 int pos = peek_position(); | 1258 int pos = peek_position(); |
1255 if (!scanner()->ScanRegExpPattern(seen_equal)) { | 1259 if (!scanner()->ScanRegExpPattern(seen_equal)) { |
1256 Next(); | 1260 Next(); |
1257 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | 1261 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); |
1258 *ok = false; | 1262 *ok = false; |
1259 return Traits::EmptyExpression(); | 1263 return Traits::EmptyExpression(); |
1260 } | 1264 } |
1261 | 1265 |
1262 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 1266 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
1263 | 1267 |
1264 typename Traits::Type::Identifier js_pattern = | 1268 IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED); |
1265 this->NextLiteralString(scanner(), TENURED); | |
1266 if (!scanner()->ScanRegExpFlags()) { | 1269 if (!scanner()->ScanRegExpFlags()) { |
1267 Next(); | 1270 Next(); |
1268 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); | 1271 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); |
1269 *ok = false; | 1272 *ok = false; |
1270 return Traits::EmptyExpression(); | 1273 return Traits::EmptyExpression(); |
1271 } | 1274 } |
1272 typename Traits::Type::Identifier js_flags = | 1275 IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED); |
1273 this->NextLiteralString(scanner(), TENURED); | |
1274 Next(); | 1276 Next(); |
1275 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | 1277 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); |
1276 } | 1278 } |
1277 | 1279 |
1278 | 1280 |
1279 #define CHECK_OK ok); \ | 1281 #define CHECK_OK ok); \ |
1280 if (!*ok) return this->EmptyExpression(); \ | 1282 if (!*ok) return this->EmptyExpression(); \ |
1281 ((void)0 | 1283 ((void)0 |
1282 #define DUMMY ) // to make indentation work | 1284 #define DUMMY ) // to make indentation work |
1283 #undef DUMMY | 1285 #undef DUMMY |
1284 | 1286 |
1285 // Used in functions where the return type is not Traits::Type::Expression. | 1287 // Used in functions where the return type is not ExpressionT. |
1286 #define CHECK_OK_CUSTOM(x) ok); \ | 1288 #define CHECK_OK_CUSTOM(x) ok); \ |
1287 if (!*ok) return this->x(); \ | 1289 if (!*ok) return this->x(); \ |
1288 ((void)0 | 1290 ((void)0 |
1289 #define DUMMY ) // to make indentation work | 1291 #define DUMMY ) // to make indentation work |
1290 #undef DUMMY | 1292 #undef DUMMY |
1291 | 1293 |
1292 template <class Traits> | 1294 template <class Traits> |
1293 typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression( | 1295 typename ParserBase<Traits>::ExpressionT |
1294 bool* ok) { | 1296 ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
1295 // PrimaryExpression :: | 1297 // PrimaryExpression :: |
1296 // 'this' | 1298 // 'this' |
1297 // 'null' | 1299 // 'null' |
1298 // 'true' | 1300 // 'true' |
1299 // 'false' | 1301 // 'false' |
1300 // Identifier | 1302 // Identifier |
1301 // Number | 1303 // Number |
1302 // String | 1304 // String |
1303 // ArrayLiteral | 1305 // ArrayLiteral |
1304 // ObjectLiteral | 1306 // ObjectLiteral |
1305 // RegExpLiteral | 1307 // RegExpLiteral |
1306 // '(' Expression ')' | 1308 // '(' Expression ')' |
1307 | 1309 |
1308 int pos = peek_position(); | 1310 int pos = peek_position(); |
1309 typename Traits::Type::Expression result = this->EmptyExpression(); | 1311 ExpressionT result = this->EmptyExpression(); |
1310 Token::Value token = peek(); | 1312 Token::Value token = peek(); |
1311 switch (token) { | 1313 switch (token) { |
1312 case Token::THIS: { | 1314 case Token::THIS: { |
1313 Consume(Token::THIS); | 1315 Consume(Token::THIS); |
1314 result = this->ThisExpression(scope_, factory()); | 1316 result = this->ThisExpression(scope_, factory()); |
1315 break; | 1317 break; |
1316 } | 1318 } |
1317 | 1319 |
1318 case Token::NULL_LITERAL: | 1320 case Token::NULL_LITERAL: |
1319 case Token::TRUE_LITERAL: | 1321 case Token::TRUE_LITERAL: |
1320 case Token::FALSE_LITERAL: | 1322 case Token::FALSE_LITERAL: |
1321 case Token::NUMBER: | 1323 case Token::NUMBER: |
1322 Next(); | 1324 Next(); |
1323 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); | 1325 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); |
1324 break; | 1326 break; |
1325 | 1327 |
1326 case Token::IDENTIFIER: | 1328 case Token::IDENTIFIER: |
1327 case Token::YIELD: | 1329 case Token::YIELD: |
1328 case Token::FUTURE_STRICT_RESERVED_WORD: { | 1330 case Token::FUTURE_STRICT_RESERVED_WORD: { |
1329 // Using eval or arguments in this context is OK even in strict mode. | 1331 // Using eval or arguments in this context is OK even in strict mode. |
1330 typename Traits::Type::Identifier name = | 1332 IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
1331 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 1333 result = this->ExpressionFromIdentifier(name, pos, scope_, factory()); |
1332 result = | |
1333 this->ExpressionFromIdentifier(name, pos, scope_, factory()); | |
1334 break; | 1334 break; |
1335 } | 1335 } |
1336 | 1336 |
1337 case Token::STRING: { | 1337 case Token::STRING: { |
1338 Consume(Token::STRING); | 1338 Consume(Token::STRING); |
1339 result = this->ExpressionFromString(pos, scanner(), factory()); | 1339 result = this->ExpressionFromString(pos, scanner(), factory()); |
1340 break; | 1340 break; |
1341 } | 1341 } |
1342 | 1342 |
1343 case Token::ASSIGN_DIV: | 1343 case Token::ASSIGN_DIV: |
(...skipping 34 matching lines...) Loading... | |
1378 ReportUnexpectedToken(token); | 1378 ReportUnexpectedToken(token); |
1379 *ok = false; | 1379 *ok = false; |
1380 } | 1380 } |
1381 } | 1381 } |
1382 | 1382 |
1383 return result; | 1383 return result; |
1384 } | 1384 } |
1385 | 1385 |
1386 // Precedence = 1 | 1386 // Precedence = 1 |
1387 template <class Traits> | 1387 template <class Traits> |
1388 typename Traits::Type::Expression ParserBase<Traits>::ParseExpression( | 1388 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
1389 bool accept_IN, bool* ok) { | 1389 bool accept_IN, bool* ok) { |
1390 // Expression :: | 1390 // Expression :: |
1391 // AssignmentExpression | 1391 // AssignmentExpression |
1392 // Expression ',' AssignmentExpression | 1392 // Expression ',' AssignmentExpression |
1393 | 1393 |
1394 typename Traits::Type::Expression result = | 1394 ExpressionT result = this->ParseAssignmentExpression(accept_IN, CHECK_OK); |
1395 this->ParseAssignmentExpression(accept_IN, CHECK_OK); | |
1396 while (peek() == Token::COMMA) { | 1395 while (peek() == Token::COMMA) { |
1397 Expect(Token::COMMA, CHECK_OK); | 1396 Expect(Token::COMMA, CHECK_OK); |
1398 int pos = position(); | 1397 int pos = position(); |
1399 typename Traits::Type::Expression right = | 1398 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); |
1400 this->ParseAssignmentExpression(accept_IN, CHECK_OK); | |
1401 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | 1399 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); |
1402 } | 1400 } |
1403 return result; | 1401 return result; |
1404 } | 1402 } |
1405 | 1403 |
1406 | 1404 |
1407 template <class Traits> | 1405 template <class Traits> |
1408 typename Traits::Type::Expression ParserBase<Traits>::ParseArrayLiteral( | 1406 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
1409 bool* ok) { | 1407 bool* ok) { |
1410 // ArrayLiteral :: | 1408 // ArrayLiteral :: |
1411 // '[' Expression? (',' Expression?)* ']' | 1409 // '[' Expression? (',' Expression?)* ']' |
1412 | 1410 |
1413 int pos = peek_position(); | 1411 int pos = peek_position(); |
1414 typename Traits::Type::ExpressionList values = | 1412 typename Traits::Type::ExpressionList values = |
1415 this->NewExpressionList(4, zone_); | 1413 this->NewExpressionList(4, zone_); |
1416 Expect(Token::LBRACK, CHECK_OK); | 1414 Expect(Token::LBRACK, CHECK_OK); |
1417 while (peek() != Token::RBRACK) { | 1415 while (peek() != Token::RBRACK) { |
1418 typename Traits::Type::Expression elem = this->EmptyExpression(); | 1416 ExpressionT elem = this->EmptyExpression(); |
1419 if (peek() == Token::COMMA) { | 1417 if (peek() == Token::COMMA) { |
1420 elem = this->GetLiteralTheHole(peek_position(), factory()); | 1418 elem = this->GetLiteralTheHole(peek_position(), factory()); |
1421 } else { | 1419 } else { |
1422 elem = this->ParseAssignmentExpression(true, CHECK_OK); | 1420 elem = this->ParseAssignmentExpression(true, CHECK_OK); |
1423 } | 1421 } |
1424 values->Add(elem, zone_); | 1422 values->Add(elem, zone_); |
1425 if (peek() != Token::RBRACK) { | 1423 if (peek() != Token::RBRACK) { |
1426 Expect(Token::COMMA, CHECK_OK); | 1424 Expect(Token::COMMA, CHECK_OK); |
1427 } | 1425 } |
1428 } | 1426 } |
1429 Expect(Token::RBRACK, CHECK_OK); | 1427 Expect(Token::RBRACK, CHECK_OK); |
1430 | 1428 |
1431 // Update the scope information before the pre-parsing bailout. | 1429 // Update the scope information before the pre-parsing bailout. |
1432 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 1430 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
1433 | 1431 |
1434 return factory()->NewArrayLiteral(values, literal_index, pos); | 1432 return factory()->NewArrayLiteral(values, literal_index, pos); |
1435 } | 1433 } |
1436 | 1434 |
1437 | 1435 |
1438 template <class Traits> | 1436 template <class Traits> |
1439 typename Traits::Type::Expression ParserBase<Traits>::ParseObjectLiteral( | 1437 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
1440 bool* ok) { | 1438 bool* ok) { |
1441 // ObjectLiteral :: | 1439 // ObjectLiteral :: |
1442 // '{' (( | 1440 // '{' (( |
1443 // ((IdentifierName | String | Number) ':' AssignmentExpression) | | 1441 // ((IdentifierName | String | Number) ':' AssignmentExpression) | |
1444 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1442 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
1445 // ) ',')* '}' | 1443 // ) ',')* '}' |
1446 // (Except that trailing comma is not required and not allowed.) | 1444 // (Except that trailing comma is not required and not allowed.) |
1447 | 1445 |
1448 int pos = peek_position(); | 1446 int pos = peek_position(); |
1449 typename Traits::Type::PropertyList properties = | 1447 typename Traits::Type::PropertyList properties = |
(...skipping 11 matching lines...) Loading... | |
1461 typename Traits::Type::Literal key = this->EmptyLiteral(); | 1459 typename Traits::Type::Literal key = this->EmptyLiteral(); |
1462 Token::Value next = peek(); | 1460 Token::Value next = peek(); |
1463 int next_pos = peek_position(); | 1461 int next_pos = peek_position(); |
1464 | 1462 |
1465 switch (next) { | 1463 switch (next) { |
1466 case Token::FUTURE_RESERVED_WORD: | 1464 case Token::FUTURE_RESERVED_WORD: |
1467 case Token::FUTURE_STRICT_RESERVED_WORD: | 1465 case Token::FUTURE_STRICT_RESERVED_WORD: |
1468 case Token::IDENTIFIER: { | 1466 case Token::IDENTIFIER: { |
1469 bool is_getter = false; | 1467 bool is_getter = false; |
1470 bool is_setter = false; | 1468 bool is_setter = false; |
1471 typename Traits::Type::Identifier id = | 1469 IdentifierT id = |
1472 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1470 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
1473 if (fni_ != NULL) this->PushLiteralName(fni_, id); | 1471 if (fni_ != NULL) this->PushLiteralName(fni_, id); |
1474 | 1472 |
1475 if ((is_getter || is_setter) && peek() != Token::COLON) { | 1473 if ((is_getter || is_setter) && peek() != Token::COLON) { |
1476 // Special handling of getter and setter syntax: | 1474 // Special handling of getter and setter syntax: |
1477 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 1475 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
1478 // We have already read the "get" or "set" keyword. | 1476 // We have already read the "get" or "set" keyword. |
1479 Token::Value next = Next(); | 1477 Token::Value next = Next(); |
1480 if (next != i::Token::IDENTIFIER && | 1478 if (next != i::Token::IDENTIFIER && |
1481 next != i::Token::FUTURE_RESERVED_WORD && | 1479 next != i::Token::FUTURE_RESERVED_WORD && |
1482 next != i::Token::FUTURE_STRICT_RESERVED_WORD && | 1480 next != i::Token::FUTURE_STRICT_RESERVED_WORD && |
1483 next != i::Token::NUMBER && | 1481 next != i::Token::NUMBER && |
1484 next != i::Token::STRING && | 1482 next != i::Token::STRING && |
1485 !Token::IsKeyword(next)) { | 1483 !Token::IsKeyword(next)) { |
1486 ReportUnexpectedToken(next); | 1484 ReportUnexpectedToken(next); |
1487 *ok = false; | 1485 *ok = false; |
1488 return this->EmptyLiteral(); | 1486 return this->EmptyLiteral(); |
1489 } | 1487 } |
1490 // Validate the property. | 1488 // Validate the property. |
1491 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | 1489 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
1492 checker.CheckProperty(next, type, CHECK_OK); | 1490 checker.CheckProperty(next, type, CHECK_OK); |
1493 typename Traits::Type::Identifier name = this->GetSymbol(scanner_); | 1491 IdentifierT name = this->GetSymbol(scanner_); |
1494 typename Traits::Type::FunctionLiteral value = | 1492 typename Traits::Type::FunctionLiteral value = |
1495 this->ParseFunctionLiteral( | 1493 this->ParseFunctionLiteral( |
1496 name, scanner()->location(), | 1494 name, scanner()->location(), |
1497 false, // reserved words are allowed here | 1495 false, // reserved words are allowed here |
1498 false, // not a generator | 1496 false, // not a generator |
1499 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 1497 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
1500 CHECK_OK); | 1498 CHECK_OK); |
1501 // Allow any number of parameters for compatibilty with JSC. | 1499 // Allow any number of parameters for compatibilty with JSC. |
1502 // Specification only allows zero parameters for get and one for set. | 1500 // Specification only allows zero parameters for get and one for set. |
1503 typename Traits::Type::ObjectLiteralProperty property = | 1501 typename Traits::Type::ObjectLiteralProperty property = |
(...skipping 13 matching lines...) Loading... | |
1517 } | 1515 } |
1518 continue; // restart the while | 1516 continue; // restart the while |
1519 } | 1517 } |
1520 // Failed to parse as get/set property, so it's just a normal property | 1518 // Failed to parse as get/set property, so it's just a normal property |
1521 // (which might be called "get" or "set" or something else). | 1519 // (which might be called "get" or "set" or something else). |
1522 key = factory()->NewLiteral(id, next_pos); | 1520 key = factory()->NewLiteral(id, next_pos); |
1523 break; | 1521 break; |
1524 } | 1522 } |
1525 case Token::STRING: { | 1523 case Token::STRING: { |
1526 Consume(Token::STRING); | 1524 Consume(Token::STRING); |
1527 typename Traits::Type::Identifier string = this->GetSymbol(scanner_); | 1525 IdentifierT string = this->GetSymbol(scanner_); |
1528 if (fni_ != NULL) this->PushLiteralName(fni_, string); | 1526 if (fni_ != NULL) this->PushLiteralName(fni_, string); |
1529 uint32_t index; | 1527 uint32_t index; |
1530 if (this->IsArrayIndex(string, &index)) { | 1528 if (this->IsArrayIndex(string, &index)) { |
1531 key = factory()->NewNumberLiteral(index, next_pos); | 1529 key = factory()->NewNumberLiteral(index, next_pos); |
1532 break; | 1530 break; |
1533 } | 1531 } |
1534 key = factory()->NewLiteral(string, next_pos); | 1532 key = factory()->NewLiteral(string, next_pos); |
1535 break; | 1533 break; |
1536 } | 1534 } |
1537 case Token::NUMBER: { | 1535 case Token::NUMBER: { |
1538 Consume(Token::NUMBER); | 1536 Consume(Token::NUMBER); |
1539 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_, | 1537 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_, |
1540 factory()); | 1538 factory()); |
1541 break; | 1539 break; |
1542 } | 1540 } |
1543 default: | 1541 default: |
1544 if (Token::IsKeyword(next)) { | 1542 if (Token::IsKeyword(next)) { |
1545 Consume(next); | 1543 Consume(next); |
1546 typename Traits::Type::Identifier string = this->GetSymbol(scanner_); | 1544 IdentifierT string = this->GetSymbol(scanner_); |
1547 key = factory()->NewLiteral(string, next_pos); | 1545 key = factory()->NewLiteral(string, next_pos); |
1548 } else { | 1546 } else { |
1549 Token::Value next = Next(); | 1547 Token::Value next = Next(); |
1550 ReportUnexpectedToken(next); | 1548 ReportUnexpectedToken(next); |
1551 *ok = false; | 1549 *ok = false; |
1552 return this->EmptyLiteral(); | 1550 return this->EmptyLiteral(); |
1553 } | 1551 } |
1554 } | 1552 } |
1555 | 1553 |
1556 // Validate the property | 1554 // Validate the property |
1557 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1555 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
1558 | 1556 |
1559 Expect(Token::COLON, CHECK_OK); | 1557 Expect(Token::COLON, CHECK_OK); |
1560 typename Traits::Type::Expression value = | 1558 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); |
1561 this->ParseAssignmentExpression(true, CHECK_OK); | |
1562 | 1559 |
1563 typename Traits::Type::ObjectLiteralProperty property = | 1560 typename Traits::Type::ObjectLiteralProperty property = |
1564 factory()->NewObjectLiteralProperty(key, value); | 1561 factory()->NewObjectLiteralProperty(key, value); |
1565 | 1562 |
1566 // Mark top-level object literals that contain function literals and | 1563 // Mark top-level object literals that contain function literals and |
1567 // pretenure the literal so it can be added as a constant function | 1564 // pretenure the literal so it can be added as a constant function |
1568 // property. (Parser only.) | 1565 // property. (Parser only.) |
1569 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, | 1566 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, |
1570 &has_function); | 1567 &has_function); |
1571 | 1568 |
(...skipping 31 matching lines...) Loading... | |
1603 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( | 1600 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
1604 bool* ok) { | 1601 bool* ok) { |
1605 // Arguments :: | 1602 // Arguments :: |
1606 // '(' (AssignmentExpression)*[','] ')' | 1603 // '(' (AssignmentExpression)*[','] ')' |
1607 | 1604 |
1608 typename Traits::Type::ExpressionList result = | 1605 typename Traits::Type::ExpressionList result = |
1609 this->NewExpressionList(4, zone_); | 1606 this->NewExpressionList(4, zone_); |
1610 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | 1607 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); |
1611 bool done = (peek() == Token::RPAREN); | 1608 bool done = (peek() == Token::RPAREN); |
1612 while (!done) { | 1609 while (!done) { |
1613 typename Traits::Type::Expression argument = | 1610 ExpressionT argument = this->ParseAssignmentExpression( |
1614 this->ParseAssignmentExpression(true, | 1611 true, CHECK_OK_CUSTOM(NullExpressionList)); |
1615 CHECK_OK_CUSTOM(NullExpressionList)); | |
1616 result->Add(argument, zone_); | 1612 result->Add(argument, zone_); |
1617 if (result->length() > Code::kMaxArguments) { | 1613 if (result->length() > Code::kMaxArguments) { |
1618 ReportMessageAt(scanner()->location(), "too_many_arguments"); | 1614 ReportMessageAt(scanner()->location(), "too_many_arguments"); |
1619 *ok = false; | 1615 *ok = false; |
1620 return this->NullExpressionList(); | 1616 return this->NullExpressionList(); |
1621 } | 1617 } |
1622 done = (peek() == Token::RPAREN); | 1618 done = (peek() == Token::RPAREN); |
1623 if (!done) { | 1619 if (!done) { |
1624 // Need {} because of the CHECK_OK_CUSTOM macro. | 1620 // Need {} because of the CHECK_OK_CUSTOM macro. |
1625 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList)); | 1621 Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList)); |
1626 } | 1622 } |
1627 } | 1623 } |
1628 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | 1624 Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList)); |
1629 return result; | 1625 return result; |
1630 } | 1626 } |
1631 | 1627 |
1632 // Precedence = 2 | 1628 // Precedence = 2 |
1633 template <class Traits> | 1629 template <class Traits> |
1634 typename Traits::Type::Expression ParserBase<Traits>::ParseAssignmentExpression( | 1630 typename ParserBase<Traits>::ExpressionT |
1635 bool accept_IN, bool* ok) { | 1631 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
1636 // AssignmentExpression :: | 1632 // AssignmentExpression :: |
1637 // ConditionalExpression | 1633 // ConditionalExpression |
1638 // YieldExpression | 1634 // YieldExpression |
1639 // LeftHandSideExpression AssignmentOperator AssignmentExpression | 1635 // LeftHandSideExpression AssignmentOperator AssignmentExpression |
1640 | 1636 |
1641 Scanner::Location lhs_location = scanner()->peek_location(); | 1637 Scanner::Location lhs_location = scanner()->peek_location(); |
1642 | 1638 |
1643 if (peek() == Token::YIELD && is_generator()) { | 1639 if (peek() == Token::YIELD && is_generator()) { |
1644 return this->ParseYieldExpression(ok); | 1640 return this->ParseYieldExpression(ok); |
1645 } | 1641 } |
1646 | 1642 |
1647 if (fni_ != NULL) fni_->Enter(); | 1643 if (fni_ != NULL) fni_->Enter(); |
1648 typename Traits::Type::Expression expression = | 1644 ExpressionT expression = |
1649 this->ParseConditionalExpression(accept_IN, CHECK_OK); | 1645 this->ParseConditionalExpression(accept_IN, CHECK_OK); |
1650 | 1646 |
1651 if (!Token::IsAssignmentOp(peek())) { | 1647 if (!Token::IsAssignmentOp(peek())) { |
1652 if (fni_ != NULL) fni_->Leave(); | 1648 if (fni_ != NULL) fni_->Leave(); |
1653 // Parsed conditional expression only (no assignment). | 1649 // Parsed conditional expression only (no assignment). |
1654 return expression; | 1650 return expression; |
1655 } | 1651 } |
1656 | 1652 |
1657 if (!this->IsValidLeftHandSide(expression)) { | 1653 if (!this->IsValidLeftHandSide(expression)) { |
1658 this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true); | 1654 this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true); |
1659 *ok = false; | 1655 *ok = false; |
1660 return this->EmptyExpression(); | 1656 return this->EmptyExpression(); |
1661 } | 1657 } |
1662 | 1658 |
1663 if (strict_mode() == STRICT) { | 1659 if (strict_mode() == STRICT) { |
1664 // Assignment to eval or arguments is disallowed in strict mode. | 1660 // Assignment to eval or arguments is disallowed in strict mode. |
1665 this->CheckStrictModeLValue(expression, CHECK_OK); | 1661 this->CheckStrictModeLValue(expression, CHECK_OK); |
1666 } | 1662 } |
1667 expression = this->MarkExpressionAsLValue(expression); | 1663 expression = this->MarkExpressionAsLValue(expression); |
1668 | 1664 |
1669 Token::Value op = Next(); // Get assignment operator. | 1665 Token::Value op = Next(); // Get assignment operator. |
1670 int pos = position(); | 1666 int pos = position(); |
1671 typename Traits::Type::Expression right = | 1667 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); |
1672 this->ParseAssignmentExpression(accept_IN, CHECK_OK); | |
1673 | 1668 |
1674 // TODO(1231235): We try to estimate the set of properties set by | 1669 // TODO(1231235): We try to estimate the set of properties set by |
1675 // constructors. We define a new property whenever there is an | 1670 // constructors. We define a new property whenever there is an |
1676 // assignment to a property of 'this'. We should probably only add | 1671 // assignment to a property of 'this'. We should probably only add |
1677 // properties if we haven't seen them before. Otherwise we'll | 1672 // properties if we haven't seen them before. Otherwise we'll |
1678 // probably overestimate the number of properties. | 1673 // probably overestimate the number of properties. |
1679 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { | 1674 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { |
1680 function_state_->AddProperty(); | 1675 function_state_->AddProperty(); |
1681 } | 1676 } |
1682 | 1677 |
(...skipping 11 matching lines...) Loading... | |
1694 } else { | 1689 } else { |
1695 fni_->RemoveLastFunction(); | 1690 fni_->RemoveLastFunction(); |
1696 } | 1691 } |
1697 fni_->Leave(); | 1692 fni_->Leave(); |
1698 } | 1693 } |
1699 | 1694 |
1700 return factory()->NewAssignment(op, expression, right, pos); | 1695 return factory()->NewAssignment(op, expression, right, pos); |
1701 } | 1696 } |
1702 | 1697 |
1703 template <class Traits> | 1698 template <class Traits> |
1704 typename Traits::Type::Expression ParserBase<Traits>::ParseYieldExpression( | 1699 typename ParserBase<Traits>::ExpressionT |
1705 bool* ok) { | 1700 ParserBase<Traits>::ParseYieldExpression(bool* ok) { |
1706 // YieldExpression :: | 1701 // YieldExpression :: |
1707 // 'yield' '*'? AssignmentExpression | 1702 // 'yield' '*'? AssignmentExpression |
1708 int pos = peek_position(); | 1703 int pos = peek_position(); |
1709 Expect(Token::YIELD, CHECK_OK); | 1704 Expect(Token::YIELD, CHECK_OK); |
1710 Yield::Kind kind = | 1705 Yield::Kind kind = |
1711 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND; | 1706 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND; |
1712 typename Traits::Type::Expression generator_object = | 1707 ExpressionT generator_object = |
1713 factory()->NewVariableProxy(function_state_->generator_object_variable()); | 1708 factory()->NewVariableProxy(function_state_->generator_object_variable()); |
1714 typename Traits::Type::Expression expression = | 1709 ExpressionT expression = |
1715 ParseAssignmentExpression(false, CHECK_OK); | 1710 ParseAssignmentExpression(false, CHECK_OK); |
1716 typename Traits::Type::YieldExpression yield = | 1711 typename Traits::Type::YieldExpression yield = |
1717 factory()->NewYield(generator_object, expression, kind, pos); | 1712 factory()->NewYield(generator_object, expression, kind, pos); |
1718 if (kind == Yield::DELEGATING) { | 1713 if (kind == Yield::DELEGATING) { |
1719 yield->set_index(function_state_->NextHandlerIndex()); | 1714 yield->set_index(function_state_->NextHandlerIndex()); |
1720 } | 1715 } |
1721 return yield; | 1716 return yield; |
1722 } | 1717 } |
1723 | 1718 |
1724 | 1719 |
1725 // Precedence = 3 | 1720 // Precedence = 3 |
1726 template <class Traits> | 1721 template <class Traits> |
1727 typename Traits::Type::Expression | 1722 typename ParserBase<Traits>::ExpressionT |
1728 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) { | 1723 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) { |
1729 // ConditionalExpression :: | 1724 // ConditionalExpression :: |
1730 // LogicalOrExpression | 1725 // LogicalOrExpression |
1731 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression | 1726 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression |
1732 | 1727 |
1733 int pos = peek_position(); | 1728 int pos = peek_position(); |
1734 // We start using the binary expression parser for prec >= 4 only! | 1729 // We start using the binary expression parser for prec >= 4 only! |
1735 typename Traits::Type::Expression expression = | 1730 ExpressionT expression = this->ParseBinaryExpression(4, accept_IN, CHECK_OK); |
1736 this->ParseBinaryExpression(4, accept_IN, CHECK_OK); | |
1737 if (peek() != Token::CONDITIONAL) return expression; | 1731 if (peek() != Token::CONDITIONAL) return expression; |
1738 Consume(Token::CONDITIONAL); | 1732 Consume(Token::CONDITIONAL); |
1739 // In parsing the first assignment expression in conditional | 1733 // In parsing the first assignment expression in conditional |
1740 // expressions we always accept the 'in' keyword; see ECMA-262, | 1734 // expressions we always accept the 'in' keyword; see ECMA-262, |
1741 // section 11.12, page 58. | 1735 // section 11.12, page 58. |
1742 typename Traits::Type::Expression left = | 1736 ExpressionT left = ParseAssignmentExpression(true, CHECK_OK); |
1743 ParseAssignmentExpression(true, CHECK_OK); | |
1744 Expect(Token::COLON, CHECK_OK); | 1737 Expect(Token::COLON, CHECK_OK); |
1745 typename Traits::Type::Expression right = | 1738 ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK); |
1746 ParseAssignmentExpression(accept_IN, CHECK_OK); | |
1747 return factory()->NewConditional(expression, left, right, pos); | 1739 return factory()->NewConditional(expression, left, right, pos); |
1748 } | 1740 } |
1749 | 1741 |
1750 | 1742 |
1751 // Precedence >= 4 | 1743 // Precedence >= 4 |
1752 template <class Traits> | 1744 template <class Traits> |
1753 typename Traits::Type::Expression | 1745 typename ParserBase<Traits>::ExpressionT |
1754 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { | 1746 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) { |
1755 ASSERT(prec >= 4); | 1747 ASSERT(prec >= 4); |
1756 typename Traits::Type::Expression x = this->ParseUnaryExpression(CHECK_OK); | 1748 ExpressionT x = this->ParseUnaryExpression(CHECK_OK); |
1757 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { | 1749 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { |
1758 // prec1 >= 4 | 1750 // prec1 >= 4 |
1759 while (Precedence(peek(), accept_IN) == prec1) { | 1751 while (Precedence(peek(), accept_IN) == prec1) { |
1760 Token::Value op = Next(); | 1752 Token::Value op = Next(); |
1761 int pos = position(); | 1753 int pos = position(); |
1762 typename Traits::Type::Expression y = | 1754 ExpressionT y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); |
1763 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); | |
1764 | 1755 |
1765 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, | 1756 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, |
1766 factory())) { | 1757 factory())) { |
1767 continue; | 1758 continue; |
1768 } | 1759 } |
1769 | 1760 |
1770 // For now we distinguish between comparisons and other binary | 1761 // For now we distinguish between comparisons and other binary |
1771 // operations. (We could combine the two and get rid of this | 1762 // operations. (We could combine the two and get rid of this |
1772 // code and AST node eventually.) | 1763 // code and AST node eventually.) |
1773 if (Token::IsCompareOp(op)) { | 1764 if (Token::IsCompareOp(op)) { |
(...skipping 53 matching lines...) Loading... | |
1827 "accessor_get_set"); | 1818 "accessor_get_set"); |
1828 } | 1819 } |
1829 *ok = false; | 1820 *ok = false; |
1830 } | 1821 } |
1831 } | 1822 } |
1832 | 1823 |
1833 | 1824 |
1834 } } // v8::internal | 1825 } } // v8::internal |
1835 | 1826 |
1836 #endif // V8_PREPARSER_H | 1827 #endif // V8_PREPARSER_H |
OLD | NEW |