| 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 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
| 29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
| 30 | 30 |
| 31 #include "hashmap.h" | 31 #include "hashmap.h" |
| 32 #include "scopes.h" | |
| 33 #include "token.h" | 32 #include "token.h" |
| 34 #include "scanner.h" | 33 #include "scanner.h" |
| 35 #include "v8.h" | |
| 36 | 34 |
| 37 namespace v8 { | 35 namespace v8 { |
| 38 namespace internal { | 36 namespace internal { |
| 39 | 37 |
| 40 // Common base class shared between parser and pre-parser. | 38 // Common base class shared between parser and pre-parser. |
| 41 template <typename Traits> | 39 class ParserBase { |
| 42 class ParserBase : public Traits { | |
| 43 public: | 40 public: |
| 44 ParserBase(Scanner* scanner, uintptr_t stack_limit, | 41 ParserBase(Scanner* scanner, uintptr_t stack_limit) |
| 45 v8::Extension* extension, | 42 : scanner_(scanner), |
| 46 typename Traits::Type::Zone* zone, | |
| 47 typename Traits::Type::Parser this_object) | |
| 48 : Traits(this_object), | |
| 49 parenthesized_function_(false), | |
| 50 scope_(NULL), | |
| 51 function_state_(NULL), | |
| 52 extension_(extension), | |
| 53 scanner_(scanner), | |
| 54 stack_limit_(stack_limit), | 43 stack_limit_(stack_limit), |
| 55 stack_overflow_(false), | 44 stack_overflow_(false), |
| 56 allow_lazy_(false), | 45 allow_lazy_(false), |
| 57 allow_natives_syntax_(false), | 46 allow_natives_syntax_(false), |
| 58 allow_generators_(false), | 47 allow_generators_(false), |
| 59 allow_for_of_(false), | 48 allow_for_of_(false) { } |
| 60 zone_(zone) { } | 49 // TODO(mstarzinger): Only virtual until message reporting has been unified. |
| 50 virtual ~ParserBase() { } |
| 61 | 51 |
| 62 // Getters that indicate whether certain syntactical constructs are | 52 // Getters that indicate whether certain syntactical constructs are |
| 63 // allowed to be parsed by this instance of the parser. | 53 // allowed to be parsed by this instance of the parser. |
| 64 bool allow_lazy() const { return allow_lazy_; } | 54 bool allow_lazy() const { return allow_lazy_; } |
| 65 bool allow_natives_syntax() const { return allow_natives_syntax_; } | 55 bool allow_natives_syntax() const { return allow_natives_syntax_; } |
| 66 bool allow_generators() const { return allow_generators_; } | 56 bool allow_generators() const { return allow_generators_; } |
| 67 bool allow_for_of() const { return allow_for_of_; } | 57 bool allow_for_of() const { return allow_for_of_; } |
| 68 bool allow_modules() const { return scanner()->HarmonyModules(); } | 58 bool allow_modules() const { return scanner()->HarmonyModules(); } |
| 69 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } | 59 bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } |
| 70 bool allow_harmony_numeric_literals() const { | 60 bool allow_harmony_numeric_literals() const { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 84 void set_allow_harmony_numeric_literals(bool allow) { | 74 void set_allow_harmony_numeric_literals(bool allow) { |
| 85 scanner()->SetHarmonyNumericLiterals(allow); | 75 scanner()->SetHarmonyNumericLiterals(allow); |
| 86 } | 76 } |
| 87 | 77 |
| 88 protected: | 78 protected: |
| 89 enum AllowEvalOrArgumentsAsIdentifier { | 79 enum AllowEvalOrArgumentsAsIdentifier { |
| 90 kAllowEvalOrArguments, | 80 kAllowEvalOrArguments, |
| 91 kDontAllowEvalOrArguments | 81 kDontAllowEvalOrArguments |
| 92 }; | 82 }; |
| 93 | 83 |
| 94 // --------------------------------------------------------------------------- | |
| 95 // FunctionState and BlockState together implement the parser's scope stack. | |
| 96 // The parser's current scope is in scope_. BlockState and FunctionState | |
| 97 // constructors push on the scope stack and the destructors pop. They are also | |
| 98 // used to hold the parser's per-function and per-block state. | |
| 99 class BlockState BASE_EMBEDDED { | |
| 100 public: | |
| 101 BlockState(typename Traits::Type::Scope** scope_stack, | |
| 102 typename Traits::Type::Scope* scope) | |
| 103 : scope_stack_(scope_stack), | |
| 104 outer_scope_(*scope_stack), | |
| 105 scope_(scope) { | |
| 106 *scope_stack_ = scope_; | |
| 107 } | |
| 108 ~BlockState() { *scope_stack_ = outer_scope_; } | |
| 109 | |
| 110 private: | |
| 111 typename Traits::Type::Scope** scope_stack_; | |
| 112 typename Traits::Type::Scope* outer_scope_; | |
| 113 typename Traits::Type::Scope* scope_; | |
| 114 }; | |
| 115 | |
| 116 class FunctionState BASE_EMBEDDED { | |
| 117 public: | |
| 118 FunctionState( | |
| 119 FunctionState** function_state_stack, | |
| 120 typename Traits::Type::Scope** scope_stack, | |
| 121 typename Traits::Type::Scope* scope, | |
| 122 typename Traits::Type::Zone* zone = NULL); | |
| 123 ~FunctionState(); | |
| 124 | |
| 125 int NextMaterializedLiteralIndex() { | |
| 126 return next_materialized_literal_index_++; | |
| 127 } | |
| 128 int materialized_literal_count() { | |
| 129 return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize; | |
| 130 } | |
| 131 | |
| 132 int NextHandlerIndex() { return next_handler_index_++; } | |
| 133 int handler_count() { return next_handler_index_; } | |
| 134 | |
| 135 void AddProperty() { expected_property_count_++; } | |
| 136 int expected_property_count() { return expected_property_count_; } | |
| 137 | |
| 138 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } | |
| 139 bool is_generator() const { return is_generator_; } | |
| 140 | |
| 141 void set_generator_object_variable( | |
| 142 typename Traits::Type::GeneratorVariable* variable) { | |
| 143 ASSERT(variable != NULL); | |
| 144 ASSERT(!is_generator()); | |
| 145 generator_object_variable_ = variable; | |
| 146 is_generator_ = true; | |
| 147 } | |
| 148 typename Traits::Type::GeneratorVariable* generator_object_variable() | |
| 149 const { | |
| 150 return generator_object_variable_; | |
| 151 } | |
| 152 | |
| 153 typename Traits::Type::Factory* factory() { return &factory_; } | |
| 154 | |
| 155 private: | |
| 156 // Used to assign an index to each literal that needs materialization in | |
| 157 // the function. Includes regexp literals, and boilerplate for object and | |
| 158 // array literals. | |
| 159 int next_materialized_literal_index_; | |
| 160 | |
| 161 // Used to assign a per-function index to try and catch handlers. | |
| 162 int next_handler_index_; | |
| 163 | |
| 164 // Properties count estimation. | |
| 165 int expected_property_count_; | |
| 166 | |
| 167 // Whether the function is a generator. | |
| 168 bool is_generator_; | |
| 169 // For generators, this variable may hold the generator object. It variable | |
| 170 // is used by yield expressions and return statements. It is not necessary | |
| 171 // for generator functions to have this variable set. | |
| 172 Variable* generator_object_variable_; | |
| 173 | |
| 174 FunctionState** function_state_stack_; | |
| 175 FunctionState* outer_function_state_; | |
| 176 typename Traits::Type::Scope** scope_stack_; | |
| 177 typename Traits::Type::Scope* outer_scope_; | |
| 178 Isolate* isolate_; // Only used by ParserTraits. | |
| 179 int saved_ast_node_id_; // Only used by ParserTraits. | |
| 180 typename Traits::Type::Factory factory_; | |
| 181 | |
| 182 friend class ParserTraits; | |
| 183 }; | |
| 184 | |
| 185 Scanner* scanner() const { return scanner_; } | 84 Scanner* scanner() const { return scanner_; } |
| 186 int position() { return scanner_->location().beg_pos; } | 85 int position() { return scanner_->location().beg_pos; } |
| 187 int peek_position() { return scanner_->peek_location().beg_pos; } | 86 int peek_position() { return scanner_->peek_location().beg_pos; } |
| 188 bool stack_overflow() const { return stack_overflow_; } | 87 bool stack_overflow() const { return stack_overflow_; } |
| 189 void set_stack_overflow() { stack_overflow_ = true; } | 88 void set_stack_overflow() { stack_overflow_ = true; } |
| 190 typename Traits::Type::Zone* zone() const { return zone_; } | 89 |
| 90 virtual bool is_classic_mode() = 0; |
| 191 | 91 |
| 192 INLINE(Token::Value peek()) { | 92 INLINE(Token::Value peek()) { |
| 193 if (stack_overflow_) return Token::ILLEGAL; | 93 if (stack_overflow_) return Token::ILLEGAL; |
| 194 return scanner()->peek(); | 94 return scanner()->peek(); |
| 195 } | 95 } |
| 196 | 96 |
| 197 INLINE(Token::Value Next()) { | 97 INLINE(Token::Value Next()) { |
| 198 if (stack_overflow_) return Token::ILLEGAL; | 98 if (stack_overflow_) return Token::ILLEGAL; |
| 199 { | 99 { |
| 200 int marker; | 100 int marker; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 225 } | 125 } |
| 226 | 126 |
| 227 void Expect(Token::Value token, bool* ok) { | 127 void Expect(Token::Value token, bool* ok) { |
| 228 Token::Value next = Next(); | 128 Token::Value next = Next(); |
| 229 if (next != token) { | 129 if (next != token) { |
| 230 ReportUnexpectedToken(next); | 130 ReportUnexpectedToken(next); |
| 231 *ok = false; | 131 *ok = false; |
| 232 } | 132 } |
| 233 } | 133 } |
| 234 | 134 |
| 235 void ExpectSemicolon(bool* ok) { | 135 bool peek_any_identifier(); |
| 236 // Check for automatic semicolon insertion according to | 136 void ExpectSemicolon(bool* ok); |
| 237 // the rules given in ECMA-262, section 7.9, page 21. | 137 bool CheckContextualKeyword(Vector<const char> keyword); |
| 238 Token::Value tok = peek(); | 138 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok); |
| 239 if (tok == Token::SEMICOLON) { | |
| 240 Next(); | |
| 241 return; | |
| 242 } | |
| 243 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
| 244 tok == Token::RBRACE || | |
| 245 tok == Token::EOS) { | |
| 246 return; | |
| 247 } | |
| 248 Expect(Token::SEMICOLON, ok); | |
| 249 } | |
| 250 | 139 |
| 251 bool peek_any_identifier() { | 140 // Strict mode octal literal validation. |
| 252 Token::Value next = peek(); | 141 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok); |
| 253 return next == Token::IDENTIFIER || | |
| 254 next == Token::FUTURE_RESERVED_WORD || | |
| 255 next == Token::FUTURE_STRICT_RESERVED_WORD || | |
| 256 next == Token::YIELD; | |
| 257 } | |
| 258 | |
| 259 bool CheckContextualKeyword(Vector<const char> keyword) { | |
| 260 if (peek() == Token::IDENTIFIER && | |
| 261 scanner()->is_next_contextual_keyword(keyword)) { | |
| 262 Consume(Token::IDENTIFIER); | |
| 263 return true; | |
| 264 } | |
| 265 return false; | |
| 266 } | |
| 267 | |
| 268 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | |
| 269 Expect(Token::IDENTIFIER, ok); | |
| 270 if (!*ok) return; | |
| 271 if (!scanner()->is_literal_contextual_keyword(keyword)) { | |
| 272 ReportUnexpectedToken(scanner()->current_token()); | |
| 273 *ok = false; | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 // Checks whether an octal literal was last seen between beg_pos and end_pos. | |
| 278 // If so, reports an error. Only called for strict mode. | |
| 279 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
| 280 Scanner::Location octal = scanner()->octal_position(); | |
| 281 if (octal.IsValid() && beg_pos <= octal.beg_pos && | |
| 282 octal.end_pos <= end_pos) { | |
| 283 ReportMessageAt(octal, "strict_octal_literal"); | |
| 284 scanner()->clear_octal_position(); | |
| 285 *ok = false; | |
| 286 } | |
| 287 } | |
| 288 | 142 |
| 289 // Determine precedence of given token. | 143 // Determine precedence of given token. |
| 290 static int Precedence(Token::Value token, bool accept_IN) { | 144 static int Precedence(Token::Value token, bool accept_IN); |
| 291 if (token == Token::IN && !accept_IN) | |
| 292 return 0; // 0 precedence will terminate binary expression parsing | |
| 293 return Token::Precedence(token); | |
| 294 } | |
| 295 | |
| 296 typename Traits::Type::Factory* factory() { | |
| 297 return function_state_->factory(); | |
| 298 } | |
| 299 | |
| 300 bool is_classic_mode() const { return scope_->is_classic_mode(); } | |
| 301 | |
| 302 bool is_generator() const { return function_state_->is_generator(); } | |
| 303 | 145 |
| 304 // Report syntax errors. | 146 // Report syntax errors. |
| 305 void ReportMessage(const char* message, Vector<const char*> args) { | 147 void ReportUnexpectedToken(Token::Value token); |
| 306 Scanner::Location source_location = scanner()->location(); | 148 void ReportMessageAt(Scanner::Location location, const char* type) { |
| 307 Traits::ReportMessageAt(source_location, message, args); | 149 ReportMessageAt(location, type, Vector<const char*>::empty()); |
| 308 } | 150 } |
| 309 | 151 virtual void ReportMessageAt(Scanner::Location source_location, |
| 310 void ReportMessageAt(Scanner::Location location, const char* message) { | 152 const char* message, |
| 311 Traits::ReportMessageAt(location, message, Vector<const char*>::empty()); | 153 Vector<const char*> args) = 0; |
| 312 } | |
| 313 | |
| 314 void ReportUnexpectedToken(Token::Value token); | |
| 315 | |
| 316 // Recursive descent functions: | |
| 317 | |
| 318 // Parses an identifier that is valid for the current scope, in particular it | |
| 319 // fails on strict mode future reserved keywords in a strict scope. If | |
| 320 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | |
| 321 // "arguments" as identifier even in strict mode (this is needed in cases like | |
| 322 // "var foo = eval;"). | |
| 323 typename Traits::Type::Identifier ParseIdentifier( | |
| 324 AllowEvalOrArgumentsAsIdentifier, | |
| 325 bool* ok); | |
| 326 // Parses an identifier or a strict mode future reserved word, and indicate | |
| 327 // whether it is strict mode future reserved. | |
| 328 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord( | |
| 329 bool* is_strict_reserved, | |
| 330 bool* ok); | |
| 331 typename Traits::Type::Identifier ParseIdentifierName(bool* ok); | |
| 332 // Parses an identifier and determines whether or not it is 'get' or 'set'. | |
| 333 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, | |
| 334 bool* is_set, | |
| 335 bool* ok); | |
| 336 | |
| 337 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, | |
| 338 bool* ok); | |
| 339 | |
| 340 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok); | |
| 341 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok); | |
| 342 typename Traits::Type::Expression ParseArrayLiteral(bool* ok); | |
| 343 | 154 |
| 344 // Used to detect duplicates in object literals. Each of the values | 155 // Used to detect duplicates in object literals. Each of the values |
| 345 // kGetterProperty, kSetterProperty and kValueProperty represents | 156 // kGetterProperty, kSetterProperty and kValueProperty represents |
| 346 // a type of object literal property. When parsing a property, its | 157 // a type of object literal property. When parsing a property, its |
| 347 // type value is stored in the DuplicateFinder for the property name. | 158 // type value is stored in the DuplicateFinder for the property name. |
| 348 // Values are chosen so that having intersection bits means the there is | 159 // Values are chosen so that having intersection bits means the there is |
| 349 // an incompatibility. | 160 // an incompatibility. |
| 350 // I.e., you can add a getter to a property that already has a setter, since | 161 // I.e., you can add a getter to a property that already has a setter, since |
| 351 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | 162 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
| 352 // already has a getter or a value. Adding the getter to an existing | 163 // already has a getter or a value. Adding the getter to an existing |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 } | 199 } |
| 389 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { | 200 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { |
| 390 return ((type1 | type2) & kValueFlag) == 0; | 201 return ((type1 | type2) & kValueFlag) == 0; |
| 391 } | 202 } |
| 392 | 203 |
| 393 ParserBase* parser_; | 204 ParserBase* parser_; |
| 394 DuplicateFinder finder_; | 205 DuplicateFinder finder_; |
| 395 LanguageMode language_mode_; | 206 LanguageMode language_mode_; |
| 396 }; | 207 }; |
| 397 | 208 |
| 398 // If true, the next (and immediately following) function literal is | |
| 399 // preceded by a parenthesis. | |
| 400 // Heuristically that means that the function will be called immediately, | |
| 401 // so never lazily compile it. | |
| 402 bool parenthesized_function_; | |
| 403 | |
| 404 typename Traits::Type::Scope* scope_; // Scope stack. | |
| 405 FunctionState* function_state_; // Function state stack. | |
| 406 v8::Extension* extension_; | |
| 407 | |
| 408 private: | 209 private: |
| 409 Scanner* scanner_; | 210 Scanner* scanner_; |
| 410 uintptr_t stack_limit_; | 211 uintptr_t stack_limit_; |
| 411 bool stack_overflow_; | 212 bool stack_overflow_; |
| 412 | 213 |
| 413 bool allow_lazy_; | 214 bool allow_lazy_; |
| 414 bool allow_natives_syntax_; | 215 bool allow_natives_syntax_; |
| 415 bool allow_generators_; | 216 bool allow_generators_; |
| 416 bool allow_for_of_; | 217 bool allow_for_of_; |
| 417 | |
| 418 typename Traits::Type::Zone* zone_; // Only used by Parser. | |
| 419 }; | 218 }; |
| 420 | 219 |
| 421 | 220 |
| 422 class PreParserIdentifier { | |
| 423 public: | |
| 424 static PreParserIdentifier Default() { | |
| 425 return PreParserIdentifier(kUnknownIdentifier); | |
| 426 } | |
| 427 static PreParserIdentifier Eval() { | |
| 428 return PreParserIdentifier(kEvalIdentifier); | |
| 429 } | |
| 430 static PreParserIdentifier Arguments() { | |
| 431 return PreParserIdentifier(kArgumentsIdentifier); | |
| 432 } | |
| 433 static PreParserIdentifier FutureReserved() { | |
| 434 return PreParserIdentifier(kFutureReservedIdentifier); | |
| 435 } | |
| 436 static PreParserIdentifier FutureStrictReserved() { | |
| 437 return PreParserIdentifier(kFutureStrictReservedIdentifier); | |
| 438 } | |
| 439 static PreParserIdentifier Yield() { | |
| 440 return PreParserIdentifier(kYieldIdentifier); | |
| 441 } | |
| 442 bool IsEval() { return type_ == kEvalIdentifier; } | |
| 443 bool IsArguments() { return type_ == kArgumentsIdentifier; } | |
| 444 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } | |
| 445 bool IsYield() { return type_ == kYieldIdentifier; } | |
| 446 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } | |
| 447 bool IsFutureStrictReserved() { | |
| 448 return type_ == kFutureStrictReservedIdentifier; | |
| 449 } | |
| 450 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } | |
| 451 | |
| 452 private: | |
| 453 enum Type { | |
| 454 kUnknownIdentifier, | |
| 455 kFutureReservedIdentifier, | |
| 456 kFutureStrictReservedIdentifier, | |
| 457 kYieldIdentifier, | |
| 458 kEvalIdentifier, | |
| 459 kArgumentsIdentifier | |
| 460 }; | |
| 461 explicit PreParserIdentifier(Type type) : type_(type) {} | |
| 462 Type type_; | |
| 463 | |
| 464 friend class PreParserExpression; | |
| 465 }; | |
| 466 | |
| 467 | |
| 468 // Bits 0 and 1 are used to identify the type of expression: | |
| 469 // If bit 0 is set, it's an identifier. | |
| 470 // if bit 1 is set, it's a string literal. | |
| 471 // If neither is set, it's no particular type, and both set isn't | |
| 472 // use yet. | |
| 473 class PreParserExpression { | |
| 474 public: | |
| 475 static PreParserExpression Default() { | |
| 476 return PreParserExpression(kUnknownExpression); | |
| 477 } | |
| 478 | |
| 479 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | |
| 480 return PreParserExpression(kIdentifierFlag | | |
| 481 (id.type_ << kIdentifierShift)); | |
| 482 } | |
| 483 | |
| 484 static PreParserExpression StringLiteral() { | |
| 485 return PreParserExpression(kUnknownStringLiteral); | |
| 486 } | |
| 487 | |
| 488 static PreParserExpression UseStrictStringLiteral() { | |
| 489 return PreParserExpression(kUseStrictString); | |
| 490 } | |
| 491 | |
| 492 static PreParserExpression This() { | |
| 493 return PreParserExpression(kThisExpression); | |
| 494 } | |
| 495 | |
| 496 static PreParserExpression ThisProperty() { | |
| 497 return PreParserExpression(kThisPropertyExpression); | |
| 498 } | |
| 499 | |
| 500 static PreParserExpression StrictFunction() { | |
| 501 return PreParserExpression(kStrictFunctionExpression); | |
| 502 } | |
| 503 | |
| 504 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; } | |
| 505 | |
| 506 // Only works corretly if it is actually an identifier expression. | |
| 507 PreParserIdentifier AsIdentifier() { | |
| 508 return PreParserIdentifier( | |
| 509 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); | |
| 510 } | |
| 511 | |
| 512 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } | |
| 513 | |
| 514 bool IsUseStrictLiteral() { | |
| 515 return (code_ & kStringLiteralMask) == kUseStrictString; | |
| 516 } | |
| 517 | |
| 518 bool IsThis() { return code_ == kThisExpression; } | |
| 519 | |
| 520 bool IsThisProperty() { return code_ == kThisPropertyExpression; } | |
| 521 | |
| 522 bool IsStrictFunction() { return code_ == kStrictFunctionExpression; } | |
| 523 | |
| 524 private: | |
| 525 // First two/three bits are used as flags. | |
| 526 // Bit 0 and 1 represent identifiers or strings literals, and are | |
| 527 // mutually exclusive, but can both be absent. | |
| 528 enum { | |
| 529 kUnknownExpression = 0, | |
| 530 // Identifiers | |
| 531 kIdentifierFlag = 1, // Used to detect labels. | |
| 532 kIdentifierShift = 3, | |
| 533 | |
| 534 kStringLiteralFlag = 2, // Used to detect directive prologue. | |
| 535 kUnknownStringLiteral = kStringLiteralFlag, | |
| 536 kUseStrictString = kStringLiteralFlag | 8, | |
| 537 kStringLiteralMask = kUseStrictString, | |
| 538 | |
| 539 // Below here applies if neither identifier nor string literal. | |
| 540 kThisExpression = 4, | |
| 541 kThisPropertyExpression = 8, | |
| 542 kStrictFunctionExpression = 12 | |
| 543 }; | |
| 544 | |
| 545 explicit PreParserExpression(int expression_code) : code_(expression_code) {} | |
| 546 | |
| 547 int code_; | |
| 548 }; | |
| 549 | |
| 550 | |
| 551 // PreParserExpressionList doesn't actually store the expressions because | |
| 552 // PreParser doesn't need to. | |
| 553 class PreParserExpressionList { | |
| 554 public: | |
| 555 // These functions make list->Add(some_expression) work (and do nothing). | |
| 556 PreParserExpressionList* operator->() { return this; } | |
| 557 void Add(PreParserExpression, void*) { } | |
| 558 }; | |
| 559 | |
| 560 | |
| 561 class PreParserScope { | |
| 562 public: | |
| 563 explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type) | |
| 564 : scope_type_(scope_type) { | |
| 565 if (outer_scope) { | |
| 566 scope_inside_with_ = | |
| 567 outer_scope->scope_inside_with_ || is_with_scope(); | |
| 568 language_mode_ = outer_scope->language_mode(); | |
| 569 } else { | |
| 570 scope_inside_with_ = is_with_scope(); | |
| 571 language_mode_ = CLASSIC_MODE; | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; } | |
| 576 bool is_classic_mode() const { | |
| 577 return language_mode() == CLASSIC_MODE; | |
| 578 } | |
| 579 bool is_extended_mode() { | |
| 580 return language_mode() == EXTENDED_MODE; | |
| 581 } | |
| 582 bool inside_with() const { | |
| 583 return scope_inside_with_; | |
| 584 } | |
| 585 | |
| 586 ScopeType type() { return scope_type_; } | |
| 587 LanguageMode language_mode() const { return language_mode_; } | |
| 588 void SetLanguageMode(LanguageMode language_mode) { | |
| 589 language_mode_ = language_mode; | |
| 590 } | |
| 591 | |
| 592 private: | |
| 593 ScopeType scope_type_; | |
| 594 bool scope_inside_with_; | |
| 595 LanguageMode language_mode_; | |
| 596 }; | |
| 597 | |
| 598 | |
| 599 class PreParserFactory { | |
| 600 public: | |
| 601 explicit PreParserFactory(void* extra_param) {} | |
| 602 | |
| 603 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, | |
| 604 PreParserIdentifier js_flags, | |
| 605 int literal_index, | |
| 606 int pos) { | |
| 607 return PreParserExpression::Default(); | |
| 608 } | |
| 609 PreParserExpression NewBinaryOperation(Token::Value op, | |
| 610 PreParserExpression left, | |
| 611 PreParserExpression right, int pos) { | |
| 612 return PreParserExpression::Default(); | |
| 613 } | |
| 614 PreParserExpression NewArrayLiteral(PreParserExpressionList values, | |
| 615 int literal_index, | |
| 616 int pos) { | |
| 617 return PreParserExpression::Default(); | |
| 618 } | |
| 619 }; | |
| 620 | |
| 621 | |
| 622 class PreParser; | |
| 623 | |
| 624 class PreParserTraits { | |
| 625 public: | |
| 626 struct Type { | |
| 627 typedef PreParser* Parser; | |
| 628 | |
| 629 // Types used by FunctionState and BlockState. | |
| 630 typedef PreParserScope Scope; | |
| 631 typedef PreParserFactory Factory; | |
| 632 // PreParser doesn't need to store generator variables. | |
| 633 typedef void GeneratorVariable; | |
| 634 // No interaction with Zones. | |
| 635 typedef void Zone; | |
| 636 | |
| 637 // Return types for traversing functions. | |
| 638 typedef PreParserIdentifier Identifier; | |
| 639 typedef PreParserExpression Expression; | |
| 640 typedef PreParserExpressionList ExpressionList; | |
| 641 }; | |
| 642 | |
| 643 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | |
| 644 | |
| 645 // Custom operations executed when FunctionStates are created and | |
| 646 // destructed. (The PreParser doesn't need to do anything.) | |
| 647 template<typename FS> | |
| 648 static void SetUpFunctionState(FS* function_state, void*) {} | |
| 649 template<typename FS> | |
| 650 static void TearDownFunctionState(FS* function_state) {} | |
| 651 | |
| 652 // Helper functions for recursive descent. | |
| 653 static bool IsEvalOrArguments(PreParserIdentifier identifier) { | |
| 654 return identifier.IsEvalOrArguments(); | |
| 655 } | |
| 656 | |
| 657 // Reporting errors. | |
| 658 void ReportMessageAt(Scanner::Location location, | |
| 659 const char* message, | |
| 660 Vector<const char*> args); | |
| 661 void ReportMessageAt(Scanner::Location location, | |
| 662 const char* type, | |
| 663 const char* name_opt); | |
| 664 void ReportMessageAt(int start_pos, | |
| 665 int end_pos, | |
| 666 const char* type, | |
| 667 const char* name_opt); | |
| 668 | |
| 669 // "null" return type creators. | |
| 670 static PreParserIdentifier EmptyIdentifier() { | |
| 671 return PreParserIdentifier::Default(); | |
| 672 } | |
| 673 static PreParserExpression EmptyExpression() { | |
| 674 return PreParserExpression::Default(); | |
| 675 } | |
| 676 | |
| 677 // Odd-ball literal creators. | |
| 678 static PreParserExpression GetLiteralTheHole(int position, | |
| 679 PreParserFactory* factory) { | |
| 680 return PreParserExpression::Default(); | |
| 681 } | |
| 682 | |
| 683 // Producing data during the recursive descent. | |
| 684 PreParserIdentifier GetSymbol(Scanner* scanner); | |
| 685 static PreParserIdentifier NextLiteralString(Scanner* scanner, | |
| 686 PretenureFlag tenured) { | |
| 687 return PreParserIdentifier::Default(); | |
| 688 } | |
| 689 | |
| 690 static PreParserExpression ThisExpression(PreParserScope* scope, | |
| 691 PreParserFactory* factory) { | |
| 692 return PreParserExpression::This(); | |
| 693 } | |
| 694 | |
| 695 static PreParserExpression ExpressionFromLiteral( | |
| 696 Token::Value token, int pos, Scanner* scanner, | |
| 697 PreParserFactory* factory) { | |
| 698 return PreParserExpression::Default(); | |
| 699 } | |
| 700 | |
| 701 static PreParserExpression ExpressionFromIdentifier( | |
| 702 PreParserIdentifier name, int pos, PreParserScope* scope, | |
| 703 PreParserFactory* factory) { | |
| 704 return PreParserExpression::FromIdentifier(name); | |
| 705 } | |
| 706 | |
| 707 PreParserExpression ExpressionFromString(int pos, | |
| 708 Scanner* scanner, | |
| 709 PreParserFactory* factory = NULL); | |
| 710 | |
| 711 static PreParserExpressionList NewExpressionList(int size, void* zone) { | |
| 712 return PreParserExpressionList(); | |
| 713 } | |
| 714 | |
| 715 // Temporary glue; these functions will move to ParserBase. | |
| 716 PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok); | |
| 717 PreParserExpression ParseObjectLiteral(bool* ok); | |
| 718 PreParserExpression ParseV8Intrinsic(bool* ok); | |
| 719 | |
| 720 private: | |
| 721 PreParser* pre_parser_; | |
| 722 }; | |
| 723 | |
| 724 | |
| 725 // Preparsing checks a JavaScript program and emits preparse-data that helps | 221 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 726 // a later parsing to be faster. | 222 // a later parsing to be faster. |
| 727 // See preparse-data-format.h for the data format. | 223 // See preparse-data-format.h for the data format. |
| 728 | 224 |
| 729 // The PreParser checks that the syntax follows the grammar for JavaScript, | 225 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 730 // and collects some information about the program along the way. | 226 // and collects some information about the program along the way. |
| 731 // The grammar check is only performed in order to understand the program | 227 // The grammar check is only performed in order to understand the program |
| 732 // sufficiently to deduce some information about it, that can be used | 228 // sufficiently to deduce some information about it, that can be used |
| 733 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 229 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 734 // rather it is to speed up properly written and correct programs. | 230 // rather it is to speed up properly written and correct programs. |
| 735 // That means that contextual checks (like a label being declared where | 231 // That means that contextual checks (like a label being declared where |
| 736 // it is used) are generally omitted. | 232 // it is used) are generally omitted. |
| 737 class PreParser : public ParserBase<PreParserTraits> { | 233 class PreParser : public ParserBase { |
| 738 public: | 234 public: |
| 739 typedef PreParserIdentifier Identifier; | |
| 740 typedef PreParserExpression Expression; | |
| 741 | |
| 742 enum PreParseResult { | 235 enum PreParseResult { |
| 743 kPreParseStackOverflow, | 236 kPreParseStackOverflow, |
| 744 kPreParseSuccess | 237 kPreParseSuccess |
| 745 }; | 238 }; |
| 746 | 239 |
| 747 PreParser(Scanner* scanner, | 240 PreParser(Scanner* scanner, |
| 748 ParserRecorder* log, | 241 ParserRecorder* log, |
| 749 uintptr_t stack_limit) | 242 uintptr_t stack_limit) |
| 750 : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, NULL, this), | 243 : ParserBase(scanner, stack_limit), |
| 751 log_(log) {} | 244 log_(log), |
| 245 scope_(NULL), |
| 246 parenthesized_function_(false) { } |
| 247 |
| 248 ~PreParser() {} |
| 752 | 249 |
| 753 // Pre-parse the program from the character stream; returns true on | 250 // Pre-parse the program from the character stream; returns true on |
| 754 // success (even if parsing failed, the pre-parse data successfully | 251 // success (even if parsing failed, the pre-parse data successfully |
| 755 // captured the syntax error), and false if a stack-overflow happened | 252 // captured the syntax error), and false if a stack-overflow happened |
| 756 // during parsing. | 253 // during parsing. |
| 757 PreParseResult PreParseProgram() { | 254 PreParseResult PreParseProgram() { |
| 758 PreParserScope scope(scope_, GLOBAL_SCOPE); | 255 Scope top_scope(&scope_, kTopLevelScope); |
| 759 FunctionState top_scope(&function_state_, &scope_, &scope, NULL); | |
| 760 bool ok = true; | 256 bool ok = true; |
| 761 int start_position = scanner()->peek_location().beg_pos; | 257 int start_position = scanner()->peek_location().beg_pos; |
| 762 ParseSourceElements(Token::EOS, &ok); | 258 ParseSourceElements(Token::EOS, &ok); |
| 763 if (stack_overflow()) return kPreParseStackOverflow; | 259 if (stack_overflow()) return kPreParseStackOverflow; |
| 764 if (!ok) { | 260 if (!ok) { |
| 765 ReportUnexpectedToken(scanner()->current_token()); | 261 ReportUnexpectedToken(scanner()->current_token()); |
| 766 } else if (!scope_->is_classic_mode()) { | 262 } else if (!scope_->is_classic_mode()) { |
| 767 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); | 263 CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
| 768 } | 264 } |
| 769 return kPreParseSuccess; | 265 return kPreParseSuccess; |
| 770 } | 266 } |
| 771 | 267 |
| 772 // Parses a single function literal, from the opening parentheses before | 268 // Parses a single function literal, from the opening parentheses before |
| 773 // parameters to the closing brace after the body. | 269 // parameters to the closing brace after the body. |
| 774 // Returns a FunctionEntry describing the body of the function in enough | 270 // Returns a FunctionEntry describing the body of the function in enough |
| 775 // detail that it can be lazily compiled. | 271 // detail that it can be lazily compiled. |
| 776 // The scanner is expected to have matched the "function" or "function*" | 272 // The scanner is expected to have matched the "function" or "function*" |
| 777 // keyword and parameters, and have consumed the initial '{'. | 273 // keyword and parameters, and have consumed the initial '{'. |
| 778 // At return, unless an error occurred, the scanner is positioned before the | 274 // At return, unless an error occurred, the scanner is positioned before the |
| 779 // the final '}'. | 275 // the final '}'. |
| 780 PreParseResult PreParseLazyFunction(LanguageMode mode, | 276 PreParseResult PreParseLazyFunction(LanguageMode mode, |
| 781 bool is_generator, | 277 bool is_generator, |
| 782 ParserRecorder* log); | 278 ParserRecorder* log); |
| 783 | 279 |
| 784 private: | 280 private: |
| 785 friend class PreParserTraits; | |
| 786 | |
| 787 // These types form an algebra over syntactic categories that is just | 281 // These types form an algebra over syntactic categories that is just |
| 788 // rich enough to let us recognize and propagate the constructs that | 282 // rich enough to let us recognize and propagate the constructs that |
| 789 // are either being counted in the preparser data, or is important | 283 // are either being counted in the preparser data, or is important |
| 790 // to throw the correct syntax error exceptions. | 284 // to throw the correct syntax error exceptions. |
| 791 | 285 |
| 286 enum ScopeType { |
| 287 kTopLevelScope, |
| 288 kFunctionScope |
| 289 }; |
| 290 |
| 792 enum VariableDeclarationContext { | 291 enum VariableDeclarationContext { |
| 793 kSourceElement, | 292 kSourceElement, |
| 794 kStatement, | 293 kStatement, |
| 795 kForStatement | 294 kForStatement |
| 796 }; | 295 }; |
| 797 | 296 |
| 798 // If a list of variable declarations includes any initializers. | 297 // If a list of variable declarations includes any initializers. |
| 799 enum VariableDeclarationProperties { | 298 enum VariableDeclarationProperties { |
| 800 kHasInitializers, | 299 kHasInitializers, |
| 801 kHasNoInitializers | 300 kHasNoInitializers |
| 802 }; | 301 }; |
| 803 | 302 |
| 303 class Expression; |
| 304 |
| 305 class Identifier { |
| 306 public: |
| 307 static Identifier Default() { |
| 308 return Identifier(kUnknownIdentifier); |
| 309 } |
| 310 static Identifier Eval() { |
| 311 return Identifier(kEvalIdentifier); |
| 312 } |
| 313 static Identifier Arguments() { |
| 314 return Identifier(kArgumentsIdentifier); |
| 315 } |
| 316 static Identifier FutureReserved() { |
| 317 return Identifier(kFutureReservedIdentifier); |
| 318 } |
| 319 static Identifier FutureStrictReserved() { |
| 320 return Identifier(kFutureStrictReservedIdentifier); |
| 321 } |
| 322 static Identifier Yield() { |
| 323 return Identifier(kYieldIdentifier); |
| 324 } |
| 325 bool IsEval() { return type_ == kEvalIdentifier; } |
| 326 bool IsArguments() { return type_ == kArgumentsIdentifier; } |
| 327 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } |
| 328 bool IsYield() { return type_ == kYieldIdentifier; } |
| 329 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } |
| 330 bool IsFutureStrictReserved() { |
| 331 return type_ == kFutureStrictReservedIdentifier; |
| 332 } |
| 333 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } |
| 334 |
| 335 private: |
| 336 enum Type { |
| 337 kUnknownIdentifier, |
| 338 kFutureReservedIdentifier, |
| 339 kFutureStrictReservedIdentifier, |
| 340 kYieldIdentifier, |
| 341 kEvalIdentifier, |
| 342 kArgumentsIdentifier |
| 343 }; |
| 344 explicit Identifier(Type type) : type_(type) { } |
| 345 Type type_; |
| 346 |
| 347 friend class Expression; |
| 348 }; |
| 349 |
| 350 // Bits 0 and 1 are used to identify the type of expression: |
| 351 // If bit 0 is set, it's an identifier. |
| 352 // if bit 1 is set, it's a string literal. |
| 353 // If neither is set, it's no particular type, and both set isn't |
| 354 // use yet. |
| 355 class Expression { |
| 356 public: |
| 357 static Expression Default() { |
| 358 return Expression(kUnknownExpression); |
| 359 } |
| 360 |
| 361 static Expression FromIdentifier(Identifier id) { |
| 362 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift)); |
| 363 } |
| 364 |
| 365 static Expression StringLiteral() { |
| 366 return Expression(kUnknownStringLiteral); |
| 367 } |
| 368 |
| 369 static Expression UseStrictStringLiteral() { |
| 370 return Expression(kUseStrictString); |
| 371 } |
| 372 |
| 373 static Expression This() { |
| 374 return Expression(kThisExpression); |
| 375 } |
| 376 |
| 377 static Expression ThisProperty() { |
| 378 return Expression(kThisPropertyExpression); |
| 379 } |
| 380 |
| 381 static Expression StrictFunction() { |
| 382 return Expression(kStrictFunctionExpression); |
| 383 } |
| 384 |
| 385 bool IsIdentifier() { |
| 386 return (code_ & kIdentifierFlag) != 0; |
| 387 } |
| 388 |
| 389 // Only works corretly if it is actually an identifier expression. |
| 390 PreParser::Identifier AsIdentifier() { |
| 391 return PreParser::Identifier( |
| 392 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); |
| 393 } |
| 394 |
| 395 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } |
| 396 |
| 397 bool IsUseStrictLiteral() { |
| 398 return (code_ & kStringLiteralMask) == kUseStrictString; |
| 399 } |
| 400 |
| 401 bool IsThis() { |
| 402 return code_ == kThisExpression; |
| 403 } |
| 404 |
| 405 bool IsThisProperty() { |
| 406 return code_ == kThisPropertyExpression; |
| 407 } |
| 408 |
| 409 bool IsStrictFunction() { |
| 410 return code_ == kStrictFunctionExpression; |
| 411 } |
| 412 |
| 413 private: |
| 414 // First two/three bits are used as flags. |
| 415 // Bit 0 and 1 represent identifiers or strings literals, and are |
| 416 // mutually exclusive, but can both be absent. |
| 417 enum { |
| 418 kUnknownExpression = 0, |
| 419 // Identifiers |
| 420 kIdentifierFlag = 1, // Used to detect labels. |
| 421 kIdentifierShift = 3, |
| 422 |
| 423 kStringLiteralFlag = 2, // Used to detect directive prologue. |
| 424 kUnknownStringLiteral = kStringLiteralFlag, |
| 425 kUseStrictString = kStringLiteralFlag | 8, |
| 426 kStringLiteralMask = kUseStrictString, |
| 427 |
| 428 // Below here applies if neither identifier nor string literal. |
| 429 kThisExpression = 4, |
| 430 kThisPropertyExpression = 8, |
| 431 kStrictFunctionExpression = 12 |
| 432 }; |
| 433 |
| 434 explicit Expression(int expression_code) : code_(expression_code) { } |
| 435 |
| 436 int code_; |
| 437 }; |
| 438 |
| 804 class Statement { | 439 class Statement { |
| 805 public: | 440 public: |
| 806 static Statement Default() { | 441 static Statement Default() { |
| 807 return Statement(kUnknownStatement); | 442 return Statement(kUnknownStatement); |
| 808 } | 443 } |
| 809 | 444 |
| 810 static Statement FunctionDeclaration() { | 445 static Statement FunctionDeclaration() { |
| 811 return Statement(kFunctionDeclaration); | 446 return Statement(kFunctionDeclaration); |
| 812 } | 447 } |
| 813 | 448 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 explicit Statement(Type code) : code_(code) {} | 482 explicit Statement(Type code) : code_(code) {} |
| 848 Type code_; | 483 Type code_; |
| 849 }; | 484 }; |
| 850 | 485 |
| 851 enum SourceElements { | 486 enum SourceElements { |
| 852 kUnknownSourceElements | 487 kUnknownSourceElements |
| 853 }; | 488 }; |
| 854 | 489 |
| 855 typedef int Arguments; | 490 typedef int Arguments; |
| 856 | 491 |
| 492 class Scope { |
| 493 public: |
| 494 Scope(Scope** variable, ScopeType type) |
| 495 : variable_(variable), |
| 496 prev_(*variable), |
| 497 type_(type), |
| 498 materialized_literal_count_(0), |
| 499 expected_properties_(0), |
| 500 with_nesting_count_(0), |
| 501 language_mode_( |
| 502 (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE), |
| 503 is_generator_(false) { |
| 504 *variable = this; |
| 505 } |
| 506 ~Scope() { *variable_ = prev_; } |
| 507 void NextMaterializedLiteralIndex() { materialized_literal_count_++; } |
| 508 void AddProperty() { expected_properties_++; } |
| 509 ScopeType type() { return type_; } |
| 510 int expected_properties() { return expected_properties_; } |
| 511 int materialized_literal_count() { return materialized_literal_count_; } |
| 512 bool IsInsideWith() { return with_nesting_count_ != 0; } |
| 513 bool is_generator() { return is_generator_; } |
| 514 void set_is_generator(bool is_generator) { is_generator_ = is_generator; } |
| 515 bool is_classic_mode() { |
| 516 return language_mode_ == CLASSIC_MODE; |
| 517 } |
| 518 LanguageMode language_mode() { |
| 519 return language_mode_; |
| 520 } |
| 521 void set_language_mode(LanguageMode language_mode) { |
| 522 language_mode_ = language_mode; |
| 523 } |
| 524 |
| 525 class InsideWith { |
| 526 public: |
| 527 explicit InsideWith(Scope* scope) : scope_(scope) { |
| 528 scope->with_nesting_count_++; |
| 529 } |
| 530 |
| 531 ~InsideWith() { scope_->with_nesting_count_--; } |
| 532 |
| 533 private: |
| 534 Scope* scope_; |
| 535 DISALLOW_COPY_AND_ASSIGN(InsideWith); |
| 536 }; |
| 537 |
| 538 private: |
| 539 Scope** const variable_; |
| 540 Scope* const prev_; |
| 541 const ScopeType type_; |
| 542 int materialized_literal_count_; |
| 543 int expected_properties_; |
| 544 int with_nesting_count_; |
| 545 LanguageMode language_mode_; |
| 546 bool is_generator_; |
| 547 }; |
| 548 |
| 549 // Report syntax error |
| 550 void ReportMessageAt(Scanner::Location location, |
| 551 const char* message, |
| 552 Vector<const char*> args) { |
| 553 ReportMessageAt(location.beg_pos, |
| 554 location.end_pos, |
| 555 message, |
| 556 args.length() > 0 ? args[0] : NULL); |
| 557 } |
| 558 void ReportMessageAt(Scanner::Location location, |
| 559 const char* type, |
| 560 const char* name_opt) { |
| 561 log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt); |
| 562 } |
| 563 void ReportMessageAt(int start_pos, |
| 564 int end_pos, |
| 565 const char* type, |
| 566 const char* name_opt) { |
| 567 log_->LogMessage(start_pos, end_pos, type, name_opt); |
| 568 } |
| 569 |
| 857 // All ParseXXX functions take as the last argument an *ok parameter | 570 // All ParseXXX functions take as the last argument an *ok parameter |
| 858 // which is set to false if parsing failed; it is unchanged otherwise. | 571 // which is set to false if parsing failed; it is unchanged otherwise. |
| 859 // By making the 'exception handling' explicit, we are forced to check | 572 // By making the 'exception handling' explicit, we are forced to check |
| 860 // for failure at the call sites. | 573 // for failure at the call sites. |
| 861 Statement ParseSourceElement(bool* ok); | 574 Statement ParseSourceElement(bool* ok); |
| 862 SourceElements ParseSourceElements(int end_token, bool* ok); | 575 SourceElements ParseSourceElements(int end_token, bool* ok); |
| 863 Statement ParseStatement(bool* ok); | 576 Statement ParseStatement(bool* ok); |
| 864 Statement ParseFunctionDeclaration(bool* ok); | 577 Statement ParseFunctionDeclaration(bool* ok); |
| 865 Statement ParseBlock(bool* ok); | 578 Statement ParseBlock(bool* ok); |
| 866 Statement ParseVariableStatement(VariableDeclarationContext var_context, | 579 Statement ParseVariableStatement(VariableDeclarationContext var_context, |
| 867 bool* ok); | 580 bool* ok); |
| 868 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, | 581 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, |
| 869 VariableDeclarationProperties* decl_props, | 582 VariableDeclarationProperties* decl_props, |
| 870 int* num_decl, | 583 int* num_decl, |
| 871 bool* ok); | 584 bool* ok); |
| 872 Statement ParseExpressionOrLabelledStatement(bool* ok); | 585 Statement ParseExpressionOrLabelledStatement(bool* ok); |
| 873 Statement ParseIfStatement(bool* ok); | 586 Statement ParseIfStatement(bool* ok); |
| 874 Statement ParseContinueStatement(bool* ok); | 587 Statement ParseContinueStatement(bool* ok); |
| 875 Statement ParseBreakStatement(bool* ok); | 588 Statement ParseBreakStatement(bool* ok); |
| 876 Statement ParseReturnStatement(bool* ok); | 589 Statement ParseReturnStatement(bool* ok); |
| 877 Statement ParseWithStatement(bool* ok); | 590 Statement ParseWithStatement(bool* ok); |
| 878 Statement ParseSwitchStatement(bool* ok); | 591 Statement ParseSwitchStatement(bool* ok); |
| 879 Statement ParseDoWhileStatement(bool* ok); | 592 Statement ParseDoWhileStatement(bool* ok); |
| 880 Statement ParseWhileStatement(bool* ok); | 593 Statement ParseWhileStatement(bool* ok); |
| 881 Statement ParseForStatement(bool* ok); | 594 Statement ParseForStatement(bool* ok); |
| 882 Statement ParseThrowStatement(bool* ok); | 595 Statement ParseThrowStatement(bool* ok); |
| 883 Statement ParseTryStatement(bool* ok); | 596 Statement ParseTryStatement(bool* ok); |
| 884 Statement ParseDebuggerStatement(bool* ok); | 597 Statement ParseDebuggerStatement(bool* ok); |
| 885 | 598 |
| 599 Expression ParseExpression(bool accept_IN, bool* ok); |
| 886 Expression ParseAssignmentExpression(bool accept_IN, bool* ok); | 600 Expression ParseAssignmentExpression(bool accept_IN, bool* ok); |
| 887 Expression ParseYieldExpression(bool* ok); | 601 Expression ParseYieldExpression(bool* ok); |
| 888 Expression ParseConditionalExpression(bool accept_IN, bool* ok); | 602 Expression ParseConditionalExpression(bool accept_IN, bool* ok); |
| 889 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); | 603 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); |
| 890 Expression ParseUnaryExpression(bool* ok); | 604 Expression ParseUnaryExpression(bool* ok); |
| 891 Expression ParsePostfixExpression(bool* ok); | 605 Expression ParsePostfixExpression(bool* ok); |
| 892 Expression ParseLeftHandSideExpression(bool* ok); | 606 Expression ParseLeftHandSideExpression(bool* ok); |
| 607 Expression ParseNewExpression(bool* ok); |
| 893 Expression ParseMemberExpression(bool* ok); | 608 Expression ParseMemberExpression(bool* ok); |
| 894 Expression ParseMemberExpressionContinuation(PreParserExpression expression, | 609 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok); |
| 895 bool* ok); | 610 Expression ParsePrimaryExpression(bool* ok); |
| 896 Expression ParseMemberWithNewPrefixesExpression(bool* ok); | 611 Expression ParseArrayLiteral(bool* ok); |
| 897 Expression ParseObjectLiteral(bool* ok); | 612 Expression ParseObjectLiteral(bool* ok); |
| 613 Expression ParseRegExpLiteral(bool seen_equal, bool* ok); |
| 898 Expression ParseV8Intrinsic(bool* ok); | 614 Expression ParseV8Intrinsic(bool* ok); |
| 899 | 615 |
| 900 Arguments ParseArguments(bool* ok); | 616 Arguments ParseArguments(bool* ok); |
| 901 Expression ParseFunctionLiteral( | 617 Expression ParseFunctionLiteral( |
| 902 Identifier name, | 618 Identifier name, |
| 903 Scanner::Location function_name_location, | 619 Scanner::Location function_name_location, |
| 904 bool name_is_strict_reserved, | 620 bool name_is_strict_reserved, |
| 905 bool is_generator, | 621 bool is_generator, |
| 906 bool* ok); | 622 bool* ok); |
| 907 void ParseLazyFunctionLiteralBody(bool* ok); | 623 void ParseLazyFunctionLiteralBody(bool* ok); |
| 908 | 624 |
| 625 Identifier ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok); |
| 626 Identifier ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
| 627 bool* ok); |
| 628 Identifier ParseIdentifierName(bool* ok); |
| 629 Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 630 bool* is_set, |
| 631 bool* ok); |
| 632 |
| 909 // Logs the currently parsed literal as a symbol in the preparser data. | 633 // Logs the currently parsed literal as a symbol in the preparser data. |
| 910 void LogSymbol(); | 634 void LogSymbol(); |
| 635 // Log the currently parsed identifier. |
| 636 Identifier GetIdentifierSymbol(); |
| 911 // Log the currently parsed string literal. | 637 // Log the currently parsed string literal. |
| 912 Expression GetStringSymbol(); | 638 Expression GetStringSymbol(); |
| 913 | 639 |
| 640 void set_language_mode(LanguageMode language_mode) { |
| 641 scope_->set_language_mode(language_mode); |
| 642 } |
| 643 |
| 644 virtual bool is_classic_mode() { |
| 645 return scope_->language_mode() == CLASSIC_MODE; |
| 646 } |
| 647 |
| 648 bool is_extended_mode() { |
| 649 return scope_->language_mode() == EXTENDED_MODE; |
| 650 } |
| 651 |
| 652 LanguageMode language_mode() { return scope_->language_mode(); } |
| 653 |
| 914 bool CheckInOrOf(bool accept_OF); | 654 bool CheckInOrOf(bool accept_OF); |
| 915 | 655 |
| 916 ParserRecorder* log_; | 656 ParserRecorder* log_; |
| 657 Scope* scope_; |
| 658 bool parenthesized_function_; |
| 917 }; | 659 }; |
| 918 | 660 |
| 919 | |
| 920 template<class Traits> | |
| 921 ParserBase<Traits>::FunctionState::FunctionState( | |
| 922 FunctionState** function_state_stack, | |
| 923 typename Traits::Type::Scope** scope_stack, | |
| 924 typename Traits::Type::Scope* scope, | |
| 925 typename Traits::Type::Zone* extra_param) | |
| 926 : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize), | |
| 927 next_handler_index_(0), | |
| 928 expected_property_count_(0), | |
| 929 is_generator_(false), | |
| 930 generator_object_variable_(NULL), | |
| 931 function_state_stack_(function_state_stack), | |
| 932 outer_function_state_(*function_state_stack), | |
| 933 scope_stack_(scope_stack), | |
| 934 outer_scope_(*scope_stack), | |
| 935 isolate_(NULL), | |
| 936 saved_ast_node_id_(0), | |
| 937 factory_(extra_param) { | |
| 938 *scope_stack_ = scope; | |
| 939 *function_state_stack = this; | |
| 940 Traits::SetUpFunctionState(this, extra_param); | |
| 941 } | |
| 942 | |
| 943 | |
| 944 template<class Traits> | |
| 945 ParserBase<Traits>::FunctionState::~FunctionState() { | |
| 946 *scope_stack_ = outer_scope_; | |
| 947 *function_state_stack_ = outer_function_state_; | |
| 948 Traits::TearDownFunctionState(this); | |
| 949 } | |
| 950 | |
| 951 | |
| 952 template<class Traits> | |
| 953 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | |
| 954 // We don't report stack overflows here, to avoid increasing the | |
| 955 // stack depth even further. Instead we report it after parsing is | |
| 956 // over, in ParseProgram. | |
| 957 if (token == Token::ILLEGAL && stack_overflow()) { | |
| 958 return; | |
| 959 } | |
| 960 Scanner::Location source_location = scanner()->location(); | |
| 961 | |
| 962 // Four of the tokens are treated specially | |
| 963 switch (token) { | |
| 964 case Token::EOS: | |
| 965 return ReportMessageAt(source_location, "unexpected_eos"); | |
| 966 case Token::NUMBER: | |
| 967 return ReportMessageAt(source_location, "unexpected_token_number"); | |
| 968 case Token::STRING: | |
| 969 return ReportMessageAt(source_location, "unexpected_token_string"); | |
| 970 case Token::IDENTIFIER: | |
| 971 return ReportMessageAt(source_location, "unexpected_token_identifier"); | |
| 972 case Token::FUTURE_RESERVED_WORD: | |
| 973 return ReportMessageAt(source_location, "unexpected_reserved"); | |
| 974 case Token::YIELD: | |
| 975 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 976 return ReportMessageAt(source_location, | |
| 977 is_classic_mode() ? "unexpected_token_identifier" | |
| 978 : "unexpected_strict_reserved"); | |
| 979 default: | |
| 980 const char* name = Token::String(token); | |
| 981 ASSERT(name != NULL); | |
| 982 Traits::ReportMessageAt( | |
| 983 source_location, "unexpected_token", Vector<const char*>(&name, 1)); | |
| 984 } | |
| 985 } | |
| 986 | |
| 987 | |
| 988 template<class Traits> | |
| 989 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( | |
| 990 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | |
| 991 bool* ok) { | |
| 992 Token::Value next = Next(); | |
| 993 if (next == Token::IDENTIFIER) { | |
| 994 typename Traits::Type::Identifier name = this->GetSymbol(scanner()); | |
| 995 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | |
| 996 !is_classic_mode() && this->IsEvalOrArguments(name)) { | |
| 997 ReportMessageAt(scanner()->location(), "strict_eval_arguments"); | |
| 998 *ok = false; | |
| 999 } | |
| 1000 return name; | |
| 1001 } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
| 1002 (next == Token::YIELD && !is_generator()))) { | |
| 1003 return this->GetSymbol(scanner()); | |
| 1004 } else { | |
| 1005 this->ReportUnexpectedToken(next); | |
| 1006 *ok = false; | |
| 1007 return Traits::EmptyIdentifier(); | |
| 1008 } | |
| 1009 } | |
| 1010 | |
| 1011 | |
| 1012 template <class Traits> | |
| 1013 typename Traits::Type::Identifier ParserBase< | |
| 1014 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | |
| 1015 bool* ok) { | |
| 1016 Token::Value next = Next(); | |
| 1017 if (next == Token::IDENTIFIER) { | |
| 1018 *is_strict_reserved = false; | |
| 1019 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
| 1020 (next == Token::YIELD && !this->is_generator())) { | |
| 1021 *is_strict_reserved = true; | |
| 1022 } else { | |
| 1023 ReportUnexpectedToken(next); | |
| 1024 *ok = false; | |
| 1025 return Traits::EmptyIdentifier(); | |
| 1026 } | |
| 1027 return this->GetSymbol(scanner()); | |
| 1028 } | |
| 1029 | |
| 1030 | |
| 1031 template <class Traits> | |
| 1032 typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName( | |
| 1033 bool* ok) { | |
| 1034 Token::Value next = Next(); | |
| 1035 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | |
| 1036 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | |
| 1037 this->ReportUnexpectedToken(next); | |
| 1038 *ok = false; | |
| 1039 return Traits::EmptyIdentifier(); | |
| 1040 } | |
| 1041 return this->GetSymbol(scanner()); | |
| 1042 } | |
| 1043 | |
| 1044 | |
| 1045 template <class Traits> | |
| 1046 typename Traits::Type::Identifier | |
| 1047 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | |
| 1048 bool* is_set, | |
| 1049 bool* ok) { | |
| 1050 typename Traits::Type::Identifier result = ParseIdentifierName(ok); | |
| 1051 if (!*ok) return Traits::EmptyIdentifier(); | |
| 1052 if (scanner()->is_literal_ascii() && | |
| 1053 scanner()->literal_length() == 3) { | |
| 1054 const char* token = scanner()->literal_ascii_string().start(); | |
| 1055 *is_get = strncmp(token, "get", 3) == 0; | |
| 1056 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | |
| 1057 } | |
| 1058 return result; | |
| 1059 } | |
| 1060 | |
| 1061 | |
| 1062 template <class Traits> | |
| 1063 typename Traits::Type::Expression | |
| 1064 ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { | |
| 1065 int pos = peek_position(); | |
| 1066 if (!scanner()->ScanRegExpPattern(seen_equal)) { | |
| 1067 Next(); | |
| 1068 ReportMessage("unterminated_regexp", Vector<const char*>::empty()); | |
| 1069 *ok = false; | |
| 1070 return Traits::EmptyExpression(); | |
| 1071 } | |
| 1072 | |
| 1073 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 1074 | |
| 1075 typename Traits::Type::Identifier js_pattern = | |
| 1076 this->NextLiteralString(scanner(), TENURED); | |
| 1077 if (!scanner()->ScanRegExpFlags()) { | |
| 1078 Next(); | |
| 1079 ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); | |
| 1080 *ok = false; | |
| 1081 return Traits::EmptyExpression(); | |
| 1082 } | |
| 1083 typename Traits::Type::Identifier js_flags = | |
| 1084 this->NextLiteralString(scanner(), TENURED); | |
| 1085 Next(); | |
| 1086 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); | |
| 1087 } | |
| 1088 | |
| 1089 | |
| 1090 #define CHECK_OK ok); \ | |
| 1091 if (!*ok) return this->EmptyExpression(); \ | |
| 1092 ((void)0 | |
| 1093 #define DUMMY ) // to make indentation work | |
| 1094 #undef DUMMY | |
| 1095 | |
| 1096 template <class Traits> | |
| 1097 typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression( | |
| 1098 bool* ok) { | |
| 1099 // PrimaryExpression :: | |
| 1100 // 'this' | |
| 1101 // 'null' | |
| 1102 // 'true' | |
| 1103 // 'false' | |
| 1104 // Identifier | |
| 1105 // Number | |
| 1106 // String | |
| 1107 // ArrayLiteral | |
| 1108 // ObjectLiteral | |
| 1109 // RegExpLiteral | |
| 1110 // '(' Expression ')' | |
| 1111 | |
| 1112 int pos = peek_position(); | |
| 1113 typename Traits::Type::Expression result = this->EmptyExpression(); | |
| 1114 Token::Value token = peek(); | |
| 1115 switch (token) { | |
| 1116 case Token::THIS: { | |
| 1117 Consume(Token::THIS); | |
| 1118 result = this->ThisExpression(scope_, factory()); | |
| 1119 break; | |
| 1120 } | |
| 1121 | |
| 1122 case Token::NULL_LITERAL: | |
| 1123 case Token::TRUE_LITERAL: | |
| 1124 case Token::FALSE_LITERAL: | |
| 1125 case Token::NUMBER: | |
| 1126 Next(); | |
| 1127 result = this->ExpressionFromLiteral(token, pos, scanner(), factory()); | |
| 1128 break; | |
| 1129 | |
| 1130 case Token::IDENTIFIER: | |
| 1131 case Token::YIELD: | |
| 1132 case Token::FUTURE_STRICT_RESERVED_WORD: { | |
| 1133 // Using eval or arguments in this context is OK even in strict mode. | |
| 1134 typename Traits::Type::Identifier name = | |
| 1135 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | |
| 1136 result = | |
| 1137 this->ExpressionFromIdentifier(name, pos, scope_, factory()); | |
| 1138 break; | |
| 1139 } | |
| 1140 | |
| 1141 case Token::STRING: { | |
| 1142 Consume(Token::STRING); | |
| 1143 result = this->ExpressionFromString(pos, scanner(), factory()); | |
| 1144 break; | |
| 1145 } | |
| 1146 | |
| 1147 case Token::ASSIGN_DIV: | |
| 1148 result = this->ParseRegExpLiteral(true, CHECK_OK); | |
| 1149 break; | |
| 1150 | |
| 1151 case Token::DIV: | |
| 1152 result = this->ParseRegExpLiteral(false, CHECK_OK); | |
| 1153 break; | |
| 1154 | |
| 1155 case Token::LBRACK: | |
| 1156 result = this->ParseArrayLiteral(CHECK_OK); | |
| 1157 break; | |
| 1158 | |
| 1159 case Token::LBRACE: | |
| 1160 result = this->ParseObjectLiteral(CHECK_OK); | |
| 1161 break; | |
| 1162 | |
| 1163 case Token::LPAREN: | |
| 1164 Consume(Token::LPAREN); | |
| 1165 // Heuristically try to detect immediately called functions before | |
| 1166 // seeing the call parentheses. | |
| 1167 parenthesized_function_ = (peek() == Token::FUNCTION); | |
| 1168 result = this->ParseExpression(true, CHECK_OK); | |
| 1169 Expect(Token::RPAREN, CHECK_OK); | |
| 1170 break; | |
| 1171 | |
| 1172 case Token::MOD: | |
| 1173 if (allow_natives_syntax() || extension_ != NULL) { | |
| 1174 result = this->ParseV8Intrinsic(CHECK_OK); | |
| 1175 break; | |
| 1176 } | |
| 1177 // If we're not allowing special syntax we fall-through to the | |
| 1178 // default case. | |
| 1179 | |
| 1180 default: { | |
| 1181 Next(); | |
| 1182 ReportUnexpectedToken(token); | |
| 1183 *ok = false; | |
| 1184 } | |
| 1185 } | |
| 1186 | |
| 1187 return result; | |
| 1188 } | |
| 1189 | |
| 1190 // Precedence = 1 | |
| 1191 template <class Traits> | |
| 1192 typename Traits::Type::Expression ParserBase<Traits>::ParseExpression( | |
| 1193 bool accept_IN, bool* ok) { | |
| 1194 // Expression :: | |
| 1195 // AssignmentExpression | |
| 1196 // Expression ',' AssignmentExpression | |
| 1197 | |
| 1198 typename Traits::Type::Expression result = | |
| 1199 this->ParseAssignmentExpression(accept_IN, CHECK_OK); | |
| 1200 while (peek() == Token::COMMA) { | |
| 1201 Expect(Token::COMMA, CHECK_OK); | |
| 1202 int pos = position(); | |
| 1203 typename Traits::Type::Expression right = | |
| 1204 this->ParseAssignmentExpression(accept_IN, CHECK_OK); | |
| 1205 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | |
| 1206 } | |
| 1207 return result; | |
| 1208 } | |
| 1209 | |
| 1210 | |
| 1211 template <class Traits> | |
| 1212 typename Traits::Type::Expression ParserBase<Traits>::ParseArrayLiteral( | |
| 1213 bool* ok) { | |
| 1214 // ArrayLiteral :: | |
| 1215 // '[' Expression? (',' Expression?)* ']' | |
| 1216 | |
| 1217 int pos = peek_position(); | |
| 1218 typename Traits::Type::ExpressionList values = | |
| 1219 this->NewExpressionList(4, zone_); | |
| 1220 Expect(Token::LBRACK, CHECK_OK); | |
| 1221 while (peek() != Token::RBRACK) { | |
| 1222 typename Traits::Type::Expression elem = this->EmptyExpression(); | |
| 1223 if (peek() == Token::COMMA) { | |
| 1224 elem = this->GetLiteralTheHole(peek_position(), factory()); | |
| 1225 } else { | |
| 1226 elem = this->ParseAssignmentExpression(true, CHECK_OK); | |
| 1227 } | |
| 1228 values->Add(elem, zone_); | |
| 1229 if (peek() != Token::RBRACK) { | |
| 1230 Expect(Token::COMMA, CHECK_OK); | |
| 1231 } | |
| 1232 } | |
| 1233 Expect(Token::RBRACK, CHECK_OK); | |
| 1234 | |
| 1235 // Update the scope information before the pre-parsing bailout. | |
| 1236 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 1237 | |
| 1238 return factory()->NewArrayLiteral(values, literal_index, pos); | |
| 1239 } | |
| 1240 | |
| 1241 #undef CHECK_OK | |
| 1242 | |
| 1243 | |
| 1244 template <typename Traits> | |
| 1245 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
| 1246 Token::Value property, | |
| 1247 PropertyKind type, | |
| 1248 bool* ok) { | |
| 1249 int old; | |
| 1250 if (property == Token::NUMBER) { | |
| 1251 old = finder_.AddNumber(scanner()->literal_ascii_string(), type); | |
| 1252 } else if (scanner()->is_literal_ascii()) { | |
| 1253 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type); | |
| 1254 } else { | |
| 1255 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type); | |
| 1256 } | |
| 1257 PropertyKind old_type = static_cast<PropertyKind>(old); | |
| 1258 if (HasConflict(old_type, type)) { | |
| 1259 if (IsDataDataConflict(old_type, type)) { | |
| 1260 // Both are data properties. | |
| 1261 if (language_mode_ == CLASSIC_MODE) return; | |
| 1262 parser()->ReportMessageAt(scanner()->location(), | |
| 1263 "strict_duplicate_property"); | |
| 1264 } else if (IsDataAccessorConflict(old_type, type)) { | |
| 1265 // Both a data and an accessor property with the same name. | |
| 1266 parser()->ReportMessageAt(scanner()->location(), | |
| 1267 "accessor_data_property"); | |
| 1268 } else { | |
| 1269 ASSERT(IsAccessorAccessorConflict(old_type, type)); | |
| 1270 // Both accessors of the same type. | |
| 1271 parser()->ReportMessageAt(scanner()->location(), | |
| 1272 "accessor_get_set"); | |
| 1273 } | |
| 1274 *ok = false; | |
| 1275 } | |
| 1276 } | |
| 1277 | |
| 1278 | |
| 1279 } } // v8::internal | 661 } } // v8::internal |
| 1280 | 662 |
| 1281 #endif // V8_PREPARSER_H | 663 #endif // V8_PREPARSER_H |
| OLD | NEW |