Chromium Code Reviews| 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; | |
|
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...) 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, |
|
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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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 |