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