OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "func-name-inferrer.h" | 8 #include "func-name-inferrer.h" |
9 #include "hashmap.h" | 9 #include "hashmap.h" |
10 #include "scopes.h" | 10 #include "scopes.h" |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 *ok = false; | 320 *ok = false; |
321 } | 321 } |
322 } | 322 } |
323 | 323 |
324 // Checks whether an octal literal was last seen between beg_pos and end_pos. | 324 // Checks whether an octal literal was last seen between beg_pos and end_pos. |
325 // If so, reports an error. Only called for strict mode. | 325 // If so, reports an error. Only called for strict mode. |
326 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { | 326 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
327 Scanner::Location octal = scanner()->octal_position(); | 327 Scanner::Location octal = scanner()->octal_position(); |
328 if (octal.IsValid() && beg_pos <= octal.beg_pos && | 328 if (octal.IsValid() && beg_pos <= octal.beg_pos && |
329 octal.end_pos <= end_pos) { | 329 octal.end_pos <= end_pos) { |
330 ReportMessageAt(octal, "strict_octal_literal"); | 330 this->ReportMessageAt(octal, "strict_octal_literal"); |
331 scanner()->clear_octal_position(); | 331 scanner()->clear_octal_position(); |
332 *ok = false; | 332 *ok = false; |
333 } | 333 } |
334 } | 334 } |
335 | 335 |
336 // Determine precedence of given token. | 336 // Determine precedence of given token. |
337 static int Precedence(Token::Value token, bool accept_IN) { | 337 static int Precedence(Token::Value token, bool accept_IN) { |
338 if (token == Token::IN && !accept_IN) | 338 if (token == Token::IN && !accept_IN) |
339 return 0; // 0 precedence will terminate binary expression parsing | 339 return 0; // 0 precedence will terminate binary expression parsing |
340 return Token::Precedence(token); | 340 return Token::Precedence(token); |
341 } | 341 } |
342 | 342 |
343 typename Traits::Type::Factory* factory() { | 343 typename Traits::Type::Factory* factory() { |
344 return function_state_->factory(); | 344 return function_state_->factory(); |
345 } | 345 } |
346 | 346 |
347 StrictMode strict_mode() { return scope_->strict_mode(); } | 347 StrictMode strict_mode() { return scope_->strict_mode(); } |
348 bool is_generator() const { return function_state_->is_generator(); } | 348 bool is_generator() const { return function_state_->is_generator(); } |
349 | 349 |
350 // Report syntax errors. | 350 // Report syntax errors. |
351 void ReportMessage(const char* message, const char* arg = NULL, | 351 void ReportMessage(const char* message, const char* arg = NULL, |
352 bool is_reference_error = false) { | 352 bool is_reference_error = false) { |
353 Scanner::Location source_location = scanner()->location(); | 353 Scanner::Location source_location = scanner()->location(); |
354 Traits::ReportMessageAt(source_location, message, arg, is_reference_error); | 354 Traits::ReportMessageAt(source_location, message, arg, is_reference_error); |
355 } | 355 } |
356 | 356 |
357 void ReportMessageAt(Scanner::Location location, const char* message, | 357 void ReportMessageAt(Scanner::Location location, const char* message, |
358 bool is_reference_error = false) { | 358 bool is_reference_error = false) { |
359 Traits::ReportMessageAt(location, message, NULL, is_reference_error); | 359 Traits::ReportMessageAt(location, message, (const char*)NULL, |
| 360 is_reference_error); |
360 } | 361 } |
361 | 362 |
362 void ReportUnexpectedToken(Token::Value token); | 363 void ReportUnexpectedToken(Token::Value token); |
363 | 364 |
364 // Recursive descent functions: | 365 // Recursive descent functions: |
365 | 366 |
366 // Parses an identifier that is valid for the current scope, in particular it | 367 // Parses an identifier that is valid for the current scope, in particular it |
367 // fails on strict mode future reserved keywords in a strict scope. If | 368 // fails on strict mode future reserved keywords in a strict scope. If |
368 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 369 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
369 // "arguments" as identifier even in strict mode (this is needed in cases like | 370 // "arguments" as identifier even in strict mode (this is needed in cases like |
370 // "var foo = eval;"). | 371 // "var foo = eval;"). |
371 IdentifierT ParseIdentifier( | 372 IdentifierT ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok); |
372 AllowEvalOrArgumentsAsIdentifier, | |
373 bool* ok); | |
374 // 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 |
375 // whether it is strict mode future reserved. | 374 // whether it is strict mode future reserved. |
376 IdentifierT ParseIdentifierOrStrictReservedWord( | 375 IdentifierT ParseIdentifierOrStrictReservedWord( |
377 bool* is_strict_reserved, | 376 bool* is_strict_reserved, |
378 bool* ok); | 377 bool* ok); |
379 IdentifierT ParseIdentifierName(bool* ok); | 378 IdentifierT ParseIdentifierName(bool* ok); |
380 // 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'. |
381 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, | 380 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, |
382 bool* is_set, | 381 bool* is_set, |
383 bool* ok); | 382 bool* ok); |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 } | 989 } |
991 | 990 |
992 // Odd-ball literal creators. | 991 // Odd-ball literal creators. |
993 static PreParserExpression GetLiteralTheHole(int position, | 992 static PreParserExpression GetLiteralTheHole(int position, |
994 PreParserFactory* factory) { | 993 PreParserFactory* factory) { |
995 return PreParserExpression::Default(); | 994 return PreParserExpression::Default(); |
996 } | 995 } |
997 | 996 |
998 // Producing data during the recursive descent. | 997 // Producing data during the recursive descent. |
999 PreParserIdentifier GetSymbol(Scanner* scanner); | 998 PreParserIdentifier GetSymbol(Scanner* scanner); |
1000 static PreParserIdentifier NextLiteralString(Scanner* scanner, | 999 |
1001 PretenureFlag tenured) { | 1000 PreParserIdentifier GetNextSymbol(Scanner* scanner) { |
1002 return PreParserIdentifier::Default(); | 1001 return PreParserIdentifier::Default(); |
1003 } | 1002 } |
1004 | 1003 |
1005 static PreParserExpression ThisExpression(PreParserScope* scope, | 1004 static PreParserExpression ThisExpression(PreParserScope* scope, |
1006 PreParserFactory* factory) { | 1005 PreParserFactory* factory) { |
1007 return PreParserExpression::This(); | 1006 return PreParserExpression::This(); |
1008 } | 1007 } |
1009 | 1008 |
1010 static PreParserExpression ExpressionFromLiteral( | 1009 static PreParserExpression ExpressionFromLiteral( |
1011 Token::Value token, int pos, Scanner* scanner, | 1010 Token::Value token, int pos, Scanner* scanner, |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 } | 1210 } |
1212 | 1211 |
1213 | 1212 |
1214 template<class Traits> | 1213 template<class Traits> |
1215 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | 1214 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { |
1216 Scanner::Location source_location = scanner()->location(); | 1215 Scanner::Location source_location = scanner()->location(); |
1217 | 1216 |
1218 // Four of the tokens are treated specially | 1217 // Four of the tokens are treated specially |
1219 switch (token) { | 1218 switch (token) { |
1220 case Token::EOS: | 1219 case Token::EOS: |
1221 return ReportMessageAt(source_location, "unexpected_eos"); | 1220 return this->ReportMessageAt(source_location, "unexpected_eos"); |
1222 case Token::NUMBER: | 1221 case Token::NUMBER: |
1223 return ReportMessageAt(source_location, "unexpected_token_number"); | 1222 return this->ReportMessageAt(source_location, "unexpected_token_number"); |
1224 case Token::STRING: | 1223 case Token::STRING: |
1225 return ReportMessageAt(source_location, "unexpected_token_string"); | 1224 return this->ReportMessageAt(source_location, "unexpected_token_string"); |
1226 case Token::IDENTIFIER: | 1225 case Token::IDENTIFIER: |
1227 return ReportMessageAt(source_location, "unexpected_token_identifier"); | 1226 return this->ReportMessageAt(source_location, |
| 1227 "unexpected_token_identifier"); |
1228 case Token::FUTURE_RESERVED_WORD: | 1228 case Token::FUTURE_RESERVED_WORD: |
1229 return ReportMessageAt(source_location, "unexpected_reserved"); | 1229 return this->ReportMessageAt(source_location, "unexpected_reserved"); |
1230 case Token::YIELD: | 1230 case Token::YIELD: |
1231 case Token::FUTURE_STRICT_RESERVED_WORD: | 1231 case Token::FUTURE_STRICT_RESERVED_WORD: |
1232 return ReportMessageAt(source_location, strict_mode() == SLOPPY | 1232 return this->ReportMessageAt(source_location, strict_mode() == SLOPPY |
1233 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); | 1233 ? "unexpected_token_identifier" : "unexpected_strict_reserved"); |
1234 default: | 1234 default: |
1235 const char* name = Token::String(token); | 1235 const char* name = Token::String(token); |
1236 ASSERT(name != NULL); | 1236 ASSERT(name != NULL); |
1237 Traits::ReportMessageAt( | 1237 Traits::ReportMessageAt( |
1238 source_location, "unexpected_token", name); | 1238 source_location, "unexpected_token", name); |
1239 } | 1239 } |
1240 } | 1240 } |
1241 | 1241 |
1242 | 1242 |
1243 template<class Traits> | 1243 template<class Traits> |
1244 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | 1244 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
1245 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 1245 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
1246 bool* ok) { | 1246 bool* ok) { |
1247 Token::Value next = Next(); | 1247 Token::Value next = Next(); |
1248 if (next == Token::IDENTIFIER) { | 1248 if (next == Token::IDENTIFIER) { |
1249 IdentifierT name = this->GetSymbol(scanner()); | 1249 IdentifierT name = this->GetSymbol(scanner()); |
1250 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 1250 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
1251 strict_mode() == STRICT && this->IsEvalOrArguments(name)) { | 1251 strict_mode() == STRICT && |
| 1252 this->IsEvalOrArguments(name)) { |
1252 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | 1253 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); |
1253 *ok = false; | 1254 *ok = false; |
1254 } | 1255 } |
1255 return name; | 1256 return name; |
1256 } else if (strict_mode() == SLOPPY && | 1257 } else if (strict_mode() == SLOPPY && |
1257 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1258 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1258 (next == Token::YIELD && !is_generator()))) { | 1259 (next == Token::YIELD && !is_generator()))) { |
1259 return this->GetSymbol(scanner()); | 1260 return this->GetSymbol(scanner()); |
1260 } else { | 1261 } else { |
1261 this->ReportUnexpectedToken(next); | 1262 this->ReportUnexpectedToken(next); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 this->ReportUnexpectedToken(next); | 1294 this->ReportUnexpectedToken(next); |
1294 *ok = false; | 1295 *ok = false; |
1295 return Traits::EmptyIdentifier(); | 1296 return Traits::EmptyIdentifier(); |
1296 } | 1297 } |
1297 return this->GetSymbol(scanner()); | 1298 return this->GetSymbol(scanner()); |
1298 } | 1299 } |
1299 | 1300 |
1300 | 1301 |
1301 template <class Traits> | 1302 template <class Traits> |
1302 typename ParserBase<Traits>::IdentifierT | 1303 typename ParserBase<Traits>::IdentifierT |
1303 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | 1304 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, |
1304 bool* is_set, | |
1305 bool* ok) { | 1305 bool* ok) { |
1306 IdentifierT result = ParseIdentifierName(ok); | 1306 IdentifierT result = ParseIdentifierName(ok); |
1307 if (!*ok) return Traits::EmptyIdentifier(); | 1307 if (!*ok) return Traits::EmptyIdentifier(); |
1308 scanner()->IsGetOrSet(is_get, is_set); | 1308 scanner()->IsGetOrSet(is_get, is_set); |
1309 return result; | 1309 return result; |
1310 } | 1310 } |
1311 | 1311 |
1312 | 1312 |
1313 template <class Traits> | 1313 template <class Traits> |
1314 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( | 1314 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( |
1315 bool seen_equal, bool* ok) { | 1315 bool seen_equal, bool* ok) { |
1316 int pos = peek_position(); | 1316 int pos = peek_position(); |
1317 if (!scanner()->ScanRegExpPattern(seen_equal)) { | 1317 if (!scanner()->ScanRegExpPattern(seen_equal)) { |
1318 Next(); | 1318 Next(); |
1319 ReportMessage("unterminated_regexp"); | 1319 ReportMessage("unterminated_regexp"); |
1320 *ok = false; | 1320 *ok = false; |
1321 return Traits::EmptyExpression(); | 1321 return Traits::EmptyExpression(); |
1322 } | 1322 } |
1323 | 1323 |
1324 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 1324 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
1325 | 1325 |
1326 IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED); | 1326 IdentifierT js_pattern = this->GetNextSymbol(scanner()); |
1327 if (!scanner()->ScanRegExpFlags()) { | 1327 if (!scanner()->ScanRegExpFlags()) { |
1328 Next(); | 1328 Next(); |
1329 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); | 1329 this->ReportMessage("invalid_regexp_flags"); |
1330 *ok = false; | 1330 *ok = false; |
1331 return Traits::EmptyExpression(); | 1331 return Traits::EmptyExpression(); |
1332 } | 1332 } |
1333 IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED); | 1333 IdentifierT js_flags = this->GetNextSymbol(scanner()); |
1334 Next(); | 1334 Next(); |
1335 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | 1335 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); |
1336 } | 1336 } |
1337 | 1337 |
1338 | 1338 |
1339 #define CHECK_OK ok); \ | 1339 #define CHECK_OK ok); \ |
1340 if (!*ok) return this->EmptyExpression(); \ | 1340 if (!*ok) return this->EmptyExpression(); \ |
1341 ((void)0 | 1341 ((void)0 |
1342 #define DUMMY ) // to make indentation work | 1342 #define DUMMY ) // to make indentation work |
1343 #undef DUMMY | 1343 #undef DUMMY |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 } | 2106 } |
2107 | 2107 |
2108 | 2108 |
2109 template <typename Traits> | 2109 template <typename Traits> |
2110 typename ParserBase<Traits>::ExpressionT | 2110 typename ParserBase<Traits>::ExpressionT |
2111 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | 2111 ParserBase<Traits>::CheckAndRewriteReferenceExpression( |
2112 ExpressionT expression, | 2112 ExpressionT expression, |
2113 Scanner::Location location, const char* message, bool* ok) { | 2113 Scanner::Location location, const char* message, bool* ok) { |
2114 if (strict_mode() == STRICT && this->IsIdentifier(expression) && | 2114 if (strict_mode() == STRICT && this->IsIdentifier(expression) && |
2115 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | 2115 this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
2116 this->ReportMessageAt(location, "strict_eval_arguments", false); | 2116 this->ReportMessageAt(location, "strict_eval_arguments"); |
2117 *ok = false; | 2117 *ok = false; |
2118 return this->EmptyExpression(); | 2118 return this->EmptyExpression(); |
2119 } else if (expression->IsValidReferenceExpression()) { | 2119 } else if (expression->IsValidReferenceExpression()) { |
2120 return expression; | 2120 return expression; |
2121 } else if (expression->IsCall()) { | 2121 } else if (expression->IsCall()) { |
2122 // If it is a call, make it a runtime error for legacy web compatibility. | 2122 // If it is a call, make it a runtime error for legacy web compatibility. |
2123 // Rewrite `expr' to `expr[throw ReferenceError]'. | 2123 // Rewrite `expr' to `expr[throw ReferenceError]'. |
2124 int pos = location.beg_pos; | 2124 int pos = location.beg_pos; |
2125 ExpressionT error = this->NewThrowReferenceError(message, pos); | 2125 ExpressionT error = this->NewThrowReferenceError(message, pos); |
2126 return factory()->NewProperty(expression, error, pos); | 2126 return factory()->NewProperty(expression, error, pos); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2165 "accessor_get_set"); | 2165 "accessor_get_set"); |
2166 } | 2166 } |
2167 *ok = false; | 2167 *ok = false; |
2168 } | 2168 } |
2169 } | 2169 } |
2170 | 2170 |
2171 | 2171 |
2172 } } // v8::internal | 2172 } } // v8::internal |
2173 | 2173 |
2174 #endif // V8_PREPARSER_H | 2174 #endif // V8_PREPARSER_H |
OLD | NEW |