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