| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/ast-literal-reindexer.h" | 9 #include "src/ast/ast-literal-reindexer.h" |
| 10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 } | 94 } |
| 95 | 95 |
| 96 | 96 |
| 97 RegExpBuilder::RegExpBuilder(Zone* zone) | 97 RegExpBuilder::RegExpBuilder(Zone* zone) |
| 98 : zone_(zone), | 98 : zone_(zone), |
| 99 pending_empty_(false), | 99 pending_empty_(false), |
| 100 characters_(NULL), | 100 characters_(NULL), |
| 101 terms_(), | 101 terms_(), |
| 102 alternatives_() | 102 alternatives_() |
| 103 #ifdef DEBUG | 103 #ifdef DEBUG |
| 104 , last_added_(ADD_NONE) | 104 , |
| 105 last_added_(ADD_NONE) |
| 105 #endif | 106 #endif |
| 106 {} | 107 { |
| 108 } |
| 107 | 109 |
| 108 | 110 |
| 109 void RegExpBuilder::FlushCharacters() { | 111 void RegExpBuilder::FlushCharacters() { |
| 110 pending_empty_ = false; | 112 pending_empty_ = false; |
| 111 if (characters_ != NULL) { | 113 if (characters_ != NULL) { |
| 112 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector()); | 114 RegExpTree* atom = new (zone()) RegExpAtom(characters_->ToConstVector()); |
| 113 characters_ = NULL; | 115 characters_ = NULL; |
| 114 text_.Add(atom, zone()); | 116 text_.Add(atom, zone()); |
| 115 LAST(ADD_ATOM); | 117 LAST(ADD_ATOM); |
| 116 } | 118 } |
| 117 } | 119 } |
| 118 | 120 |
| 119 | 121 |
| 120 void RegExpBuilder::FlushText() { | 122 void RegExpBuilder::FlushText() { |
| 121 FlushCharacters(); | 123 FlushCharacters(); |
| 122 int num_text = text_.length(); | 124 int num_text = text_.length(); |
| 123 if (num_text == 0) { | 125 if (num_text == 0) { |
| 124 return; | 126 return; |
| 125 } else if (num_text == 1) { | 127 } else if (num_text == 1) { |
| 126 terms_.Add(text_.last(), zone()); | 128 terms_.Add(text_.last(), zone()); |
| 127 } else { | 129 } else { |
| 128 RegExpText* text = new(zone()) RegExpText(zone()); | 130 RegExpText* text = new (zone()) RegExpText(zone()); |
| 129 for (int i = 0; i < num_text; i++) | 131 for (int i = 0; i < num_text; i++) text_.Get(i)->AppendToText(text, zone()); |
| 130 text_.Get(i)->AppendToText(text, zone()); | |
| 131 terms_.Add(text, zone()); | 132 terms_.Add(text, zone()); |
| 132 } | 133 } |
| 133 text_.Clear(); | 134 text_.Clear(); |
| 134 } | 135 } |
| 135 | 136 |
| 136 | 137 |
| 137 void RegExpBuilder::AddCharacter(uc16 c) { | 138 void RegExpBuilder::AddCharacter(uc16 c) { |
| 138 pending_empty_ = false; | 139 pending_empty_ = false; |
| 139 if (characters_ == NULL) { | 140 if (characters_ == NULL) { |
| 140 characters_ = new(zone()) ZoneList<uc16>(4, zone()); | 141 characters_ = new (zone()) ZoneList<uc16>(4, zone()); |
| 141 } | 142 } |
| 142 characters_->Add(c, zone()); | 143 characters_->Add(c, zone()); |
| 143 LAST(ADD_CHAR); | 144 LAST(ADD_CHAR); |
| 144 } | 145 } |
| 145 | 146 |
| 146 | 147 |
| 147 void RegExpBuilder::AddEmpty() { | 148 void RegExpBuilder::AddEmpty() { pending_empty_ = true; } |
| 148 pending_empty_ = true; | |
| 149 } | |
| 150 | 149 |
| 151 | 150 |
| 152 void RegExpBuilder::AddAtom(RegExpTree* term) { | 151 void RegExpBuilder::AddAtom(RegExpTree* term) { |
| 153 if (term->IsEmpty()) { | 152 if (term->IsEmpty()) { |
| 154 AddEmpty(); | 153 AddEmpty(); |
| 155 return; | 154 return; |
| 156 } | 155 } |
| 157 if (term->IsTextElement()) { | 156 if (term->IsTextElement()) { |
| 158 FlushCharacters(); | 157 FlushCharacters(); |
| 159 text_.Add(term, zone()); | 158 text_.Add(term, zone()); |
| 160 } else { | 159 } else { |
| 161 FlushText(); | 160 FlushText(); |
| 162 terms_.Add(term, zone()); | 161 terms_.Add(term, zone()); |
| 163 } | 162 } |
| 164 LAST(ADD_ATOM); | 163 LAST(ADD_ATOM); |
| 165 } | 164 } |
| 166 | 165 |
| 167 | 166 |
| 168 void RegExpBuilder::AddAssertion(RegExpTree* assert) { | 167 void RegExpBuilder::AddAssertion(RegExpTree* assert) { |
| 169 FlushText(); | 168 FlushText(); |
| 170 terms_.Add(assert, zone()); | 169 terms_.Add(assert, zone()); |
| 171 LAST(ADD_ASSERT); | 170 LAST(ADD_ASSERT); |
| 172 } | 171 } |
| 173 | 172 |
| 174 | 173 |
| 175 void RegExpBuilder::NewAlternative() { | 174 void RegExpBuilder::NewAlternative() { FlushTerms(); } |
| 176 FlushTerms(); | |
| 177 } | |
| 178 | 175 |
| 179 | 176 |
| 180 void RegExpBuilder::FlushTerms() { | 177 void RegExpBuilder::FlushTerms() { |
| 181 FlushText(); | 178 FlushText(); |
| 182 int num_terms = terms_.length(); | 179 int num_terms = terms_.length(); |
| 183 RegExpTree* alternative; | 180 RegExpTree* alternative; |
| 184 if (num_terms == 0) { | 181 if (num_terms == 0) { |
| 185 alternative = new (zone()) RegExpEmpty(); | 182 alternative = new (zone()) RegExpEmpty(); |
| 186 } else if (num_terms == 1) { | 183 } else if (num_terms == 1) { |
| 187 alternative = terms_.last(); | 184 alternative = terms_.last(); |
| 188 } else { | 185 } else { |
| 189 alternative = new(zone()) RegExpAlternative(terms_.GetList(zone())); | 186 alternative = new (zone()) RegExpAlternative(terms_.GetList(zone())); |
| 190 } | 187 } |
| 191 alternatives_.Add(alternative, zone()); | 188 alternatives_.Add(alternative, zone()); |
| 192 terms_.Clear(); | 189 terms_.Clear(); |
| 193 LAST(ADD_NONE); | 190 LAST(ADD_NONE); |
| 194 } | 191 } |
| 195 | 192 |
| 196 | 193 |
| 197 RegExpTree* RegExpBuilder::ToRegExp() { | 194 RegExpTree* RegExpBuilder::ToRegExp() { |
| 198 FlushTerms(); | 195 FlushTerms(); |
| 199 int num_alternatives = alternatives_.length(); | 196 int num_alternatives = alternatives_.length(); |
| 200 if (num_alternatives == 0) return new (zone()) RegExpEmpty(); | 197 if (num_alternatives == 0) return new (zone()) RegExpEmpty(); |
| 201 if (num_alternatives == 1) return alternatives_.last(); | 198 if (num_alternatives == 1) return alternatives_.last(); |
| 202 return new(zone()) RegExpDisjunction(alternatives_.GetList(zone())); | 199 return new (zone()) RegExpDisjunction(alternatives_.GetList(zone())); |
| 203 } | 200 } |
| 204 | 201 |
| 205 | 202 |
| 206 void RegExpBuilder::AddQuantifierToAtom( | 203 void RegExpBuilder::AddQuantifierToAtom( |
| 207 int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { | 204 int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { |
| 208 if (pending_empty_) { | 205 if (pending_empty_) { |
| 209 pending_empty_ = false; | 206 pending_empty_ = false; |
| 210 return; | 207 return; |
| 211 } | 208 } |
| 212 RegExpTree* atom; | 209 RegExpTree* atom; |
| 213 if (characters_ != NULL) { | 210 if (characters_ != NULL) { |
| 214 DCHECK(last_added_ == ADD_CHAR); | 211 DCHECK(last_added_ == ADD_CHAR); |
| 215 // Last atom was character. | 212 // Last atom was character. |
| 216 Vector<const uc16> char_vector = characters_->ToConstVector(); | 213 Vector<const uc16> char_vector = characters_->ToConstVector(); |
| 217 int num_chars = char_vector.length(); | 214 int num_chars = char_vector.length(); |
| 218 if (num_chars > 1) { | 215 if (num_chars > 1) { |
| 219 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); | 216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); |
| 220 text_.Add(new(zone()) RegExpAtom(prefix), zone()); | 217 text_.Add(new (zone()) RegExpAtom(prefix), zone()); |
| 221 char_vector = char_vector.SubVector(num_chars - 1, num_chars); | 218 char_vector = char_vector.SubVector(num_chars - 1, num_chars); |
| 222 } | 219 } |
| 223 characters_ = NULL; | 220 characters_ = NULL; |
| 224 atom = new(zone()) RegExpAtom(char_vector); | 221 atom = new (zone()) RegExpAtom(char_vector); |
| 225 FlushText(); | 222 FlushText(); |
| 226 } else if (text_.length() > 0) { | 223 } else if (text_.length() > 0) { |
| 227 DCHECK(last_added_ == ADD_ATOM); | 224 DCHECK(last_added_ == ADD_ATOM); |
| 228 atom = text_.RemoveLast(); | 225 atom = text_.RemoveLast(); |
| 229 FlushText(); | 226 FlushText(); |
| 230 } else if (terms_.length() > 0) { | 227 } else if (terms_.length() > 0) { |
| 231 DCHECK(last_added_ == ADD_ATOM); | 228 DCHECK(last_added_ == ADD_ATOM); |
| 232 atom = terms_.RemoveLast(); | 229 atom = terms_.RemoveLast(); |
| 233 if (atom->max_match() == 0) { | 230 if (atom->max_match() == 0) { |
| 234 // Guaranteed to only match an empty string. | 231 // Guaranteed to only match an empty string. |
| 235 LAST(ADD_TERM); | 232 LAST(ADD_TERM); |
| 236 if (min == 0) { | 233 if (min == 0) { |
| 237 return; | 234 return; |
| 238 } | 235 } |
| 239 terms_.Add(atom, zone()); | 236 terms_.Add(atom, zone()); |
| 240 return; | 237 return; |
| 241 } | 238 } |
| 242 } else { | 239 } else { |
| 243 // Only call immediately after adding an atom or character! | 240 // Only call immediately after adding an atom or character! |
| 244 UNREACHABLE(); | 241 UNREACHABLE(); |
| 245 return; | 242 return; |
| 246 } | 243 } |
| 247 terms_.Add( | 244 terms_.Add(new (zone()) RegExpQuantifier(min, max, quantifier_type, atom), |
| 248 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); | 245 zone()); |
| 249 LAST(ADD_TERM); | 246 LAST(ADD_TERM); |
| 250 } | 247 } |
| 251 | 248 |
| 252 | 249 |
| 253 FunctionEntry ParseData::GetFunctionEntry(int start) { | 250 FunctionEntry ParseData::GetFunctionEntry(int start) { |
| 254 // The current pre-data entry must be a FunctionEntry with the given | 251 // The current pre-data entry must be a FunctionEntry with the given |
| 255 // start position. | 252 // start position. |
| 256 if ((function_index_ + FunctionEntry::kSize <= Length()) && | 253 if ((function_index_ + FunctionEntry::kSize <= Length()) && |
| 257 (static_cast<int>(Data()[function_index_]) == start)) { | 254 (static_cast<int>(Data()[function_index_]) == start)) { |
| 258 int index = function_index_; | 255 int index = function_index_; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 279 int data_length = Length(); | 276 int data_length = Length(); |
| 280 if (data_length < PreparseDataConstants::kHeaderSize) return false; | 277 if (data_length < PreparseDataConstants::kHeaderSize) return false; |
| 281 if (Magic() != PreparseDataConstants::kMagicNumber) return false; | 278 if (Magic() != PreparseDataConstants::kMagicNumber) return false; |
| 282 if (Version() != PreparseDataConstants::kCurrentVersion) return false; | 279 if (Version() != PreparseDataConstants::kCurrentVersion) return false; |
| 283 if (HasError()) return false; | 280 if (HasError()) return false; |
| 284 // Check that the space allocated for function entries is sane. | 281 // Check that the space allocated for function entries is sane. |
| 285 int functions_size = FunctionsSize(); | 282 int functions_size = FunctionsSize(); |
| 286 if (functions_size < 0) return false; | 283 if (functions_size < 0) return false; |
| 287 if (functions_size % FunctionEntry::kSize != 0) return false; | 284 if (functions_size % FunctionEntry::kSize != 0) return false; |
| 288 // Check that the total size has room for header and function entries. | 285 // Check that the total size has room for header and function entries. |
| 289 int minimum_size = | 286 int minimum_size = PreparseDataConstants::kHeaderSize + functions_size; |
| 290 PreparseDataConstants::kHeaderSize + functions_size; | |
| 291 if (data_length < minimum_size) return false; | 287 if (data_length < minimum_size) return false; |
| 292 return true; | 288 return true; |
| 293 } | 289 } |
| 294 | 290 |
| 295 | 291 |
| 296 void ParseData::Initialize() { | 292 void ParseData::Initialize() { |
| 297 // Prepares state for use. | 293 // Prepares state for use. |
| 298 int data_length = Length(); | 294 int data_length = Length(); |
| 299 if (data_length >= PreparseDataConstants::kHeaderSize) { | 295 if (data_length >= PreparseDataConstants::kHeaderSize) { |
| 300 function_index_ = PreparseDataConstants::kHeaderSize; | 296 function_index_ = PreparseDataConstants::kHeaderSize; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // 'continue' statement targets). Upon construction, a new target is | 398 // 'continue' statement targets). Upon construction, a new target is |
| 403 // added; it is removed upon destruction. | 399 // added; it is removed upon destruction. |
| 404 | 400 |
| 405 class Target BASE_EMBEDDED { | 401 class Target BASE_EMBEDDED { |
| 406 public: | 402 public: |
| 407 Target(Target** variable, BreakableStatement* statement) | 403 Target(Target** variable, BreakableStatement* statement) |
| 408 : variable_(variable), statement_(statement), previous_(*variable) { | 404 : variable_(variable), statement_(statement), previous_(*variable) { |
| 409 *variable = this; | 405 *variable = this; |
| 410 } | 406 } |
| 411 | 407 |
| 412 ~Target() { | 408 ~Target() { *variable_ = previous_; } |
| 413 *variable_ = previous_; | |
| 414 } | |
| 415 | 409 |
| 416 Target* previous() { return previous_; } | 410 Target* previous() { return previous_; } |
| 417 BreakableStatement* statement() { return statement_; } | 411 BreakableStatement* statement() { return statement_; } |
| 418 | 412 |
| 419 private: | 413 private: |
| 420 Target** variable_; | 414 Target** variable_; |
| 421 BreakableStatement* statement_; | 415 BreakableStatement* statement_; |
| 422 Target* previous_; | 416 Target* previous_; |
| 423 }; | 417 }; |
| 424 | 418 |
| 425 | 419 |
| 426 class TargetScope BASE_EMBEDDED { | 420 class TargetScope BASE_EMBEDDED { |
| 427 public: | 421 public: |
| 428 explicit TargetScope(Target** variable) | 422 explicit TargetScope(Target** variable) |
| 429 : variable_(variable), previous_(*variable) { | 423 : variable_(variable), previous_(*variable) { |
| 430 *variable = NULL; | 424 *variable = NULL; |
| 431 } | 425 } |
| 432 | 426 |
| 433 ~TargetScope() { | 427 ~TargetScope() { *variable_ = previous_; } |
| 434 *variable_ = previous_; | |
| 435 } | |
| 436 | 428 |
| 437 private: | 429 private: |
| 438 Target** variable_; | 430 Target** variable_; |
| 439 Target* previous_; | 431 Target* previous_; |
| 440 }; | 432 }; |
| 441 | 433 |
| 442 | 434 |
| 443 // ---------------------------------------------------------------------------- | 435 // ---------------------------------------------------------------------------- |
| 444 // The CHECK_OK macro is a convenient macro to enforce error | 436 // The CHECK_OK macro is a convenient macro to enforce error |
| 445 // handling for functions that may fail (by returning !*ok). | 437 // handling for functions that may fail (by returning !*ok). |
| 446 // | 438 // |
| 447 // CAUTION: This macro appends extra statements after a call, | 439 // CAUTION: This macro appends extra statements after a call, |
| 448 // thus it must never be used where only a single statement | 440 // thus it must never be used where only a single statement |
| 449 // is correct (e.g. an if statement branch w/o braces)! | 441 // is correct (e.g. an if statement branch w/o braces)! |
| 450 | 442 |
| 451 #define CHECK_OK ok); \ | 443 #define CHECK_OK ok); \ |
| 452 if (!*ok) return NULL; \ | 444 if (!*ok) return NULL; \ |
| 453 ((void)0 | 445 ((void)0 |
| 454 #define DUMMY ) // to make indentation work | 446 #define DUMMY ) // to make indentation work |
| 455 #undef DUMMY | 447 #undef DUMMY |
| 456 | 448 |
| 457 #define CHECK_FAILED /**/); \ | 449 #define CHECK_FAILED /**/); \ |
| 458 if (failed_) return NULL; \ | 450 if (failed_) return NULL; \ |
| 459 ((void)0 | 451 ((void)0 |
| 460 #define DUMMY ) // to make indentation work | 452 #define DUMMY ) // to make indentation work |
| 461 #undef DUMMY | 453 #undef DUMMY |
| 462 | 454 |
| 463 // ---------------------------------------------------------------------------- | 455 // ---------------------------------------------------------------------------- |
| 464 // Implementation of Parser | 456 // Implementation of Parser |
| 465 | 457 |
| 466 bool ParserTraits::IsEval(const AstRawString* identifier) const { | 458 bool ParserTraits::IsEval(const AstRawString* identifier) const { |
| 467 return identifier == parser_->ast_value_factory()->eval_string(); | 459 return identifier == parser_->ast_value_factory()->eval_string(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 | 510 |
| 519 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, | 511 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, |
| 520 Expression* right) { | 512 Expression* right) { |
| 521 DCHECK(left != NULL); | 513 DCHECK(left != NULL); |
| 522 if (left->IsProperty() && right->IsFunctionLiteral()) { | 514 if (left->IsProperty() && right->IsFunctionLiteral()) { |
| 523 right->AsFunctionLiteral()->set_pretenure(); | 515 right->AsFunctionLiteral()->set_pretenure(); |
| 524 } | 516 } |
| 525 } | 517 } |
| 526 | 518 |
| 527 | 519 |
| 528 void ParserTraits::CheckPossibleEvalCall(Expression* expression, | 520 void ParserTraits::CheckPossibleEvalCall(Expression* expression, Scope* scope) { |
| 529 Scope* scope) { | |
| 530 VariableProxy* callee = expression->AsVariableProxy(); | 521 VariableProxy* callee = expression->AsVariableProxy(); |
| 531 if (callee != NULL && | 522 if (callee != NULL && |
| 532 callee->raw_name() == parser_->ast_value_factory()->eval_string()) { | 523 callee->raw_name() == parser_->ast_value_factory()->eval_string()) { |
| 533 scope->DeclarationScope()->RecordEvalCall(); | 524 scope->DeclarationScope()->RecordEvalCall(); |
| 534 scope->RecordEvalCall(); | 525 scope->RecordEvalCall(); |
| 535 } | 526 } |
| 536 } | 527 } |
| 537 | 528 |
| 538 | 529 |
| 539 Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) { | 530 Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 } | 620 } |
| 630 } | 621 } |
| 631 } | 622 } |
| 632 // Desugar '+foo' => 'foo*1' | 623 // Desugar '+foo' => 'foo*1' |
| 633 if (op == Token::ADD) { | 624 if (op == Token::ADD) { |
| 634 return factory->NewBinaryOperation( | 625 return factory->NewBinaryOperation( |
| 635 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos); | 626 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos); |
| 636 } | 627 } |
| 637 // The same idea for '-foo' => 'foo*(-1)'. | 628 // The same idea for '-foo' => 'foo*(-1)'. |
| 638 if (op == Token::SUB) { | 629 if (op == Token::SUB) { |
| 639 return factory->NewBinaryOperation( | 630 return factory->NewBinaryOperation(Token::MUL, expression, |
| 640 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos); | 631 factory->NewNumberLiteral(-1, pos), pos); |
| 641 } | 632 } |
| 642 // ...and one more time for '~foo' => 'foo^(~0)'. | 633 // ...and one more time for '~foo' => 'foo^(~0)'. |
| 643 if (op == Token::BIT_NOT) { | 634 if (op == Token::BIT_NOT) { |
| 644 return factory->NewBinaryOperation( | 635 return factory->NewBinaryOperation(Token::BIT_XOR, expression, |
| 645 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos); | 636 factory->NewNumberLiteral(~0, pos), pos); |
| 646 } | 637 } |
| 647 return factory->NewUnaryOperation(op, expression, pos); | 638 return factory->NewUnaryOperation(op, expression, pos); |
| 648 } | 639 } |
| 649 | 640 |
| 650 | 641 |
| 651 Expression* ParserTraits::NewThrowReferenceError( | 642 Expression* ParserTraits::NewThrowReferenceError( |
| 652 MessageTemplate::Template message, int pos) { | 643 MessageTemplate::Template message, int pos) { |
| 653 return NewThrowError(Runtime::kNewReferenceError, message, | 644 return NewThrowError(Runtime::kNewReferenceError, message, |
| 654 parser_->ast_value_factory()->empty_string(), pos); | 645 parser_->ast_value_factory()->empty_string(), pos); |
| 655 } | 646 } |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 | 1035 |
| 1045 // Enter 'scope' with the given parsing mode. | 1036 // Enter 'scope' with the given parsing mode. |
| 1046 ParsingModeScope parsing_mode_scope(this, parsing_mode); | 1037 ParsingModeScope parsing_mode_scope(this, parsing_mode); |
| 1047 AstNodeFactory function_factory(ast_value_factory()); | 1038 AstNodeFactory function_factory(ast_value_factory()); |
| 1048 FunctionState function_state(&function_state_, &scope_, scope, | 1039 FunctionState function_state(&function_state_, &scope_, scope, |
| 1049 kNormalFunction, &function_factory); | 1040 kNormalFunction, &function_factory); |
| 1050 | 1041 |
| 1051 // Don't count the mode in the use counters--give the program a chance | 1042 // Don't count the mode in the use counters--give the program a chance |
| 1052 // to enable script/module-wide strict/strong mode below. | 1043 // to enable script/module-wide strict/strong mode below. |
| 1053 scope_->SetLanguageMode(info->language_mode()); | 1044 scope_->SetLanguageMode(info->language_mode()); |
| 1054 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 1045 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(16, zone()); |
| 1055 bool ok = true; | 1046 bool ok = true; |
| 1056 int beg_pos = scanner()->location().beg_pos; | 1047 int beg_pos = scanner()->location().beg_pos; |
| 1057 if (info->is_module()) { | 1048 if (info->is_module()) { |
| 1058 ParseModuleItemList(body, &ok); | 1049 ParseModuleItemList(body, &ok); |
| 1059 } else { | 1050 } else { |
| 1060 ParseStatementList(body, Token::EOS, &ok); | 1051 ParseStatementList(body, Token::EOS, &ok); |
| 1061 } | 1052 } |
| 1062 | 1053 |
| 1063 // The parser will peek but not consume EOS. Our scope logically goes all | 1054 // The parser will peek but not consume EOS. Our scope logically goes all |
| 1064 // the way to the EOS, though. | 1055 // the way to the EOS, though. |
| 1065 scope->set_end_position(scanner()->peek_location().beg_pos); | 1056 scope->set_end_position(scanner()->peek_location().beg_pos); |
| 1066 | 1057 |
| 1067 if (ok && is_strict(language_mode())) { | 1058 if (ok && is_strict(language_mode())) { |
| 1068 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 1059 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
| 1069 } | 1060 } |
| 1070 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) { | 1061 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) { |
| 1071 // TODO(littledan): Function bindings on the global object that modify | 1062 // TODO(littledan): Function bindings on the global object that modify |
| 1072 // pre-existing bindings should be made writable, enumerable and | 1063 // pre-existing bindings should be made writable, enumerable and |
| 1073 // nonconfigurable if possible, whereas this code will leave attributes | 1064 // nonconfigurable if possible, whereas this code will leave attributes |
| 1074 // unchanged if the property already exists. | 1065 // unchanged if the property already exists. |
| 1075 InsertSloppyBlockFunctionVarBindings(scope, &ok); | 1066 InsertSloppyBlockFunctionVarBindings(scope, &ok); |
| 1076 } | 1067 } |
| 1077 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() || | 1068 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() || |
| 1078 allow_harmony_destructuring_bind())) { | 1069 allow_harmony_destructuring_bind())) { |
| 1079 CheckConflictingVarDeclarations(scope_, &ok); | 1070 CheckConflictingVarDeclarations(scope_, &ok); |
| 1080 } | 1071 } |
| 1081 | 1072 |
| 1082 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 1073 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
| 1083 if (body->length() != 1 || | 1074 if (body->length() != 1 || !body->at(0)->IsExpressionStatement() || |
| 1084 !body->at(0)->IsExpressionStatement() || | 1075 !body->at(0) |
| 1085 !body->at(0)->AsExpressionStatement()-> | 1076 ->AsExpressionStatement() |
| 1086 expression()->IsFunctionLiteral()) { | 1077 ->expression() |
| 1078 ->IsFunctionLiteral()) { |
| 1087 ReportMessage(MessageTemplate::kSingleFunctionLiteral); | 1079 ReportMessage(MessageTemplate::kSingleFunctionLiteral); |
| 1088 ok = false; | 1080 ok = false; |
| 1089 } | 1081 } |
| 1090 } | 1082 } |
| 1091 | 1083 |
| 1092 if (ok) { | 1084 if (ok) { |
| 1093 result = factory()->NewFunctionLiteral( | 1085 result = factory()->NewFunctionLiteral( |
| 1094 ast_value_factory()->empty_string(), ast_value_factory(), scope_, | 1086 ast_value_factory()->empty_string(), ast_value_factory(), scope_, |
| 1095 body, function_state.materialized_literal_count(), | 1087 body, function_state.materialized_literal_count(), |
| 1096 function_state.expected_property_count(), 0, | 1088 function_state.expected_property_count(), 0, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1120 timer.Start(); | 1112 timer.Start(); |
| 1121 } | 1113 } |
| 1122 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 1114 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 1123 | 1115 |
| 1124 // Initialize parser state. | 1116 // Initialize parser state. |
| 1125 source = String::Flatten(source); | 1117 source = String::Flatten(source); |
| 1126 FunctionLiteral* result; | 1118 FunctionLiteral* result; |
| 1127 if (source->IsExternalTwoByteString()) { | 1119 if (source->IsExternalTwoByteString()) { |
| 1128 ExternalTwoByteStringUtf16CharacterStream stream( | 1120 ExternalTwoByteStringUtf16CharacterStream stream( |
| 1129 Handle<ExternalTwoByteString>::cast(source), | 1121 Handle<ExternalTwoByteString>::cast(source), |
| 1130 shared_info->start_position(), | 1122 shared_info->start_position(), shared_info->end_position()); |
| 1131 shared_info->end_position()); | |
| 1132 result = ParseLazy(isolate, info, &stream); | 1123 result = ParseLazy(isolate, info, &stream); |
| 1133 } else { | 1124 } else { |
| 1134 GenericStringUtf16CharacterStream stream(source, | 1125 GenericStringUtf16CharacterStream stream( |
| 1135 shared_info->start_position(), | 1126 source, shared_info->start_position(), shared_info->end_position()); |
| 1136 shared_info->end_position()); | |
| 1137 result = ParseLazy(isolate, info, &stream); | 1127 result = ParseLazy(isolate, info, &stream); |
| 1138 } | 1128 } |
| 1139 | 1129 |
| 1140 if (FLAG_trace_parse && result != NULL) { | 1130 if (FLAG_trace_parse && result != NULL) { |
| 1141 double ms = timer.Elapsed().InMillisecondsF(); | 1131 double ms = timer.Elapsed().InMillisecondsF(); |
| 1142 base::SmartArrayPointer<char> name_chars = | 1132 base::SmartArrayPointer<char> name_chars = |
| 1143 result->debug_name()->ToCString(); | 1133 result->debug_name()->ToCString(); |
| 1144 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); | 1134 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); |
| 1145 } | 1135 } |
| 1146 return result; | 1136 return result; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1176 scope = Scope::DeserializeScopeChain(isolate, zone(), | 1166 scope = Scope::DeserializeScopeChain(isolate, zone(), |
| 1177 info->closure()->context(), scope); | 1167 info->closure()->context(), scope); |
| 1178 } | 1168 } |
| 1179 original_scope_ = scope; | 1169 original_scope_ = scope; |
| 1180 AstNodeFactory function_factory(ast_value_factory()); | 1170 AstNodeFactory function_factory(ast_value_factory()); |
| 1181 FunctionState function_state(&function_state_, &scope_, scope, | 1171 FunctionState function_state(&function_state_, &scope_, scope, |
| 1182 shared_info->kind(), &function_factory); | 1172 shared_info->kind(), &function_factory); |
| 1183 DCHECK(is_sloppy(scope->language_mode()) || | 1173 DCHECK(is_sloppy(scope->language_mode()) || |
| 1184 is_strict(info->language_mode())); | 1174 is_strict(info->language_mode())); |
| 1185 DCHECK(info->language_mode() == shared_info->language_mode()); | 1175 DCHECK(info->language_mode() == shared_info->language_mode()); |
| 1186 FunctionLiteral::FunctionType function_type = shared_info->is_expression() | 1176 FunctionLiteral::FunctionType function_type = |
| 1187 ? (shared_info->is_anonymous() | 1177 shared_info->is_expression() |
| 1188 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 1178 ? (shared_info->is_anonymous() |
| 1189 : FunctionLiteral::NAMED_EXPRESSION) | 1179 ? FunctionLiteral::ANONYMOUS_EXPRESSION |
| 1190 : FunctionLiteral::DECLARATION; | 1180 : FunctionLiteral::NAMED_EXPRESSION) |
| 1181 : FunctionLiteral::DECLARATION; |
| 1191 bool ok = true; | 1182 bool ok = true; |
| 1192 | 1183 |
| 1193 if (shared_info->is_arrow()) { | 1184 if (shared_info->is_arrow()) { |
| 1194 Scope* scope = | 1185 Scope* scope = |
| 1195 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); | 1186 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); |
| 1196 SetLanguageMode(scope, shared_info->language_mode()); | 1187 SetLanguageMode(scope, shared_info->language_mode()); |
| 1197 scope->set_start_position(shared_info->start_position()); | 1188 scope->set_start_position(shared_info->start_position()); |
| 1198 ExpressionClassifier formals_classifier; | 1189 ExpressionClassifier formals_classifier; |
| 1199 ParserFormalParameters formals(scope); | 1190 ParserFormalParameters formals(scope); |
| 1200 Checkpoint checkpoint(this); | 1191 Checkpoint checkpoint(this); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 // StatementList :: | 1262 // StatementList :: |
| 1272 // (StatementListItem)* <end_token> | 1263 // (StatementListItem)* <end_token> |
| 1273 | 1264 |
| 1274 // Allocate a target stack to use for this set of source | 1265 // Allocate a target stack to use for this set of source |
| 1275 // elements. This way, all scripts and functions get their own | 1266 // elements. This way, all scripts and functions get their own |
| 1276 // target stack thus avoiding illegal breaks and continues across | 1267 // target stack thus avoiding illegal breaks and continues across |
| 1277 // functions. | 1268 // functions. |
| 1278 TargetScope scope(&this->target_stack_); | 1269 TargetScope scope(&this->target_stack_); |
| 1279 | 1270 |
| 1280 DCHECK(body != NULL); | 1271 DCHECK(body != NULL); |
| 1281 bool directive_prologue = true; // Parsing directive prologue. | 1272 bool directive_prologue = true; // Parsing directive prologue. |
| 1282 | 1273 |
| 1283 while (peek() != end_token) { | 1274 while (peek() != end_token) { |
| 1284 if (directive_prologue && peek() != Token::STRING) { | 1275 if (directive_prologue && peek() != Token::STRING) { |
| 1285 directive_prologue = false; | 1276 directive_prologue = false; |
| 1286 } | 1277 } |
| 1287 | 1278 |
| 1288 Scanner::Location token_loc = scanner()->peek_location(); | 1279 Scanner::Location token_loc = scanner()->peek_location(); |
| 1289 Scanner::Location old_this_loc = function_state_->this_location(); | 1280 Scanner::Location old_this_loc = function_state_->this_location(); |
| 1290 Scanner::Location old_super_loc = function_state_->super_location(); | 1281 Scanner::Location old_super_loc = function_state_->super_location(); |
| 1291 Statement* stat = ParseStatementListItem(CHECK_OK); | 1282 Statement* stat = ParseStatementListItem(CHECK_OK); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1302 } | 1293 } |
| 1303 if (super_loc.beg_pos != old_super_loc.beg_pos && | 1294 if (super_loc.beg_pos != old_super_loc.beg_pos && |
| 1304 super_loc.beg_pos != token_loc.beg_pos) { | 1295 super_loc.beg_pos != token_loc.beg_pos) { |
| 1305 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper); | 1296 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper); |
| 1306 *ok = false; | 1297 *ok = false; |
| 1307 return nullptr; | 1298 return nullptr; |
| 1308 } | 1299 } |
| 1309 } | 1300 } |
| 1310 | 1301 |
| 1311 if (stat == NULL || stat->IsEmpty()) { | 1302 if (stat == NULL || stat->IsEmpty()) { |
| 1312 directive_prologue = false; // End of directive prologue. | 1303 directive_prologue = false; // End of directive prologue. |
| 1313 continue; | 1304 continue; |
| 1314 } | 1305 } |
| 1315 | 1306 |
| 1316 if (directive_prologue) { | 1307 if (directive_prologue) { |
| 1317 // A shot at a directive. | 1308 // A shot at a directive. |
| 1318 ExpressionStatement* e_stat; | 1309 ExpressionStatement* e_stat; |
| 1319 Literal* literal; | 1310 Literal* literal; |
| 1320 // Still processing directive prologue? | 1311 // Still processing directive prologue? |
| 1321 if ((e_stat = stat->AsExpressionStatement()) != NULL && | 1312 if ((e_stat = stat->AsExpressionStatement()) != NULL && |
| 1322 (literal = e_stat->expression()->AsLiteral()) != NULL && | 1313 (literal = e_stat->expression()->AsLiteral()) != NULL && |
| (...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 ZoneList<const AstRawString*>* names, bool* ok) { | 2222 ZoneList<const AstRawString*>* names, bool* ok) { |
| 2232 // FunctionDeclaration :: | 2223 // FunctionDeclaration :: |
| 2233 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 2224 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 2234 // GeneratorDeclaration :: | 2225 // GeneratorDeclaration :: |
| 2235 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 2226 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 2236 // '{' FunctionBody '}' | 2227 // '{' FunctionBody '}' |
| 2237 Expect(Token::FUNCTION, CHECK_OK); | 2228 Expect(Token::FUNCTION, CHECK_OK); |
| 2238 int pos = position(); | 2229 int pos = position(); |
| 2239 bool is_generator = Check(Token::MUL); | 2230 bool is_generator = Check(Token::MUL); |
| 2240 bool is_strict_reserved = false; | 2231 bool is_strict_reserved = false; |
| 2241 const AstRawString* name = ParseIdentifierOrStrictReservedWord( | 2232 const AstRawString* name = |
| 2242 &is_strict_reserved, CHECK_OK); | 2233 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 2243 | 2234 |
| 2244 if (fni_ != NULL) { | 2235 if (fni_ != NULL) { |
| 2245 fni_->Enter(); | 2236 fni_->Enter(); |
| 2246 fni_->PushEnclosingName(name); | 2237 fni_->PushEnclosingName(name); |
| 2247 } | 2238 } |
| 2248 FunctionLiteral* fun = ParseFunctionLiteral( | 2239 FunctionLiteral* fun = ParseFunctionLiteral( |
| 2249 name, scanner()->location(), | 2240 name, scanner()->location(), |
| 2250 is_strict_reserved ? kFunctionNameIsStrictReserved | 2241 is_strict_reserved ? kFunctionNameIsStrictReserved |
| 2251 : kFunctionNameValidityUnknown, | 2242 : kFunctionNameValidityUnknown, |
| 2252 is_generator ? FunctionKind::kGeneratorFunction | 2243 is_generator ? FunctionKind::kGeneratorFunction |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2349 } | 2340 } |
| 2350 | 2341 |
| 2351 | 2342 |
| 2352 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { | 2343 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { |
| 2353 // The harmony mode uses block elements instead of statements. | 2344 // The harmony mode uses block elements instead of statements. |
| 2354 // | 2345 // |
| 2355 // Block :: | 2346 // Block :: |
| 2356 // '{' StatementList '}' | 2347 // '{' StatementList '}' |
| 2357 | 2348 |
| 2358 // Construct block expecting 16 statements. | 2349 // Construct block expecting 16 statements. |
| 2359 Block* body = | 2350 Block* body = factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); |
| 2360 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); | |
| 2361 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2351 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 2362 | 2352 |
| 2363 // Parse the statements and collect escaping labels. | 2353 // Parse the statements and collect escaping labels. |
| 2364 Expect(Token::LBRACE, CHECK_OK); | 2354 Expect(Token::LBRACE, CHECK_OK); |
| 2365 block_scope->set_start_position(scanner()->location().beg_pos); | 2355 block_scope->set_start_position(scanner()->location().beg_pos); |
| 2366 { BlockState block_state(&scope_, block_scope); | 2356 { |
| 2357 BlockState block_state(&scope_, block_scope); |
| 2367 Target target(&this->target_stack_, body); | 2358 Target target(&this->target_stack_, body); |
| 2368 | 2359 |
| 2369 while (peek() != Token::RBRACE) { | 2360 while (peek() != Token::RBRACE) { |
| 2370 Statement* stat = ParseStatementListItem(CHECK_OK); | 2361 Statement* stat = ParseStatementListItem(CHECK_OK); |
| 2371 if (stat && !stat->IsEmpty()) { | 2362 if (stat && !stat->IsEmpty()) { |
| 2372 body->statements()->Add(stat, zone()); | 2363 body->statements()->Add(stat, zone()); |
| 2373 } | 2364 } |
| 2374 } | 2365 } |
| 2375 } | 2366 } |
| 2376 Expect(Token::RBRACE, CHECK_OK); | 2367 Expect(Token::RBRACE, CHECK_OK); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2585 | 2576 |
| 2586 parsing_result->bindings_loc = | 2577 parsing_result->bindings_loc = |
| 2587 Scanner::Location(bindings_start, scanner()->location().end_pos); | 2578 Scanner::Location(bindings_start, scanner()->location().end_pos); |
| 2588 } | 2579 } |
| 2589 | 2580 |
| 2590 | 2581 |
| 2591 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 2582 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, |
| 2592 const AstRawString* label) { | 2583 const AstRawString* label) { |
| 2593 DCHECK(label != NULL); | 2584 DCHECK(label != NULL); |
| 2594 if (labels != NULL) { | 2585 if (labels != NULL) { |
| 2595 for (int i = labels->length(); i-- > 0; ) { | 2586 for (int i = labels->length(); i-- > 0;) { |
| 2596 if (labels->at(i) == label) { | 2587 if (labels->at(i) == label) { |
| 2597 return true; | 2588 return true; |
| 2598 } | 2589 } |
| 2599 } | 2590 } |
| 2600 } | 2591 } |
| 2601 return false; | 2592 return false; |
| 2602 } | 2593 } |
| 2603 | 2594 |
| 2604 | 2595 |
| 2605 Statement* Parser::ParseExpressionOrLabelledStatement( | 2596 Statement* Parser::ParseExpressionOrLabelledStatement( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2617 case Token::FUNCTION: | 2608 case Token::FUNCTION: |
| 2618 case Token::LBRACE: | 2609 case Token::LBRACE: |
| 2619 UNREACHABLE(); // Always handled by the callers. | 2610 UNREACHABLE(); // Always handled by the callers. |
| 2620 case Token::CLASS: | 2611 case Token::CLASS: |
| 2621 ReportUnexpectedToken(Next()); | 2612 ReportUnexpectedToken(Next()); |
| 2622 *ok = false; | 2613 *ok = false; |
| 2623 return nullptr; | 2614 return nullptr; |
| 2624 | 2615 |
| 2625 case Token::THIS: | 2616 case Token::THIS: |
| 2626 if (!FLAG_strong_this) break; | 2617 if (!FLAG_strong_this) break; |
| 2627 // Fall through. | 2618 // Fall through. |
| 2628 case Token::SUPER: | 2619 case Token::SUPER: |
| 2629 if (is_strong(language_mode()) && | 2620 if (is_strong(language_mode()) && |
| 2630 IsClassConstructor(function_state_->kind())) { | 2621 IsClassConstructor(function_state_->kind())) { |
| 2631 bool is_this = peek() == Token::THIS; | 2622 bool is_this = peek() == Token::THIS; |
| 2632 Expression* expr; | 2623 Expression* expr; |
| 2633 ExpressionClassifier classifier; | 2624 ExpressionClassifier classifier; |
| 2634 if (is_this) { | 2625 if (is_this) { |
| 2635 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); | 2626 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); |
| 2636 } else { | 2627 } else { |
| 2637 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); | 2628 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2658 } | 2649 } |
| 2659 break; | 2650 break; |
| 2660 | 2651 |
| 2661 default: | 2652 default: |
| 2662 break; | 2653 break; |
| 2663 } | 2654 } |
| 2664 | 2655 |
| 2665 bool starts_with_idenfifier = peek_any_identifier(); | 2656 bool starts_with_idenfifier = peek_any_identifier(); |
| 2666 Expression* expr = ParseExpression(true, CHECK_OK); | 2657 Expression* expr = ParseExpression(true, CHECK_OK); |
| 2667 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | 2658 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && |
| 2668 expr->AsVariableProxy() != NULL && | 2659 expr->AsVariableProxy() != NULL && !expr->AsVariableProxy()->is_this()) { |
| 2669 !expr->AsVariableProxy()->is_this()) { | |
| 2670 // Expression is a single identifier, and not, e.g., a parenthesized | 2660 // Expression is a single identifier, and not, e.g., a parenthesized |
| 2671 // identifier. | 2661 // identifier. |
| 2672 VariableProxy* var = expr->AsVariableProxy(); | 2662 VariableProxy* var = expr->AsVariableProxy(); |
| 2673 const AstRawString* label = var->raw_name(); | 2663 const AstRawString* label = var->raw_name(); |
| 2674 // TODO(1240780): We don't check for redeclaration of labels | 2664 // TODO(1240780): We don't check for redeclaration of labels |
| 2675 // during preparsing since keeping track of the set of active | 2665 // during preparsing since keeping track of the set of active |
| 2676 // labels requires nontrivial changes to the way scopes are | 2666 // labels requires nontrivial changes to the way scopes are |
| 2677 // structured. However, these are probably changes we want to | 2667 // structured. However, these are probably changes we want to |
| 2678 // make later anyway so we should go back and fix this then. | 2668 // make later anyway so we should go back and fix this then. |
| 2679 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | 2669 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
| 2680 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label); | 2670 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label); |
| 2681 *ok = false; | 2671 *ok = false; |
| 2682 return NULL; | 2672 return NULL; |
| 2683 } | 2673 } |
| 2684 if (labels == NULL) { | 2674 if (labels == NULL) { |
| 2685 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); | 2675 labels = new (zone()) ZoneList<const AstRawString*>(4, zone()); |
| 2686 } | 2676 } |
| 2687 labels->Add(label, zone()); | 2677 labels->Add(label, zone()); |
| 2688 // Remove the "ghost" variable that turned out to be a label | 2678 // Remove the "ghost" variable that turned out to be a label |
| 2689 // from the top scope. This way, we don't try to resolve it | 2679 // from the top scope. This way, we don't try to resolve it |
| 2690 // during the scope processing. | 2680 // during the scope processing. |
| 2691 scope_->RemoveUnresolved(var); | 2681 scope_->RemoveUnresolved(var); |
| 2692 Expect(Token::COLON, CHECK_OK); | 2682 Expect(Token::COLON, CHECK_OK); |
| 2693 return ParseStatement(labels, ok); | 2683 return ParseStatement(labels, ok); |
| 2694 } | 2684 } |
| 2695 | 2685 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 Expression* condition = ParseExpression(true, CHECK_OK); | 2721 Expression* condition = ParseExpression(true, CHECK_OK); |
| 2732 Expect(Token::RPAREN, CHECK_OK); | 2722 Expect(Token::RPAREN, CHECK_OK); |
| 2733 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); | 2723 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); |
| 2734 Statement* else_statement = NULL; | 2724 Statement* else_statement = NULL; |
| 2735 if (peek() == Token::ELSE) { | 2725 if (peek() == Token::ELSE) { |
| 2736 Next(); | 2726 Next(); |
| 2737 else_statement = ParseSubStatement(labels, CHECK_OK); | 2727 else_statement = ParseSubStatement(labels, CHECK_OK); |
| 2738 } else { | 2728 } else { |
| 2739 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 2729 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
| 2740 } | 2730 } |
| 2741 return factory()->NewIfStatement( | 2731 return factory()->NewIfStatement(condition, then_statement, else_statement, |
| 2742 condition, then_statement, else_statement, pos); | 2732 pos); |
| 2743 } | 2733 } |
| 2744 | 2734 |
| 2745 | 2735 |
| 2746 Statement* Parser::ParseContinueStatement(bool* ok) { | 2736 Statement* Parser::ParseContinueStatement(bool* ok) { |
| 2747 // ContinueStatement :: | 2737 // ContinueStatement :: |
| 2748 // 'continue' Identifier? ';' | 2738 // 'continue' Identifier? ';' |
| 2749 | 2739 |
| 2750 int pos = peek_position(); | 2740 int pos = peek_position(); |
| 2751 Expect(Token::CONTINUE, CHECK_OK); | 2741 Expect(Token::CONTINUE, CHECK_OK); |
| 2752 const AstRawString* label = NULL; | 2742 const AstRawString* label = NULL; |
| 2753 Token::Value tok = peek(); | 2743 Token::Value tok = peek(); |
| 2754 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 2744 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
| 2755 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 2745 tok != Token::RBRACE && tok != Token::EOS) { |
| 2756 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 2746 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 2757 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2747 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 2758 } | 2748 } |
| 2759 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); | 2749 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); |
| 2760 if (target == NULL) { | 2750 if (target == NULL) { |
| 2761 // Illegal continue statement. | 2751 // Illegal continue statement. |
| 2762 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; | 2752 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; |
| 2763 if (label != NULL) { | 2753 if (label != NULL) { |
| 2764 message = MessageTemplate::kUnknownLabel; | 2754 message = MessageTemplate::kUnknownLabel; |
| 2765 } | 2755 } |
| 2766 ParserTraits::ReportMessage(message, label); | 2756 ParserTraits::ReportMessage(message, label); |
| 2767 *ok = false; | 2757 *ok = false; |
| 2768 return NULL; | 2758 return NULL; |
| 2769 } | 2759 } |
| 2770 ExpectSemicolon(CHECK_OK); | 2760 ExpectSemicolon(CHECK_OK); |
| 2771 return factory()->NewContinueStatement(target, pos); | 2761 return factory()->NewContinueStatement(target, pos); |
| 2772 } | 2762 } |
| 2773 | 2763 |
| 2774 | 2764 |
| 2775 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, | 2765 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, |
| 2776 bool* ok) { | 2766 bool* ok) { |
| 2777 // BreakStatement :: | 2767 // BreakStatement :: |
| 2778 // 'break' Identifier? ';' | 2768 // 'break' Identifier? ';' |
| 2779 | 2769 |
| 2780 int pos = peek_position(); | 2770 int pos = peek_position(); |
| 2781 Expect(Token::BREAK, CHECK_OK); | 2771 Expect(Token::BREAK, CHECK_OK); |
| 2782 const AstRawString* label = NULL; | 2772 const AstRawString* label = NULL; |
| 2783 Token::Value tok = peek(); | 2773 Token::Value tok = peek(); |
| 2784 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 2774 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
| 2785 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 2775 tok != Token::RBRACE && tok != Token::EOS) { |
| 2786 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 2776 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 2787 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2777 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 2788 } | 2778 } |
| 2789 // Parse labeled break statements that target themselves into | 2779 // Parse labeled break statements that target themselves into |
| 2790 // empty statements, e.g. 'l1: l2: l3: break l2;' | 2780 // empty statements, e.g. 'l1: l2: l3: break l2;' |
| 2791 if (label != NULL && ContainsLabel(labels, label)) { | 2781 if (label != NULL && ContainsLabel(labels, label)) { |
| 2792 ExpectSemicolon(CHECK_OK); | 2782 ExpectSemicolon(CHECK_OK); |
| 2793 return factory()->NewEmptyStatement(pos); | 2783 return factory()->NewEmptyStatement(pos); |
| 2794 } | 2784 } |
| 2795 BreakableStatement* target = NULL; | 2785 BreakableStatement* target = NULL; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2816 // Consume the return token. It is necessary to do that before | 2806 // Consume the return token. It is necessary to do that before |
| 2817 // reporting any errors on it, because of the way errors are | 2807 // reporting any errors on it, because of the way errors are |
| 2818 // reported (underlining). | 2808 // reported (underlining). |
| 2819 Expect(Token::RETURN, CHECK_OK); | 2809 Expect(Token::RETURN, CHECK_OK); |
| 2820 Scanner::Location loc = scanner()->location(); | 2810 Scanner::Location loc = scanner()->location(); |
| 2821 function_state_->set_return_location(loc); | 2811 function_state_->set_return_location(loc); |
| 2822 | 2812 |
| 2823 Token::Value tok = peek(); | 2813 Token::Value tok = peek(); |
| 2824 Statement* result; | 2814 Statement* result; |
| 2825 Expression* return_value; | 2815 Expression* return_value; |
| 2826 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 2816 if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || |
| 2827 tok == Token::SEMICOLON || | 2817 tok == Token::RBRACE || tok == Token::EOS) { |
| 2828 tok == Token::RBRACE || | |
| 2829 tok == Token::EOS) { | |
| 2830 if (IsSubclassConstructor(function_state_->kind())) { | 2818 if (IsSubclassConstructor(function_state_->kind())) { |
| 2831 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | 2819 return_value = ThisExpression(scope_, factory(), loc.beg_pos); |
| 2832 } else { | 2820 } else { |
| 2833 return_value = GetLiteralUndefined(position()); | 2821 return_value = GetLiteralUndefined(position()); |
| 2834 } | 2822 } |
| 2835 } else { | 2823 } else { |
| 2836 if (is_strong(language_mode()) && | 2824 if (is_strong(language_mode()) && |
| 2837 IsClassConstructor(function_state_->kind())) { | 2825 IsClassConstructor(function_state_->kind())) { |
| 2838 int pos = peek_position(); | 2826 int pos = peek_position(); |
| 2839 ReportMessageAt(Scanner::Location(pos, pos + 1), | 2827 ReportMessageAt(Scanner::Location(pos, pos + 1), |
| 2840 MessageTemplate::kStrongConstructorReturnValue); | 2828 MessageTemplate::kStrongConstructorReturnValue); |
| 2841 *ok = false; | 2829 *ok = false; |
| 2842 return NULL; | 2830 return NULL; |
| 2843 } | 2831 } |
| 2844 | 2832 |
| 2845 int pos = peek_position(); | 2833 int pos = peek_position(); |
| 2846 return_value = ParseExpression(true, CHECK_OK); | 2834 return_value = ParseExpression(true, CHECK_OK); |
| 2847 | 2835 |
| 2848 if (IsSubclassConstructor(function_state_->kind())) { | 2836 if (IsSubclassConstructor(function_state_->kind())) { |
| 2849 // For subclass constructors we need to return this in case of undefined | 2837 // For subclass constructors we need to return this in case of undefined |
| 2850 // and throw an exception in case of a non object. | 2838 // and throw an exception in case of a non object. |
| 2851 // | 2839 // |
| 2852 // return expr; | 2840 // return expr; |
| 2853 // | 2841 // |
| 2854 // Is rewritten as: | 2842 // Is rewritten as: |
| 2855 // | 2843 // |
| 2856 // return (temp = expr) === undefined ? this : | 2844 // return (temp = expr) === undefined ? this : |
| 2857 // %_IsSpecObject(temp) ? temp : throw new TypeError(...); | 2845 // %_IsSpecObject(temp) ? temp : throw new TypeError(...); |
| 2858 Variable* temp = scope_->NewTemporary( | 2846 Variable* temp = |
| 2859 ast_value_factory()->empty_string()); | 2847 scope_->NewTemporary(ast_value_factory()->empty_string()); |
| 2860 Assignment* assign = factory()->NewAssignment( | 2848 Assignment* assign = factory()->NewAssignment( |
| 2861 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); | 2849 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); |
| 2862 | 2850 |
| 2863 Expression* throw_expression = | 2851 Expression* throw_expression = |
| 2864 NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn, | 2852 NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn, |
| 2865 ast_value_factory()->empty_string(), pos); | 2853 ast_value_factory()->empty_string(), pos); |
| 2866 | 2854 |
| 2867 // %_IsSpecObject(temp) | 2855 // %_IsSpecObject(temp) |
| 2868 ZoneList<Expression*>* is_spec_object_args = | 2856 ZoneList<Expression*>* is_spec_object_args = |
| 2869 new (zone()) ZoneList<Expression*>(1, zone()); | 2857 new (zone()) ZoneList<Expression*>(1, zone()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2885 return_value = factory()->NewConditional( | 2873 return_value = factory()->NewConditional( |
| 2886 is_undefined, ThisExpression(scope_, factory(), pos), | 2874 is_undefined, ThisExpression(scope_, factory(), pos), |
| 2887 is_object_conditional, pos); | 2875 is_object_conditional, pos); |
| 2888 } | 2876 } |
| 2889 } | 2877 } |
| 2890 ExpectSemicolon(CHECK_OK); | 2878 ExpectSemicolon(CHECK_OK); |
| 2891 | 2879 |
| 2892 if (is_generator()) { | 2880 if (is_generator()) { |
| 2893 Expression* generator = factory()->NewVariableProxy( | 2881 Expression* generator = factory()->NewVariableProxy( |
| 2894 function_state_->generator_object_variable()); | 2882 function_state_->generator_object_variable()); |
| 2895 Expression* yield = factory()->NewYield( | 2883 Expression* yield = factory()->NewYield(generator, return_value, |
| 2896 generator, return_value, Yield::kFinal, loc.beg_pos); | 2884 Yield::kFinal, loc.beg_pos); |
| 2897 result = factory()->NewExpressionStatement(yield, loc.beg_pos); | 2885 result = factory()->NewExpressionStatement(yield, loc.beg_pos); |
| 2898 } else { | 2886 } else { |
| 2899 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2887 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
| 2900 } | 2888 } |
| 2901 | 2889 |
| 2902 Scope* decl_scope = scope_->DeclarationScope(); | 2890 Scope* decl_scope = scope_->DeclarationScope(); |
| 2903 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | 2891 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
| 2904 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | 2892 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
| 2905 *ok = false; | 2893 *ok = false; |
| 2906 return NULL; | 2894 return NULL; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2923 return NULL; | 2911 return NULL; |
| 2924 } | 2912 } |
| 2925 | 2913 |
| 2926 Expect(Token::LPAREN, CHECK_OK); | 2914 Expect(Token::LPAREN, CHECK_OK); |
| 2927 Expression* expr = ParseExpression(true, CHECK_OK); | 2915 Expression* expr = ParseExpression(true, CHECK_OK); |
| 2928 Expect(Token::RPAREN, CHECK_OK); | 2916 Expect(Token::RPAREN, CHECK_OK); |
| 2929 | 2917 |
| 2930 scope_->DeclarationScope()->RecordWithStatement(); | 2918 scope_->DeclarationScope()->RecordWithStatement(); |
| 2931 Scope* with_scope = NewScope(scope_, WITH_SCOPE); | 2919 Scope* with_scope = NewScope(scope_, WITH_SCOPE); |
| 2932 Block* body; | 2920 Block* body; |
| 2933 { BlockState block_state(&scope_, with_scope); | 2921 { |
| 2922 BlockState block_state(&scope_, with_scope); |
| 2934 with_scope->set_start_position(scanner()->peek_location().beg_pos); | 2923 with_scope->set_start_position(scanner()->peek_location().beg_pos); |
| 2935 | 2924 |
| 2936 // The body of the with statement must be enclosed in an additional | 2925 // The body of the with statement must be enclosed in an additional |
| 2937 // lexical scope in case the body is a FunctionDeclaration. | 2926 // lexical scope in case the body is a FunctionDeclaration. |
| 2938 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); | 2927 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); |
| 2939 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2928 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 2940 block_scope->set_start_position(scanner()->location().beg_pos); | 2929 block_scope->set_start_position(scanner()->location().beg_pos); |
| 2941 { | 2930 { |
| 2942 BlockState block_state(&scope_, block_scope); | 2931 BlockState block_state(&scope_, block_scope); |
| 2943 Target target(&this->target_stack_, body); | 2932 Target target(&this->target_stack_, body); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2968 if (*default_seen_ptr) { | 2957 if (*default_seen_ptr) { |
| 2969 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch); | 2958 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch); |
| 2970 *ok = false; | 2959 *ok = false; |
| 2971 return NULL; | 2960 return NULL; |
| 2972 } | 2961 } |
| 2973 *default_seen_ptr = true; | 2962 *default_seen_ptr = true; |
| 2974 } | 2963 } |
| 2975 Expect(Token::COLON, CHECK_OK); | 2964 Expect(Token::COLON, CHECK_OK); |
| 2976 int pos = position(); | 2965 int pos = position(); |
| 2977 ZoneList<Statement*>* statements = | 2966 ZoneList<Statement*>* statements = |
| 2978 new(zone()) ZoneList<Statement*>(5, zone()); | 2967 new (zone()) ZoneList<Statement*>(5, zone()); |
| 2979 Statement* stat = NULL; | 2968 Statement* stat = NULL; |
| 2980 while (peek() != Token::CASE && | 2969 while (peek() != Token::CASE && peek() != Token::DEFAULT && |
| 2981 peek() != Token::DEFAULT && | |
| 2982 peek() != Token::RBRACE) { | 2970 peek() != Token::RBRACE) { |
| 2983 stat = ParseStatementListItem(CHECK_OK); | 2971 stat = ParseStatementListItem(CHECK_OK); |
| 2984 statements->Add(stat, zone()); | 2972 statements->Add(stat, zone()); |
| 2985 } | 2973 } |
| 2986 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() && | 2974 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() && |
| 2987 peek() != Token::RBRACE) { | 2975 peek() != Token::RBRACE) { |
| 2988 ReportMessageAt(scanner()->location(), | 2976 ReportMessageAt(scanner()->location(), |
| 2989 MessageTemplate::kStrongSwitchFallthrough); | 2977 MessageTemplate::kStrongSwitchFallthrough); |
| 2990 *ok = false; | 2978 *ok = false; |
| 2991 return NULL; | 2979 return NULL; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3080 Expect(Token::THROW, CHECK_OK); | 3068 Expect(Token::THROW, CHECK_OK); |
| 3081 int pos = position(); | 3069 int pos = position(); |
| 3082 if (scanner()->HasAnyLineTerminatorBeforeNext()) { | 3070 if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 3083 ReportMessage(MessageTemplate::kNewlineAfterThrow); | 3071 ReportMessage(MessageTemplate::kNewlineAfterThrow); |
| 3084 *ok = false; | 3072 *ok = false; |
| 3085 return NULL; | 3073 return NULL; |
| 3086 } | 3074 } |
| 3087 Expression* exception = ParseExpression(true, CHECK_OK); | 3075 Expression* exception = ParseExpression(true, CHECK_OK); |
| 3088 ExpectSemicolon(CHECK_OK); | 3076 ExpectSemicolon(CHECK_OK); |
| 3089 | 3077 |
| 3090 return factory()->NewExpressionStatement( | 3078 return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos), |
| 3091 factory()->NewThrow(exception, pos), pos); | 3079 pos); |
| 3092 } | 3080 } |
| 3093 | 3081 |
| 3094 | 3082 |
| 3095 TryStatement* Parser::ParseTryStatement(bool* ok) { | 3083 TryStatement* Parser::ParseTryStatement(bool* ok) { |
| 3096 // TryStatement :: | 3084 // TryStatement :: |
| 3097 // 'try' Block Catch | 3085 // 'try' Block Catch |
| 3098 // 'try' Block Finally | 3086 // 'try' Block Finally |
| 3099 // 'try' Block Catch Finally | 3087 // 'try' Block Catch Finally |
| 3100 // | 3088 // |
| 3101 // Catch :: | 3089 // Catch :: |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3313 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3301 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
| 3314 | 3302 |
| 3315 return factory()->NewBinaryOperation( | 3303 return factory()->NewBinaryOperation( |
| 3316 Token::AND, | 3304 Token::AND, |
| 3317 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3305 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
| 3318 throw_call, pos); | 3306 throw_call, pos); |
| 3319 } | 3307 } |
| 3320 | 3308 |
| 3321 | 3309 |
| 3322 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3310 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
| 3323 Expression* each, | 3311 Expression* each, Expression* subject, |
| 3324 Expression* subject, | |
| 3325 Statement* body) { | 3312 Statement* body) { |
| 3326 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3313 ForOfStatement* for_of = stmt->AsForOfStatement(); |
| 3327 | 3314 |
| 3328 if (for_of != NULL) { | 3315 if (for_of != NULL) { |
| 3329 Variable* iterator = scope_->NewTemporary( | 3316 Variable* iterator = |
| 3330 ast_value_factory()->dot_iterator_string()); | 3317 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); |
| 3331 Variable* result = scope_->NewTemporary( | 3318 Variable* result = |
| 3332 ast_value_factory()->dot_result_string()); | 3319 scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
| 3333 | 3320 |
| 3334 Expression* assign_iterator; | 3321 Expression* assign_iterator; |
| 3335 Expression* next_result; | 3322 Expression* next_result; |
| 3336 Expression* result_done; | 3323 Expression* result_done; |
| 3337 Expression* assign_each; | 3324 Expression* assign_each; |
| 3338 | 3325 |
| 3339 // iterator = subject[Symbol.iterator]() | 3326 // iterator = subject[Symbol.iterator]() |
| 3340 assign_iterator = factory()->NewAssignment( | 3327 assign_iterator = factory()->NewAssignment( |
| 3341 Token::ASSIGN, factory()->NewVariableProxy(iterator), | 3328 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
| 3342 GetIterator(subject, factory()), subject->position()); | 3329 GetIterator(subject, factory()), subject->position()); |
| 3343 | 3330 |
| 3344 // !%_IsSpecObject(result = iterator.next()) && | 3331 // !%_IsSpecObject(result = iterator.next()) && |
| 3345 // %ThrowIteratorResultNotAnObject(result) | 3332 // %ThrowIteratorResultNotAnObject(result) |
| 3346 { | 3333 { |
| 3347 // result = iterator.next() | 3334 // result = iterator.next() |
| 3348 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | 3335 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
| 3349 next_result = | 3336 next_result = |
| 3350 BuildIteratorNextResult(iterator_proxy, result, subject->position()); | 3337 BuildIteratorNextResult(iterator_proxy, result, subject->position()); |
| 3351 } | 3338 } |
| 3352 | 3339 |
| 3353 // result.done | 3340 // result.done |
| 3354 { | 3341 { |
| 3355 Expression* done_literal = factory()->NewStringLiteral( | 3342 Expression* done_literal = factory()->NewStringLiteral( |
| 3356 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | 3343 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
| 3357 Expression* result_proxy = factory()->NewVariableProxy(result); | 3344 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3358 result_done = factory()->NewProperty( | 3345 result_done = factory()->NewProperty(result_proxy, done_literal, |
| 3359 result_proxy, done_literal, RelocInfo::kNoPosition); | 3346 RelocInfo::kNoPosition); |
| 3360 } | 3347 } |
| 3361 | 3348 |
| 3362 // each = result.value | 3349 // each = result.value |
| 3363 { | 3350 { |
| 3364 Expression* value_literal = factory()->NewStringLiteral( | 3351 Expression* value_literal = factory()->NewStringLiteral( |
| 3365 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | 3352 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
| 3366 Expression* result_proxy = factory()->NewVariableProxy(result); | 3353 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3367 Expression* result_value = factory()->NewProperty( | 3354 Expression* result_value = factory()->NewProperty( |
| 3368 result_proxy, value_literal, RelocInfo::kNoPosition); | 3355 result_proxy, value_literal, RelocInfo::kNoPosition); |
| 3369 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | 3356 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
| 3370 RelocInfo::kNoPosition); | 3357 RelocInfo::kNoPosition); |
| 3371 } | 3358 } |
| 3372 | 3359 |
| 3373 for_of->Initialize(each, subject, body, | 3360 for_of->Initialize(each, subject, body, assign_iterator, next_result, |
| 3374 assign_iterator, | 3361 result_done, assign_each); |
| 3375 next_result, | |
| 3376 result_done, | |
| 3377 assign_each); | |
| 3378 } else { | 3362 } else { |
| 3379 stmt->Initialize(each, subject, body); | 3363 stmt->Initialize(each, subject, body); |
| 3380 } | 3364 } |
| 3381 } | 3365 } |
| 3382 | 3366 |
| 3383 | 3367 |
| 3384 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3368 Statement* Parser::DesugarLexicalBindingsInForStatement( |
| 3385 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, | 3369 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, |
| 3386 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3370 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
| 3387 Statement* body, bool* ok) { | 3371 Statement* body, bool* ok) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3435 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 3419 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
| 3436 | 3420 |
| 3437 // For each lexical variable x: | 3421 // For each lexical variable x: |
| 3438 // make statement: temp_x = x. | 3422 // make statement: temp_x = x. |
| 3439 for (int i = 0; i < names->length(); i++) { | 3423 for (int i = 0; i < names->length(); i++) { |
| 3440 VariableProxy* proxy = NewUnresolved(names->at(i), LET); | 3424 VariableProxy* proxy = NewUnresolved(names->at(i), LET); |
| 3441 Variable* temp = scope_->NewTemporary(temp_name); | 3425 Variable* temp = scope_->NewTemporary(temp_name); |
| 3442 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3426 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
| 3443 Assignment* assignment = factory()->NewAssignment( | 3427 Assignment* assignment = factory()->NewAssignment( |
| 3444 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | 3428 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
| 3445 Statement* assignment_statement = factory()->NewExpressionStatement( | 3429 Statement* assignment_statement = |
| 3446 assignment, RelocInfo::kNoPosition); | 3430 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3447 outer_block->statements()->Add(assignment_statement, zone()); | 3431 outer_block->statements()->Add(assignment_statement, zone()); |
| 3448 temps.Add(temp, zone()); | 3432 temps.Add(temp, zone()); |
| 3449 } | 3433 } |
| 3450 | 3434 |
| 3451 Variable* first = NULL; | 3435 Variable* first = NULL; |
| 3452 // Make statement: first = 1. | 3436 // Make statement: first = 1. |
| 3453 if (next) { | 3437 if (next) { |
| 3454 first = scope_->NewTemporary(temp_name); | 3438 first = scope_->NewTemporary(temp_name); |
| 3455 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3439 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
| 3456 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3440 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3715 // { | 3699 // { |
| 3716 // <let x' be a temporary variable> | 3700 // <let x' be a temporary variable> |
| 3717 // for (x' in/of e) { | 3701 // for (x' in/of e) { |
| 3718 // let/const/var x; | 3702 // let/const/var x; |
| 3719 // x = x'; | 3703 // x = x'; |
| 3720 // b; | 3704 // b; |
| 3721 // } | 3705 // } |
| 3722 // let x; // for TDZ | 3706 // let x; // for TDZ |
| 3723 // } | 3707 // } |
| 3724 | 3708 |
| 3725 Variable* temp = scope_->NewTemporary( | 3709 Variable* temp = |
| 3726 ast_value_factory()->dot_for_string()); | 3710 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
| 3727 ForEachStatement* loop = | 3711 ForEachStatement* loop = |
| 3728 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3712 factory()->NewForEachStatement(mode, labels, stmt_pos); |
| 3729 Target target(&this->target_stack_, loop); | 3713 Target target(&this->target_stack_, loop); |
| 3730 | 3714 |
| 3731 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3715 Expression* enumerable = ParseExpression(true, CHECK_OK); |
| 3732 | 3716 |
| 3733 Expect(Token::RPAREN, CHECK_OK); | 3717 Expect(Token::RPAREN, CHECK_OK); |
| 3734 | 3718 |
| 3735 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | 3719 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
| 3736 body_scope->set_start_position(scanner()->location().beg_pos); | 3720 body_scope->set_start_position(scanner()->location().beg_pos); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3897 Expression* exp = ParseExpression(true, CHECK_OK); | 3881 Expression* exp = ParseExpression(true, CHECK_OK); |
| 3898 next = factory()->NewExpressionStatement(exp, exp->position()); | 3882 next = factory()->NewExpressionStatement(exp, exp->position()); |
| 3899 } | 3883 } |
| 3900 Expect(Token::RPAREN, CHECK_OK); | 3884 Expect(Token::RPAREN, CHECK_OK); |
| 3901 | 3885 |
| 3902 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3886 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
| 3903 | 3887 |
| 3904 Statement* result = NULL; | 3888 Statement* result = NULL; |
| 3905 if (lexical_bindings.length() > 0) { | 3889 if (lexical_bindings.length() > 0) { |
| 3906 scope_ = for_scope; | 3890 scope_ = for_scope; |
| 3907 result = DesugarLexicalBindingsInForStatement( | 3891 result = DesugarLexicalBindingsInForStatement(inner_scope, is_const, |
| 3908 inner_scope, is_const, &lexical_bindings, loop, init, cond, | 3892 &lexical_bindings, loop, init, |
| 3909 next, body, CHECK_OK); | 3893 cond, next, body, CHECK_OK); |
| 3910 scope_ = saved_scope; | 3894 scope_ = saved_scope; |
| 3911 for_scope->set_end_position(scanner()->location().end_pos); | 3895 for_scope->set_end_position(scanner()->location().end_pos); |
| 3912 } else { | 3896 } else { |
| 3913 scope_ = saved_scope; | 3897 scope_ = saved_scope; |
| 3914 for_scope->set_end_position(scanner()->location().end_pos); | 3898 for_scope->set_end_position(scanner()->location().end_pos); |
| 3915 for_scope = for_scope->FinalizeBlockScope(); | 3899 for_scope = for_scope->FinalizeBlockScope(); |
| 3916 if (for_scope) { | 3900 if (for_scope) { |
| 3917 // Rewrite a for statement of the form | 3901 // Rewrite a for statement of the form |
| 3918 // for (const x = i; c; n) b | 3902 // for (const x = i; c; n) b |
| 3919 // | 3903 // |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4098 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { | 4082 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { |
| 4099 *ok = false; | 4083 *ok = false; |
| 4100 return nullptr; | 4084 return nullptr; |
| 4101 } | 4085 } |
| 4102 return expr; | 4086 return expr; |
| 4103 } | 4087 } |
| 4104 | 4088 |
| 4105 | 4089 |
| 4106 void ParserTraits::ParseArrowFunctionFormalParameterList( | 4090 void ParserTraits::ParseArrowFunctionFormalParameterList( |
| 4107 ParserFormalParameters* parameters, Expression* expr, | 4091 ParserFormalParameters* parameters, Expression* expr, |
| 4108 const Scanner::Location& params_loc, | 4092 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, |
| 4109 Scanner::Location* duplicate_loc, bool* ok) { | 4093 bool* ok) { |
| 4110 if (expr->IsEmptyParentheses()) return; | 4094 if (expr->IsEmptyParentheses()) return; |
| 4111 | 4095 |
| 4112 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok); | 4096 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok); |
| 4113 if (!*ok) return; | 4097 if (!*ok) return; |
| 4114 | 4098 |
| 4115 ExpressionClassifier classifier; | 4099 ExpressionClassifier classifier; |
| 4116 if (!parameters->is_simple) { | 4100 if (!parameters->is_simple) { |
| 4117 classifier.RecordNonSimpleParameter(); | 4101 classifier.RecordNonSimpleParameter(); |
| 4118 } | 4102 } |
| 4119 for (int i = 0; i < parameters->Arity(); ++i) { | 4103 for (int i = 0; i < parameters->Arity(); ++i) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4154 LanguageMode language_mode, bool* ok) { | 4138 LanguageMode language_mode, bool* ok) { |
| 4155 // Function :: | 4139 // Function :: |
| 4156 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 4140 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 4157 // | 4141 // |
| 4158 // Getter :: | 4142 // Getter :: |
| 4159 // '(' ')' '{' FunctionBody '}' | 4143 // '(' ')' '{' FunctionBody '}' |
| 4160 // | 4144 // |
| 4161 // Setter :: | 4145 // Setter :: |
| 4162 // '(' PropertySetParameterList ')' '{' FunctionBody '}' | 4146 // '(' PropertySetParameterList ')' '{' FunctionBody '}' |
| 4163 | 4147 |
| 4164 int pos = function_token_pos == RelocInfo::kNoPosition | 4148 int pos = function_token_pos == RelocInfo::kNoPosition ? peek_position() |
| 4165 ? peek_position() : function_token_pos; | 4149 : function_token_pos; |
| 4166 | 4150 |
| 4167 bool is_generator = IsGeneratorFunction(kind); | 4151 bool is_generator = IsGeneratorFunction(kind); |
| 4168 | 4152 |
| 4169 // Anonymous functions were passed either the empty symbol or a null | 4153 // Anonymous functions were passed either the empty symbol or a null |
| 4170 // handle as the function name. Remember if we were passed a non-empty | 4154 // handle as the function name. Remember if we were passed a non-empty |
| 4171 // handle to decide whether to invoke function name inference. | 4155 // handle to decide whether to invoke function name inference. |
| 4172 bool should_infer_name = function_name == NULL; | 4156 bool should_infer_name = function_name == NULL; |
| 4173 | 4157 |
| 4174 // We want a non-null handle as the function name. | 4158 // We want a non-null handle as the function name. |
| 4175 if (should_infer_name) { | 4159 if (should_infer_name) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4246 | 4230 |
| 4247 Expect(Token::LPAREN, CHECK_OK); | 4231 Expect(Token::LPAREN, CHECK_OK); |
| 4248 int start_position = scanner()->location().beg_pos; | 4232 int start_position = scanner()->location().beg_pos; |
| 4249 scope_->set_start_position(start_position); | 4233 scope_->set_start_position(start_position); |
| 4250 ParserFormalParameters formals(scope); | 4234 ParserFormalParameters formals(scope); |
| 4251 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); | 4235 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
| 4252 arity = formals.Arity(); | 4236 arity = formals.Arity(); |
| 4253 Expect(Token::RPAREN, CHECK_OK); | 4237 Expect(Token::RPAREN, CHECK_OK); |
| 4254 int formals_end_position = scanner()->location().end_pos; | 4238 int formals_end_position = scanner()->location().end_pos; |
| 4255 | 4239 |
| 4256 CheckArityRestrictions(arity, arity_restriction, | 4240 CheckArityRestrictions(arity, arity_restriction, formals.has_rest, |
| 4257 formals.has_rest, start_position, | 4241 start_position, formals_end_position, CHECK_OK); |
| 4258 formals_end_position, CHECK_OK); | |
| 4259 Expect(Token::LBRACE, CHECK_OK); | 4242 Expect(Token::LBRACE, CHECK_OK); |
| 4260 | 4243 |
| 4261 // Determine if the function can be parsed lazily. Lazy parsing is different | 4244 // Determine if the function can be parsed lazily. Lazy parsing is different |
| 4262 // from lazy compilation; we need to parse more eagerly than we compile. | 4245 // from lazy compilation; we need to parse more eagerly than we compile. |
| 4263 | 4246 |
| 4264 // We can only parse lazily if we also compile lazily. The heuristics for | 4247 // We can only parse lazily if we also compile lazily. The heuristics for |
| 4265 // lazy compilation are: | 4248 // lazy compilation are: |
| 4266 // - It must not have been prohibited by the caller to Parse (some callers | 4249 // - It must not have been prohibited by the caller to Parse (some callers |
| 4267 // need a full AST). | 4250 // need a full AST). |
| 4268 // - The outer scope must allow lazy compilation of inner functions. | 4251 // - The outer scope must allow lazy compilation of inner functions. |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4555 Expression* initial_value = | 4538 Expression* initial_value = |
| 4556 factory()->NewVariableProxy(parameters.scope->parameter(i)); | 4539 factory()->NewVariableProxy(parameters.scope->parameter(i)); |
| 4557 if (parameter.initializer != nullptr) { | 4540 if (parameter.initializer != nullptr) { |
| 4558 // IS_UNDEFINED($param) ? initializer : $param | 4541 // IS_UNDEFINED($param) ? initializer : $param |
| 4559 DCHECK(!parameter.is_rest); | 4542 DCHECK(!parameter.is_rest); |
| 4560 auto condition = factory()->NewCompareOperation( | 4543 auto condition = factory()->NewCompareOperation( |
| 4561 Token::EQ_STRICT, | 4544 Token::EQ_STRICT, |
| 4562 factory()->NewVariableProxy(parameters.scope->parameter(i)), | 4545 factory()->NewVariableProxy(parameters.scope->parameter(i)), |
| 4563 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 4546 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
| 4564 RelocInfo::kNoPosition); | 4547 RelocInfo::kNoPosition); |
| 4565 initial_value = factory()->NewConditional( | 4548 initial_value = |
| 4566 condition, parameter.initializer, initial_value, | 4549 factory()->NewConditional(condition, parameter.initializer, |
| 4567 RelocInfo::kNoPosition); | 4550 initial_value, RelocInfo::kNoPosition); |
| 4568 descriptor.initialization_pos = parameter.initializer->position(); | 4551 descriptor.initialization_pos = parameter.initializer->position(); |
| 4569 initializer_position = parameter.initializer_end_position; | 4552 initializer_position = parameter.initializer_end_position; |
| 4570 } else if (parameter.is_rest) { | 4553 } else if (parameter.is_rest) { |
| 4571 // $rest = []; | 4554 // $rest = []; |
| 4572 // for (var $argument_index = $rest_index; | 4555 // for (var $argument_index = $rest_index; |
| 4573 // $argument_index < %_ArgumentsLength(); | 4556 // $argument_index < %_ArgumentsLength(); |
| 4574 // ++$argument_index) { | 4557 // ++$argument_index) { |
| 4575 // %AppendElement($rest, %_Arguments($argument_index)); | 4558 // %AppendElement($rest, %_Arguments($argument_index)); |
| 4576 // } | 4559 // } |
| 4577 // let <param> = $rest; | 4560 // let <param> = $rest; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4676 } | 4659 } |
| 4677 | 4660 |
| 4678 | 4661 |
| 4679 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4662 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| 4680 const AstRawString* function_name, int pos, | 4663 const AstRawString* function_name, int pos, |
| 4681 const ParserFormalParameters& parameters, FunctionKind kind, | 4664 const ParserFormalParameters& parameters, FunctionKind kind, |
| 4682 FunctionLiteral::FunctionType function_type, bool* ok) { | 4665 FunctionLiteral::FunctionType function_type, bool* ok) { |
| 4683 // Everything inside an eagerly parsed function will be parsed eagerly | 4666 // Everything inside an eagerly parsed function will be parsed eagerly |
| 4684 // (see comment above). | 4667 // (see comment above). |
| 4685 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4668 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 4686 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4669 ZoneList<Statement*>* result = new (zone()) ZoneList<Statement*>(8, zone()); |
| 4687 | 4670 |
| 4688 static const int kFunctionNameAssignmentIndex = 0; | 4671 static const int kFunctionNameAssignmentIndex = 0; |
| 4689 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | 4672 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
| 4690 DCHECK(function_name != NULL); | 4673 DCHECK(function_name != NULL); |
| 4691 // If we have a named function expression, we add a local variable | 4674 // If we have a named function expression, we add a local variable |
| 4692 // declaration to the body of the function with the name of the | 4675 // declaration to the body of the function with the name of the |
| 4693 // function and let it refer to the function itself (closure). | 4676 // function and let it refer to the function itself (closure). |
| 4694 // Not having parsed the function body, the language mode may still change, | 4677 // Not having parsed the function body, the language mode may still change, |
| 4695 // so we reserve a spot and create the actual const assignment later. | 4678 // so we reserve a spot and create the actual const assignment later. |
| 4696 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); | 4679 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4708 inner_block->set_scope(inner_scope); | 4691 inner_block->set_scope(inner_scope); |
| 4709 body = inner_block->statements(); | 4692 body = inner_block->statements(); |
| 4710 } | 4693 } |
| 4711 | 4694 |
| 4712 { | 4695 { |
| 4713 BlockState block_state(&scope_, inner_scope); | 4696 BlockState block_state(&scope_, inner_scope); |
| 4714 | 4697 |
| 4715 // For generators, allocate and yield an iterator on function entry. | 4698 // For generators, allocate and yield an iterator on function entry. |
| 4716 if (IsGeneratorFunction(kind)) { | 4699 if (IsGeneratorFunction(kind)) { |
| 4717 ZoneList<Expression*>* arguments = | 4700 ZoneList<Expression*>* arguments = |
| 4718 new(zone()) ZoneList<Expression*>(0, zone()); | 4701 new (zone()) ZoneList<Expression*>(0, zone()); |
| 4719 CallRuntime* allocation = factory()->NewCallRuntime( | 4702 CallRuntime* allocation = factory()->NewCallRuntime( |
| 4720 Runtime::kCreateJSGeneratorObject, arguments, pos); | 4703 Runtime::kCreateJSGeneratorObject, arguments, pos); |
| 4721 VariableProxy* init_proxy = factory()->NewVariableProxy( | 4704 VariableProxy* init_proxy = factory()->NewVariableProxy( |
| 4722 function_state_->generator_object_variable()); | 4705 function_state_->generator_object_variable()); |
| 4723 Assignment* assignment = factory()->NewAssignment( | 4706 Assignment* assignment = factory()->NewAssignment( |
| 4724 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); | 4707 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
| 4725 VariableProxy* get_proxy = factory()->NewVariableProxy( | 4708 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 4726 function_state_->generator_object_variable()); | 4709 function_state_->generator_object_variable()); |
| 4727 Yield* yield = factory()->NewYield( | 4710 Yield* yield = factory()->NewYield(get_proxy, assignment, Yield::kInitial, |
| 4728 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); | 4711 RelocInfo::kNoPosition); |
| 4729 body->Add(factory()->NewExpressionStatement( | 4712 body->Add( |
| 4730 yield, RelocInfo::kNoPosition), zone()); | 4713 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
| 4714 zone()); |
| 4731 } | 4715 } |
| 4732 | 4716 |
| 4733 ParseStatementList(body, Token::RBRACE, CHECK_OK); | 4717 ParseStatementList(body, Token::RBRACE, CHECK_OK); |
| 4734 | 4718 |
| 4735 if (IsGeneratorFunction(kind)) { | 4719 if (IsGeneratorFunction(kind)) { |
| 4736 VariableProxy* get_proxy = factory()->NewVariableProxy( | 4720 VariableProxy* get_proxy = factory()->NewVariableProxy( |
| 4737 function_state_->generator_object_variable()); | 4721 function_state_->generator_object_variable()); |
| 4738 Expression* undefined = | 4722 Expression* undefined = |
| 4739 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | 4723 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); |
| 4740 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, | 4724 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, |
| 4741 RelocInfo::kNoPosition); | 4725 RelocInfo::kNoPosition); |
| 4742 body->Add(factory()->NewExpressionStatement( | 4726 body->Add( |
| 4743 yield, RelocInfo::kNoPosition), zone()); | 4727 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
| 4728 zone()); |
| 4744 } | 4729 } |
| 4745 | 4730 |
| 4746 if (IsSubclassConstructor(kind)) { | 4731 if (IsSubclassConstructor(kind)) { |
| 4747 body->Add( | 4732 body->Add( |
| 4748 factory()->NewReturnStatement( | 4733 factory()->NewReturnStatement( |
| 4749 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), | 4734 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), |
| 4750 RelocInfo::kNoPosition), | 4735 RelocInfo::kNoPosition), |
| 4751 zone()); | 4736 zone()); |
| 4752 } | 4737 } |
| 4753 } | 4738 } |
| 4754 | 4739 |
| 4755 Expect(Token::RBRACE, CHECK_OK); | 4740 Expect(Token::RBRACE, CHECK_OK); |
| 4756 scope_->set_end_position(scanner()->location().end_pos); | 4741 scope_->set_end_position(scanner()->location().end_pos); |
| 4757 | 4742 |
| 4758 if (!parameters.is_simple) { | 4743 if (!parameters.is_simple) { |
| 4759 DCHECK_NOT_NULL(inner_scope); | 4744 DCHECK_NOT_NULL(inner_scope); |
| 4760 DCHECK_EQ(body, inner_block->statements()); | 4745 DCHECK_EQ(body, inner_block->statements()); |
| 4761 SetLanguageMode(scope_, inner_scope->language_mode()); | 4746 SetLanguageMode(scope_, inner_scope->language_mode()); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4939 } | 4924 } |
| 4940 | 4925 |
| 4941 | 4926 |
| 4942 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 4927 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| 4943 // CallRuntime :: | 4928 // CallRuntime :: |
| 4944 // '%' Identifier Arguments | 4929 // '%' Identifier Arguments |
| 4945 | 4930 |
| 4946 int pos = peek_position(); | 4931 int pos = peek_position(); |
| 4947 Expect(Token::MOD, CHECK_OK); | 4932 Expect(Token::MOD, CHECK_OK); |
| 4948 // Allow "eval" or "arguments" for backward compatibility. | 4933 // Allow "eval" or "arguments" for backward compatibility. |
| 4949 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers, | 4934 const AstRawString* name = |
| 4950 CHECK_OK); | 4935 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 4951 Scanner::Location spread_pos; | 4936 Scanner::Location spread_pos; |
| 4952 ExpressionClassifier classifier; | 4937 ExpressionClassifier classifier; |
| 4953 ZoneList<Expression*>* args = | 4938 ZoneList<Expression*>* args = |
| 4954 ParseArguments(&spread_pos, &classifier, CHECK_OK); | 4939 ParseArguments(&spread_pos, &classifier, CHECK_OK); |
| 4955 ValidateExpression(&classifier, CHECK_OK); | 4940 ValidateExpression(&classifier, CHECK_OK); |
| 4956 | 4941 |
| 4957 DCHECK(!spread_pos.IsValid()); | 4942 DCHECK(!spread_pos.IsValid()); |
| 4958 | 4943 |
| 4959 if (extension_ != NULL) { | 4944 if (extension_ != NULL) { |
| 4960 // The extension structures are only accessible while parsing the | 4945 // The extension structures are only accessible while parsing the |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5010 return factory()->NewUndefinedLiteral(position); | 4995 return factory()->NewUndefinedLiteral(position); |
| 5011 } | 4996 } |
| 5012 | 4997 |
| 5013 | 4998 |
| 5014 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 4999 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| 5015 Declaration* decl = scope->CheckConflictingVarDeclarations(); | 5000 Declaration* decl = scope->CheckConflictingVarDeclarations(); |
| 5016 if (decl != NULL) { | 5001 if (decl != NULL) { |
| 5017 // In ES6, conflicting variable bindings are early errors. | 5002 // In ES6, conflicting variable bindings are early errors. |
| 5018 const AstRawString* name = decl->proxy()->raw_name(); | 5003 const AstRawString* name = decl->proxy()->raw_name(); |
| 5019 int position = decl->proxy()->position(); | 5004 int position = decl->proxy()->position(); |
| 5020 Scanner::Location location = position == RelocInfo::kNoPosition | 5005 Scanner::Location location = |
| 5021 ? Scanner::Location::invalid() | 5006 position == RelocInfo::kNoPosition |
| 5022 : Scanner::Location(position, position + 1); | 5007 ? Scanner::Location::invalid() |
| 5008 : Scanner::Location(position, position + 1); |
| 5023 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration, | 5009 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration, |
| 5024 name); | 5010 name); |
| 5025 *ok = false; | 5011 *ok = false; |
| 5026 } | 5012 } |
| 5027 } | 5013 } |
| 5028 | 5014 |
| 5029 | 5015 |
| 5030 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { | 5016 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { |
| 5031 // For each var-binding that shadows a parameter, insert an assignment | 5017 // For each var-binding that shadows a parameter, insert an assignment |
| 5032 // initializing the variable with the parameter. | 5018 // initializing the variable with the parameter. |
| 5033 Scope* inner_scope = inner_block->scope(); | 5019 Scope* inner_scope = inner_block->scope(); |
| 5034 DCHECK(inner_scope->is_declaration_scope()); | 5020 DCHECK(inner_scope->is_declaration_scope()); |
| 5035 Scope* function_scope = inner_scope->outer_scope(); | 5021 Scope* function_scope = inner_scope->outer_scope(); |
| 5036 DCHECK(function_scope->is_function_scope()); | 5022 DCHECK(function_scope->is_function_scope()); |
| 5037 ZoneList<Declaration*>* decls = inner_scope->declarations(); | 5023 ZoneList<Declaration*>* decls = inner_scope->declarations(); |
| 5038 for (int i = 0; i < decls->length(); ++i) { | 5024 for (int i = 0; i < decls->length(); ++i) { |
| 5039 Declaration* decl = decls->at(i); | 5025 Declaration* decl = decls->at(i); |
| 5040 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue; | 5026 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue; |
| 5041 const AstRawString* name = decl->proxy()->raw_name(); | 5027 const AstRawString* name = decl->proxy()->raw_name(); |
| 5042 Variable* parameter = function_scope->LookupLocal(name); | 5028 Variable* parameter = function_scope->LookupLocal(name); |
| 5043 if (parameter == nullptr) continue; | 5029 if (parameter == nullptr) continue; |
| 5044 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); | 5030 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); |
| 5045 VariableProxy* from = factory()->NewVariableProxy(parameter); | 5031 VariableProxy* from = factory()->NewVariableProxy(parameter); |
| 5046 Expression* assignment = factory()->NewAssignment( | 5032 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, to, from, |
| 5047 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5033 RelocInfo::kNoPosition); |
| 5048 Statement* statement = factory()->NewExpressionStatement( | 5034 Statement* statement = |
| 5049 assignment, RelocInfo::kNoPosition); | 5035 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 5050 inner_block->statements()->InsertAt(0, statement, zone()); | 5036 inner_block->statements()->InsertAt(0, statement, zone()); |
| 5051 } | 5037 } |
| 5052 } | 5038 } |
| 5053 | 5039 |
| 5054 | 5040 |
| 5055 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { | 5041 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { |
| 5056 // For each variable which is used as a function declaration in a sloppy | 5042 // For each variable which is used as a function declaration in a sloppy |
| 5057 // block, | 5043 // block, |
| 5058 DCHECK(scope->is_declaration_scope()); | 5044 DCHECK(scope->is_declaration_scope()); |
| 5059 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 5045 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5230 Advance(); | 5216 Advance(); |
| 5231 } | 5217 } |
| 5232 | 5218 |
| 5233 | 5219 |
| 5234 void RegExpParser::Advance(int dist) { | 5220 void RegExpParser::Advance(int dist) { |
| 5235 next_pos_ += dist - 1; | 5221 next_pos_ += dist - 1; |
| 5236 Advance(); | 5222 Advance(); |
| 5237 } | 5223 } |
| 5238 | 5224 |
| 5239 | 5225 |
| 5240 bool RegExpParser::simple() { | 5226 bool RegExpParser::simple() { return simple_; } |
| 5241 return simple_; | |
| 5242 } | |
| 5243 | 5227 |
| 5244 | 5228 |
| 5245 bool RegExpParser::IsSyntaxCharacter(uc32 c) { | 5229 bool RegExpParser::IsSyntaxCharacter(uc32 c) { |
| 5246 return c == '^' || c == '$' || c == '\\' || c == '.' || c == '*' || | 5230 return c == '^' || c == '$' || c == '\\' || c == '.' || c == '*' || |
| 5247 c == '+' || c == '?' || c == '(' || c == ')' || c == '[' || c == ']' || | 5231 c == '+' || c == '?' || c == '(' || c == ')' || c == '[' || c == ']' || |
| 5248 c == '{' || c == '}' || c == '|'; | 5232 c == '{' || c == '}' || c == '|'; |
| 5249 } | 5233 } |
| 5250 | 5234 |
| 5251 | 5235 |
| 5252 RegExpTree* RegExpParser::ReportError(Vector<const char> message) { | 5236 RegExpTree* RegExpParser::ReportError(Vector<const char> message) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5285 // Atom Quantifier | 5269 // Atom Quantifier |
| 5286 RegExpTree* RegExpParser::ParseDisjunction() { | 5270 RegExpTree* RegExpParser::ParseDisjunction() { |
| 5287 // Used to store current state while parsing subexpressions. | 5271 // Used to store current state while parsing subexpressions. |
| 5288 RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0, | 5272 RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0, |
| 5289 zone()); | 5273 zone()); |
| 5290 RegExpParserState* state = &initial_state; | 5274 RegExpParserState* state = &initial_state; |
| 5291 // Cache the builder in a local variable for quick access. | 5275 // Cache the builder in a local variable for quick access. |
| 5292 RegExpBuilder* builder = initial_state.builder(); | 5276 RegExpBuilder* builder = initial_state.builder(); |
| 5293 while (true) { | 5277 while (true) { |
| 5294 switch (current()) { | 5278 switch (current()) { |
| 5295 case kEndMarker: | 5279 case kEndMarker: |
| 5296 if (state->IsSubexpression()) { | 5280 if (state->IsSubexpression()) { |
| 5297 // Inside a parenthesized group when hitting end of input. | 5281 // Inside a parenthesized group when hitting end of input. |
| 5298 ReportError(CStrVector("Unterminated group") CHECK_FAILED); | 5282 ReportError(CStrVector("Unterminated group") CHECK_FAILED); |
| 5299 } | 5283 } |
| 5300 DCHECK_EQ(INITIAL, state->group_type()); | 5284 DCHECK_EQ(INITIAL, state->group_type()); |
| 5301 // Parsing completed successfully. | 5285 // Parsing completed successfully. |
| 5302 return builder->ToRegExp(); | 5286 return builder->ToRegExp(); |
| 5303 case ')': { | 5287 case ')': { |
| 5304 if (!state->IsSubexpression()) { | 5288 if (!state->IsSubexpression()) { |
| 5305 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED); | 5289 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED); |
| 5306 } | 5290 } |
| 5307 DCHECK_NE(INITIAL, state->group_type()); | 5291 DCHECK_NE(INITIAL, state->group_type()); |
| 5308 | 5292 |
| 5309 Advance(); | 5293 Advance(); |
| 5310 // End disjunction parsing and convert builder content to new single | 5294 // End disjunction parsing and convert builder content to new single |
| 5311 // regexp atom. | 5295 // regexp atom. |
| 5312 RegExpTree* body = builder->ToRegExp(); | 5296 RegExpTree* body = builder->ToRegExp(); |
| 5313 | 5297 |
| 5314 int end_capture_index = captures_started(); | 5298 int end_capture_index = captures_started(); |
| 5315 | 5299 |
| 5316 int capture_index = state->capture_index(); | 5300 int capture_index = state->capture_index(); |
| 5317 SubexpressionType group_type = state->group_type(); | 5301 SubexpressionType group_type = state->group_type(); |
| 5318 | 5302 |
| 5319 // Build result of subexpression. | 5303 // Build result of subexpression. |
| 5320 if (group_type == CAPTURE) { | 5304 if (group_type == CAPTURE) { |
| 5321 RegExpCapture* capture = GetCapture(capture_index); | 5305 RegExpCapture* capture = GetCapture(capture_index); |
| 5322 capture->set_body(body); | 5306 capture->set_body(body); |
| 5323 body = capture; | 5307 body = capture; |
| 5324 } else if (group_type != GROUPING) { | 5308 } else if (group_type != GROUPING) { |
| 5325 DCHECK(group_type == POSITIVE_LOOKAROUND || | 5309 DCHECK(group_type == POSITIVE_LOOKAROUND || |
| 5326 group_type == NEGATIVE_LOOKAROUND); | 5310 group_type == NEGATIVE_LOOKAROUND); |
| 5327 bool is_positive = (group_type == POSITIVE_LOOKAROUND); | 5311 bool is_positive = (group_type == POSITIVE_LOOKAROUND); |
| 5328 body = new (zone()) RegExpLookaround( | 5312 body = new (zone()) RegExpLookaround( |
| 5329 body, is_positive, end_capture_index - capture_index, capture_index, | 5313 body, is_positive, end_capture_index - capture_index, |
| 5330 state->lookaround_type()); | 5314 capture_index, state->lookaround_type()); |
| 5331 } | 5315 } |
| 5332 | 5316 |
| 5333 // Restore previous state. | 5317 // Restore previous state. |
| 5334 state = state->previous_state(); | 5318 state = state->previous_state(); |
| 5335 builder = state->builder(); | 5319 builder = state->builder(); |
| 5336 | 5320 |
| 5337 builder->AddAtom(body); | 5321 builder->AddAtom(body); |
| 5338 // For compatability with JSC and ES3, we allow quantifiers after | 5322 // For compatability with JSC and ES3, we allow quantifiers after |
| 5339 // lookaheads, and break in all cases. | 5323 // lookaheads, and break in all cases. |
| 5340 break; | 5324 break; |
| 5341 } | 5325 } |
| 5342 case '|': { | 5326 case '|': { |
| 5343 Advance(); | 5327 Advance(); |
| 5344 builder->NewAlternative(); | 5328 builder->NewAlternative(); |
| 5345 continue; | 5329 continue; |
| 5346 } | 5330 } |
| 5347 case '*': | 5331 case '*': |
| 5348 case '+': | 5332 case '+': |
| 5349 case '?': | 5333 case '?': |
| 5350 return ReportError(CStrVector("Nothing to repeat")); | 5334 return ReportError(CStrVector("Nothing to repeat")); |
| 5351 case '^': { | 5335 case '^': { |
| 5352 Advance(); | 5336 Advance(); |
| 5353 if (multiline_) { | 5337 if (multiline_) { |
| 5354 builder->AddAssertion( | 5338 builder->AddAssertion( |
| 5355 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); | 5339 new (zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); |
| 5356 } else { | 5340 } else { |
| 5357 builder->AddAssertion( | 5341 builder->AddAssertion( |
| 5358 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); | 5342 new (zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); |
| 5359 set_contains_anchor(); | 5343 set_contains_anchor(); |
| 5360 } | 5344 } |
| 5361 continue; | 5345 continue; |
| 5362 } | 5346 } |
| 5363 case '$': { | 5347 case '$': { |
| 5364 Advance(); | 5348 Advance(); |
| 5365 RegExpAssertion::AssertionType assertion_type = | 5349 RegExpAssertion::AssertionType assertion_type = |
| 5366 multiline_ ? RegExpAssertion::END_OF_LINE : | 5350 multiline_ ? RegExpAssertion::END_OF_LINE |
| 5367 RegExpAssertion::END_OF_INPUT; | 5351 : RegExpAssertion::END_OF_INPUT; |
| 5368 builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type)); | 5352 builder->AddAssertion(new (zone()) RegExpAssertion(assertion_type)); |
| 5369 continue; | 5353 continue; |
| 5370 } | 5354 } |
| 5371 case '.': { | 5355 case '.': { |
| 5372 Advance(); | 5356 Advance(); |
| 5373 // everything except \x0a, \x0d, \u2028 and \u2029 | 5357 // everything except \x0a, \x0d, \u2028 and \u2029 |
| 5374 ZoneList<CharacterRange>* ranges = | 5358 ZoneList<CharacterRange>* ranges = |
| 5375 new(zone()) ZoneList<CharacterRange>(2, zone()); | 5359 new (zone()) ZoneList<CharacterRange>(2, zone()); |
| 5376 CharacterRange::AddClassEscape('.', ranges, zone()); | 5360 CharacterRange::AddClassEscape('.', ranges, zone()); |
| 5377 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); | 5361 RegExpTree* atom = new (zone()) RegExpCharacterClass(ranges, false); |
| 5378 builder->AddAtom(atom); | 5362 builder->AddAtom(atom); |
| 5379 break; | 5363 break; |
| 5380 } | 5364 } |
| 5381 case '(': { | 5365 case '(': { |
| 5382 SubexpressionType subexpr_type = CAPTURE; | 5366 SubexpressionType subexpr_type = CAPTURE; |
| 5383 RegExpLookaround::Type lookaround_type = state->lookaround_type(); | 5367 RegExpLookaround::Type lookaround_type = state->lookaround_type(); |
| 5384 Advance(); | 5368 Advance(); |
| 5385 if (current() == '?') { | 5369 if (current() == '?') { |
| 5370 switch (Next()) { |
| 5371 case ':': |
| 5372 subexpr_type = GROUPING; |
| 5373 break; |
| 5374 case '=': |
| 5375 lookaround_type = RegExpLookaround::LOOKAHEAD; |
| 5376 subexpr_type = POSITIVE_LOOKAROUND; |
| 5377 break; |
| 5378 case '!': |
| 5379 lookaround_type = RegExpLookaround::LOOKAHEAD; |
| 5380 subexpr_type = NEGATIVE_LOOKAROUND; |
| 5381 break; |
| 5382 case '<': |
| 5383 if (FLAG_harmony_regexp_lookbehind) { |
| 5384 Advance(); |
| 5385 lookaround_type = RegExpLookaround::LOOKBEHIND; |
| 5386 if (Next() == '=') { |
| 5387 subexpr_type = POSITIVE_LOOKAROUND; |
| 5388 break; |
| 5389 } else if (Next() == '!') { |
| 5390 subexpr_type = NEGATIVE_LOOKAROUND; |
| 5391 break; |
| 5392 } |
| 5393 } |
| 5394 // Fall through. |
| 5395 default: |
| 5396 ReportError(CStrVector("Invalid group") CHECK_FAILED); |
| 5397 break; |
| 5398 } |
| 5399 Advance(2); |
| 5400 } else { |
| 5401 if (captures_started_ >= kMaxCaptures) { |
| 5402 ReportError(CStrVector("Too many captures") CHECK_FAILED); |
| 5403 } |
| 5404 captures_started_++; |
| 5405 } |
| 5406 // Store current state and begin new disjunction parsing. |
| 5407 state = new (zone()) RegExpParserState( |
| 5408 state, subexpr_type, lookaround_type, captures_started_, zone()); |
| 5409 builder = state->builder(); |
| 5410 continue; |
| 5411 } |
| 5412 case '[': { |
| 5413 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED); |
| 5414 builder->AddAtom(atom); |
| 5415 break; |
| 5416 } |
| 5417 // Atom :: |
| 5418 // \ AtomEscape |
| 5419 case '\\': |
| 5386 switch (Next()) { | 5420 switch (Next()) { |
| 5387 case ':': | 5421 case kEndMarker: |
| 5388 subexpr_type = GROUPING; | 5422 return ReportError(CStrVector("\\ at end of pattern")); |
| 5389 break; | 5423 case 'b': |
| 5390 case '=': | 5424 Advance(2); |
| 5391 lookaround_type = RegExpLookaround::LOOKAHEAD; | 5425 builder->AddAssertion( |
| 5392 subexpr_type = POSITIVE_LOOKAROUND; | 5426 new (zone()) RegExpAssertion(RegExpAssertion::BOUNDARY)); |
| 5393 break; | 5427 continue; |
| 5394 case '!': | 5428 case 'B': |
| 5395 lookaround_type = RegExpLookaround::LOOKAHEAD; | 5429 Advance(2); |
| 5396 subexpr_type = NEGATIVE_LOOKAROUND; | 5430 builder->AddAssertion( |
| 5397 break; | 5431 new (zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); |
| 5398 case '<': | 5432 continue; |
| 5399 if (FLAG_harmony_regexp_lookbehind) { | 5433 // AtomEscape :: |
| 5434 // CharacterClassEscape |
| 5435 // |
| 5436 // CharacterClassEscape :: one of |
| 5437 // d D s S w W |
| 5438 case 'd': |
| 5439 case 'D': |
| 5440 case 's': |
| 5441 case 'S': |
| 5442 case 'w': |
| 5443 case 'W': { |
| 5444 uc32 c = Next(); |
| 5445 Advance(2); |
| 5446 ZoneList<CharacterRange>* ranges = |
| 5447 new (zone()) ZoneList<CharacterRange>(2, zone()); |
| 5448 CharacterRange::AddClassEscape(c, ranges, zone()); |
| 5449 RegExpTree* atom = new (zone()) RegExpCharacterClass(ranges, false); |
| 5450 builder->AddAtom(atom); |
| 5451 break; |
| 5452 } |
| 5453 case '1': |
| 5454 case '2': |
| 5455 case '3': |
| 5456 case '4': |
| 5457 case '5': |
| 5458 case '6': |
| 5459 case '7': |
| 5460 case '8': |
| 5461 case '9': { |
| 5462 int index = 0; |
| 5463 if (ParseBackReferenceIndex(&index)) { |
| 5464 if (state->IsInsideCaptureGroup(index)) { |
| 5465 // The backreference is inside the capture group it refers to. |
| 5466 // Nothing can possibly have been captured yet. |
| 5467 builder->AddEmpty(); |
| 5468 } else { |
| 5469 RegExpCapture* capture = GetCapture(index); |
| 5470 RegExpTree* atom = new (zone()) RegExpBackReference(capture); |
| 5471 builder->AddAtom(atom); |
| 5472 } |
| 5473 break; |
| 5474 } |
| 5475 uc32 first_digit = Next(); |
| 5476 if (first_digit == '8' || first_digit == '9') { |
| 5477 // If the 'u' flag is present, only syntax characters can be |
| 5478 // escaped, |
| 5479 // no other identity escapes are allowed. If the 'u' flag is not |
| 5480 // present, all identity escapes are allowed. |
| 5481 if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5482 builder->AddCharacter(first_digit); |
| 5483 Advance(2); |
| 5484 } else { |
| 5485 return ReportError(CStrVector("Invalid escape")); |
| 5486 } |
| 5487 break; |
| 5488 } |
| 5489 } |
| 5490 // FALLTHROUGH |
| 5491 case '0': { |
| 5492 Advance(); |
| 5493 uc32 octal = ParseOctalLiteral(); |
| 5494 builder->AddCharacter(octal); |
| 5495 break; |
| 5496 } |
| 5497 // ControlEscape :: one of |
| 5498 // f n r t v |
| 5499 case 'f': |
| 5500 Advance(2); |
| 5501 builder->AddCharacter('\f'); |
| 5502 break; |
| 5503 case 'n': |
| 5504 Advance(2); |
| 5505 builder->AddCharacter('\n'); |
| 5506 break; |
| 5507 case 'r': |
| 5508 Advance(2); |
| 5509 builder->AddCharacter('\r'); |
| 5510 break; |
| 5511 case 't': |
| 5512 Advance(2); |
| 5513 builder->AddCharacter('\t'); |
| 5514 break; |
| 5515 case 'v': |
| 5516 Advance(2); |
| 5517 builder->AddCharacter('\v'); |
| 5518 break; |
| 5519 case 'c': { |
| 5520 Advance(); |
| 5521 uc32 controlLetter = Next(); |
| 5522 // Special case if it is an ASCII letter. |
| 5523 // Convert lower case letters to uppercase. |
| 5524 uc32 letter = controlLetter & ~('a' ^ 'A'); |
| 5525 if (letter < 'A' || 'Z' < letter) { |
| 5526 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
| 5527 // This is outside the specification. We match JSC in |
| 5528 // reading the backslash as a literal character instead |
| 5529 // of as starting an escape. |
| 5530 builder->AddCharacter('\\'); |
| 5531 } else { |
| 5532 Advance(2); |
| 5533 builder->AddCharacter(controlLetter & 0x1f); |
| 5534 } |
| 5535 break; |
| 5536 } |
| 5537 case 'x': { |
| 5538 Advance(2); |
| 5539 uc32 value; |
| 5540 if (ParseHexEscape(2, &value)) { |
| 5541 builder->AddCharacter(value); |
| 5542 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5543 builder->AddCharacter('x'); |
| 5544 } else { |
| 5545 // If the 'u' flag is present, invalid escapes are not treated as |
| 5546 // identity escapes. |
| 5547 return ReportError(CStrVector("Invalid escape")); |
| 5548 } |
| 5549 break; |
| 5550 } |
| 5551 case 'u': { |
| 5552 Advance(2); |
| 5553 uc32 value; |
| 5554 if (ParseUnicodeEscape(&value)) { |
| 5555 builder->AddCharacter(value); |
| 5556 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5557 builder->AddCharacter('u'); |
| 5558 } else { |
| 5559 // If the 'u' flag is present, invalid escapes are not treated as |
| 5560 // identity escapes. |
| 5561 return ReportError(CStrVector("Invalid unicode escape")); |
| 5562 } |
| 5563 break; |
| 5564 } |
| 5565 default: |
| 5566 Advance(); |
| 5567 // If the 'u' flag is present, only syntax characters can be |
| 5568 // escaped, no |
| 5569 // other identity escapes are allowed. If the 'u' flag is not |
| 5570 // present, |
| 5571 // all identity escapes are allowed. |
| 5572 if (!FLAG_harmony_unicode_regexps || !unicode_ || |
| 5573 IsSyntaxCharacter(current())) { |
| 5574 builder->AddCharacter(current()); |
| 5400 Advance(); | 5575 Advance(); |
| 5401 lookaround_type = RegExpLookaround::LOOKBEHIND; | 5576 } else { |
| 5402 if (Next() == '=') { | 5577 return ReportError(CStrVector("Invalid escape")); |
| 5403 subexpr_type = POSITIVE_LOOKAROUND; | 5578 } |
| 5404 break; | 5579 break; |
| 5405 } else if (Next() == '!') { | 5580 } |
| 5406 subexpr_type = NEGATIVE_LOOKAROUND; | 5581 break; |
| 5407 break; | 5582 case '{': { |
| 5408 } | 5583 int dummy; |
| 5409 } | 5584 if (ParseIntervalQuantifier(&dummy, &dummy)) { |
| 5410 // Fall through. | 5585 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED); |
| 5411 default: | 5586 } |
| 5412 ReportError(CStrVector("Invalid group") CHECK_FAILED); | 5587 // fallthrough |
| 5413 break; | |
| 5414 } | |
| 5415 Advance(2); | |
| 5416 } else { | |
| 5417 if (captures_started_ >= kMaxCaptures) { | |
| 5418 ReportError(CStrVector("Too many captures") CHECK_FAILED); | |
| 5419 } | |
| 5420 captures_started_++; | |
| 5421 } | |
| 5422 // Store current state and begin new disjunction parsing. | |
| 5423 state = new (zone()) RegExpParserState( | |
| 5424 state, subexpr_type, lookaround_type, captures_started_, zone()); | |
| 5425 builder = state->builder(); | |
| 5426 continue; | |
| 5427 } | |
| 5428 case '[': { | |
| 5429 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED); | |
| 5430 builder->AddAtom(atom); | |
| 5431 break; | |
| 5432 } | |
| 5433 // Atom :: | |
| 5434 // \ AtomEscape | |
| 5435 case '\\': | |
| 5436 switch (Next()) { | |
| 5437 case kEndMarker: | |
| 5438 return ReportError(CStrVector("\\ at end of pattern")); | |
| 5439 case 'b': | |
| 5440 Advance(2); | |
| 5441 builder->AddAssertion( | |
| 5442 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY)); | |
| 5443 continue; | |
| 5444 case 'B': | |
| 5445 Advance(2); | |
| 5446 builder->AddAssertion( | |
| 5447 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); | |
| 5448 continue; | |
| 5449 // AtomEscape :: | |
| 5450 // CharacterClassEscape | |
| 5451 // | |
| 5452 // CharacterClassEscape :: one of | |
| 5453 // d D s S w W | |
| 5454 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': { | |
| 5455 uc32 c = Next(); | |
| 5456 Advance(2); | |
| 5457 ZoneList<CharacterRange>* ranges = | |
| 5458 new(zone()) ZoneList<CharacterRange>(2, zone()); | |
| 5459 CharacterRange::AddClassEscape(c, ranges, zone()); | |
| 5460 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); | |
| 5461 builder->AddAtom(atom); | |
| 5462 break; | |
| 5463 } | |
| 5464 case '1': case '2': case '3': case '4': case '5': case '6': | |
| 5465 case '7': case '8': case '9': { | |
| 5466 int index = 0; | |
| 5467 if (ParseBackReferenceIndex(&index)) { | |
| 5468 if (state->IsInsideCaptureGroup(index)) { | |
| 5469 // The backreference is inside the capture group it refers to. | |
| 5470 // Nothing can possibly have been captured yet. | |
| 5471 builder->AddEmpty(); | |
| 5472 } else { | |
| 5473 RegExpCapture* capture = GetCapture(index); | |
| 5474 RegExpTree* atom = new (zone()) RegExpBackReference(capture); | |
| 5475 builder->AddAtom(atom); | |
| 5476 } | |
| 5477 break; | |
| 5478 } | |
| 5479 uc32 first_digit = Next(); | |
| 5480 if (first_digit == '8' || first_digit == '9') { | |
| 5481 // If the 'u' flag is present, only syntax characters can be escaped, | |
| 5482 // no other identity escapes are allowed. If the 'u' flag is not | |
| 5483 // present, all identity escapes are allowed. | |
| 5484 if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
| 5485 builder->AddCharacter(first_digit); | |
| 5486 Advance(2); | |
| 5487 } else { | |
| 5488 return ReportError(CStrVector("Invalid escape")); | |
| 5489 } | |
| 5490 break; | |
| 5491 } | |
| 5492 } | |
| 5493 // FALLTHROUGH | |
| 5494 case '0': { | |
| 5495 Advance(); | |
| 5496 uc32 octal = ParseOctalLiteral(); | |
| 5497 builder->AddCharacter(octal); | |
| 5498 break; | |
| 5499 } | |
| 5500 // ControlEscape :: one of | |
| 5501 // f n r t v | |
| 5502 case 'f': | |
| 5503 Advance(2); | |
| 5504 builder->AddCharacter('\f'); | |
| 5505 break; | |
| 5506 case 'n': | |
| 5507 Advance(2); | |
| 5508 builder->AddCharacter('\n'); | |
| 5509 break; | |
| 5510 case 'r': | |
| 5511 Advance(2); | |
| 5512 builder->AddCharacter('\r'); | |
| 5513 break; | |
| 5514 case 't': | |
| 5515 Advance(2); | |
| 5516 builder->AddCharacter('\t'); | |
| 5517 break; | |
| 5518 case 'v': | |
| 5519 Advance(2); | |
| 5520 builder->AddCharacter('\v'); | |
| 5521 break; | |
| 5522 case 'c': { | |
| 5523 Advance(); | |
| 5524 uc32 controlLetter = Next(); | |
| 5525 // Special case if it is an ASCII letter. | |
| 5526 // Convert lower case letters to uppercase. | |
| 5527 uc32 letter = controlLetter & ~('a' ^ 'A'); | |
| 5528 if (letter < 'A' || 'Z' < letter) { | |
| 5529 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. | |
| 5530 // This is outside the specification. We match JSC in | |
| 5531 // reading the backslash as a literal character instead | |
| 5532 // of as starting an escape. | |
| 5533 builder->AddCharacter('\\'); | |
| 5534 } else { | |
| 5535 Advance(2); | |
| 5536 builder->AddCharacter(controlLetter & 0x1f); | |
| 5537 } | |
| 5538 break; | |
| 5539 } | |
| 5540 case 'x': { | |
| 5541 Advance(2); | |
| 5542 uc32 value; | |
| 5543 if (ParseHexEscape(2, &value)) { | |
| 5544 builder->AddCharacter(value); | |
| 5545 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
| 5546 builder->AddCharacter('x'); | |
| 5547 } else { | |
| 5548 // If the 'u' flag is present, invalid escapes are not treated as | |
| 5549 // identity escapes. | |
| 5550 return ReportError(CStrVector("Invalid escape")); | |
| 5551 } | |
| 5552 break; | |
| 5553 } | |
| 5554 case 'u': { | |
| 5555 Advance(2); | |
| 5556 uc32 value; | |
| 5557 if (ParseUnicodeEscape(&value)) { | |
| 5558 builder->AddCharacter(value); | |
| 5559 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
| 5560 builder->AddCharacter('u'); | |
| 5561 } else { | |
| 5562 // If the 'u' flag is present, invalid escapes are not treated as | |
| 5563 // identity escapes. | |
| 5564 return ReportError(CStrVector("Invalid unicode escape")); | |
| 5565 } | |
| 5566 break; | |
| 5567 } | 5588 } |
| 5568 default: | 5589 default: |
| 5569 Advance(); | 5590 builder->AddCharacter(current()); |
| 5570 // If the 'u' flag is present, only syntax characters can be escaped, no | 5591 Advance(); |
| 5571 // other identity escapes are allowed. If the 'u' flag is not present, | 5592 break; |
| 5572 // all identity escapes are allowed. | |
| 5573 if (!FLAG_harmony_unicode_regexps || !unicode_ || | |
| 5574 IsSyntaxCharacter(current())) { | |
| 5575 builder->AddCharacter(current()); | |
| 5576 Advance(); | |
| 5577 } else { | |
| 5578 return ReportError(CStrVector("Invalid escape")); | |
| 5579 } | |
| 5580 break; | |
| 5581 } | |
| 5582 break; | |
| 5583 case '{': { | |
| 5584 int dummy; | |
| 5585 if (ParseIntervalQuantifier(&dummy, &dummy)) { | |
| 5586 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED); | |
| 5587 } | |
| 5588 // fallthrough | |
| 5589 } | |
| 5590 default: | |
| 5591 builder->AddCharacter(current()); | |
| 5592 Advance(); | |
| 5593 break; | |
| 5594 } // end switch(current()) | 5593 } // end switch(current()) |
| 5595 | 5594 |
| 5596 int min; | 5595 int min; |
| 5597 int max; | 5596 int max; |
| 5598 switch (current()) { | 5597 switch (current()) { |
| 5599 // QuantifierPrefix :: | 5598 // QuantifierPrefix :: |
| 5600 // * | 5599 // * |
| 5601 // + | 5600 // + |
| 5602 // ? | 5601 // ? |
| 5603 // { | 5602 // { |
| 5604 case '*': | 5603 case '*': |
| 5605 min = 0; | 5604 min = 0; |
| 5606 max = RegExpTree::kInfinity; | 5605 max = RegExpTree::kInfinity; |
| 5607 Advance(); | 5606 Advance(); |
| 5608 break; | 5607 break; |
| 5609 case '+': | 5608 case '+': |
| 5610 min = 1; | 5609 min = 1; |
| 5611 max = RegExpTree::kInfinity; | 5610 max = RegExpTree::kInfinity; |
| 5612 Advance(); | 5611 Advance(); |
| 5613 break; | 5612 break; |
| 5614 case '?': | 5613 case '?': |
| 5615 min = 0; | 5614 min = 0; |
| 5616 max = 1; | 5615 max = 1; |
| 5617 Advance(); | 5616 Advance(); |
| 5618 break; | 5617 break; |
| 5619 case '{': | 5618 case '{': |
| 5620 if (ParseIntervalQuantifier(&min, &max)) { | 5619 if (ParseIntervalQuantifier(&min, &max)) { |
| 5621 if (max < min) { | 5620 if (max < min) { |
| 5622 ReportError(CStrVector("numbers out of order in {} quantifier.") | 5621 ReportError(CStrVector("numbers out of order in {} quantifier.") |
| 5623 CHECK_FAILED); | 5622 CHECK_FAILED); |
| 5624 } | 5623 } |
| 5625 break; | 5624 break; |
| 5626 } else { | 5625 } else { |
| 5627 continue; | 5626 continue; |
| 5628 } | 5627 } |
| 5629 default: | 5628 default: |
| 5630 continue; | 5629 continue; |
| 5631 } | 5630 } |
| 5632 RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; | 5631 RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; |
| 5633 if (current() == '?') { | 5632 if (current() == '?') { |
| 5634 quantifier_type = RegExpQuantifier::NON_GREEDY; | 5633 quantifier_type = RegExpQuantifier::NON_GREEDY; |
| 5635 Advance(); | 5634 Advance(); |
| 5636 } else if (FLAG_regexp_possessive_quantifier && current() == '+') { | 5635 } else if (FLAG_regexp_possessive_quantifier && current() == '+') { |
| 5637 // FLAG_regexp_possessive_quantifier is a debug-only flag. | 5636 // FLAG_regexp_possessive_quantifier is a debug-only flag. |
| 5638 quantifier_type = RegExpQuantifier::POSSESSIVE; | 5637 quantifier_type = RegExpQuantifier::POSSESSIVE; |
| 5639 Advance(); | 5638 Advance(); |
| 5640 } | 5639 } |
| 5641 builder->AddQuantifierToAtom(min, max, quantifier_type); | 5640 builder->AddQuantifierToAtom(min, max, quantifier_type); |
| 5642 } | 5641 } |
| 5643 } | 5642 } |
| 5644 | 5643 |
| 5645 | 5644 |
| 5646 #ifdef DEBUG | 5645 #ifdef DEBUG |
| 5647 // Currently only used in an DCHECK. | 5646 // Currently only used in an DCHECK. |
| 5648 static bool IsSpecialClassEscape(uc32 c) { | 5647 static bool IsSpecialClassEscape(uc32 c) { |
| 5649 switch (c) { | 5648 switch (c) { |
| 5650 case 'd': case 'D': | 5649 case 'd': |
| 5651 case 's': case 'S': | 5650 case 'D': |
| 5652 case 'w': case 'W': | 5651 case 's': |
| 5652 case 'S': |
| 5653 case 'w': |
| 5654 case 'W': |
| 5653 return true; | 5655 return true; |
| 5654 default: | 5656 default: |
| 5655 return false; | 5657 return false; |
| 5656 } | 5658 } |
| 5657 } | 5659 } |
| 5658 #endif | 5660 #endif |
| 5659 | 5661 |
| 5660 | 5662 |
| 5661 // In order to know whether an escape is a backreference or not we have to scan | 5663 // In order to know whether an escape is a backreference or not we have to scan |
| 5662 // the entire regexp and find the number of capturing parentheses. However we | 5664 // the entire regexp and find the number of capturing parentheses. However we |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5929 return '\t'; | 5931 return '\t'; |
| 5930 case 'v': | 5932 case 'v': |
| 5931 Advance(); | 5933 Advance(); |
| 5932 return '\v'; | 5934 return '\v'; |
| 5933 case 'c': { | 5935 case 'c': { |
| 5934 uc32 controlLetter = Next(); | 5936 uc32 controlLetter = Next(); |
| 5935 uc32 letter = controlLetter & ~('A' ^ 'a'); | 5937 uc32 letter = controlLetter & ~('A' ^ 'a'); |
| 5936 // For compatibility with JSC, inside a character class | 5938 // For compatibility with JSC, inside a character class |
| 5937 // we also accept digits and underscore as control characters. | 5939 // we also accept digits and underscore as control characters. |
| 5938 if ((controlLetter >= '0' && controlLetter <= '9') || | 5940 if ((controlLetter >= '0' && controlLetter <= '9') || |
| 5939 controlLetter == '_' || | 5941 controlLetter == '_' || (letter >= 'A' && letter <= 'Z')) { |
| 5940 (letter >= 'A' && letter <= 'Z')) { | |
| 5941 Advance(2); | 5942 Advance(2); |
| 5942 // Control letters mapped to ASCII control characters in the range | 5943 // Control letters mapped to ASCII control characters in the range |
| 5943 // 0x00-0x1f. | 5944 // 0x00-0x1f. |
| 5944 return controlLetter & 0x1f; | 5945 return controlLetter & 0x1f; |
| 5945 } | 5946 } |
| 5946 // We match JSC in reading the backslash as a literal | 5947 // We match JSC in reading the backslash as a literal |
| 5947 // character instead of as starting an escape. | 5948 // character instead of as starting an escape. |
| 5948 return '\\'; | 5949 return '\\'; |
| 5949 } | 5950 } |
| 5950 case '0': case '1': case '2': case '3': case '4': case '5': | 5951 case '0': |
| 5951 case '6': case '7': | 5952 case '1': |
| 5953 case '2': |
| 5954 case '3': |
| 5955 case '4': |
| 5956 case '5': |
| 5957 case '6': |
| 5958 case '7': |
| 5952 // For compatibility, we interpret a decimal escape that isn't | 5959 // For compatibility, we interpret a decimal escape that isn't |
| 5953 // a back reference (and therefore either \0 or not valid according | 5960 // a back reference (and therefore either \0 or not valid according |
| 5954 // to the specification) as a 1..3 digit octal character code. | 5961 // to the specification) as a 1..3 digit octal character code. |
| 5955 return ParseOctalLiteral(); | 5962 return ParseOctalLiteral(); |
| 5956 case 'x': { | 5963 case 'x': { |
| 5957 Advance(); | 5964 Advance(); |
| 5958 uc32 value; | 5965 uc32 value; |
| 5959 if (ParseHexEscape(2, &value)) { | 5966 if (ParseHexEscape(2, &value)) { |
| 5960 return value; | 5967 return value; |
| 5961 } | 5968 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5999 } | 6006 } |
| 6000 return 0; | 6007 return 0; |
| 6001 } | 6008 } |
| 6002 | 6009 |
| 6003 | 6010 |
| 6004 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { | 6011 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { |
| 6005 DCHECK_EQ(0, *char_class); | 6012 DCHECK_EQ(0, *char_class); |
| 6006 uc32 first = current(); | 6013 uc32 first = current(); |
| 6007 if (first == '\\') { | 6014 if (first == '\\') { |
| 6008 switch (Next()) { | 6015 switch (Next()) { |
| 6009 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': { | 6016 case 'w': |
| 6017 case 'W': |
| 6018 case 'd': |
| 6019 case 'D': |
| 6020 case 's': |
| 6021 case 'S': { |
| 6010 *char_class = Next(); | 6022 *char_class = Next(); |
| 6011 Advance(2); | 6023 Advance(2); |
| 6012 return CharacterRange::Singleton(0); // Return dummy value. | 6024 return CharacterRange::Singleton(0); // Return dummy value. |
| 6013 } | 6025 } |
| 6014 case kEndMarker: | 6026 case kEndMarker: |
| 6015 return ReportError(CStrVector("\\ at end of pattern")); | 6027 return ReportError(CStrVector("\\ at end of pattern")); |
| 6016 default: | 6028 default: |
| 6017 uc32 c = ParseClassCharacterEscape(CHECK_FAILED); | 6029 uc32 c = ParseClassCharacterEscape(CHECK_FAILED); |
| 6018 return CharacterRange::Singleton(c); | 6030 return CharacterRange::Singleton(c); |
| 6019 } | 6031 } |
| 6020 } else { | 6032 } else { |
| 6021 Advance(); | 6033 Advance(); |
| 6022 return CharacterRange::Singleton(first); | 6034 return CharacterRange::Singleton(first); |
| 6023 } | 6035 } |
| 6024 } | 6036 } |
| 6025 | 6037 |
| 6026 | 6038 |
| 6027 static const uc16 kNoCharClass = 0; | 6039 static const uc16 kNoCharClass = 0; |
| 6028 | 6040 |
| 6029 // Adds range or pre-defined character class to character ranges. | 6041 // Adds range or pre-defined character class to character ranges. |
| 6030 // If char_class is not kInvalidClass, it's interpreted as a class | 6042 // If char_class is not kInvalidClass, it's interpreted as a class |
| 6031 // escape (i.e., 's' means whitespace, from '\s'). | 6043 // escape (i.e., 's' means whitespace, from '\s'). |
| 6032 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, | 6044 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, |
| 6033 uc16 char_class, | 6045 uc16 char_class, CharacterRange range, |
| 6034 CharacterRange range, | |
| 6035 Zone* zone) { | 6046 Zone* zone) { |
| 6036 if (char_class != kNoCharClass) { | 6047 if (char_class != kNoCharClass) { |
| 6037 CharacterRange::AddClassEscape(char_class, ranges, zone); | 6048 CharacterRange::AddClassEscape(char_class, ranges, zone); |
| 6038 } else { | 6049 } else { |
| 6039 ranges->Add(range, zone); | 6050 ranges->Add(range, zone); |
| 6040 } | 6051 } |
| 6041 } | 6052 } |
| 6042 | 6053 |
| 6043 | 6054 |
| 6044 RegExpTree* RegExpParser::ParseCharacterClass() { | 6055 RegExpTree* RegExpParser::ParseCharacterClass() { |
| 6045 static const char* kUnterminated = "Unterminated character class"; | 6056 static const char* kUnterminated = "Unterminated character class"; |
| 6046 static const char* kRangeOutOfOrder = "Range out of order in character class"; | 6057 static const char* kRangeOutOfOrder = "Range out of order in character class"; |
| 6047 | 6058 |
| 6048 DCHECK_EQ(current(), '['); | 6059 DCHECK_EQ(current(), '['); |
| 6049 Advance(); | 6060 Advance(); |
| 6050 bool is_negated = false; | 6061 bool is_negated = false; |
| 6051 if (current() == '^') { | 6062 if (current() == '^') { |
| 6052 is_negated = true; | 6063 is_negated = true; |
| 6053 Advance(); | 6064 Advance(); |
| 6054 } | 6065 } |
| 6055 ZoneList<CharacterRange>* ranges = | 6066 ZoneList<CharacterRange>* ranges = |
| 6056 new(zone()) ZoneList<CharacterRange>(2, zone()); | 6067 new (zone()) ZoneList<CharacterRange>(2, zone()); |
| 6057 while (has_more() && current() != ']') { | 6068 while (has_more() && current() != ']') { |
| 6058 uc16 char_class = kNoCharClass; | 6069 uc16 char_class = kNoCharClass; |
| 6059 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); | 6070 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); |
| 6060 if (current() == '-') { | 6071 if (current() == '-') { |
| 6061 Advance(); | 6072 Advance(); |
| 6062 if (current() == kEndMarker) { | 6073 if (current() == kEndMarker) { |
| 6063 // If we reach the end we break out of the loop and let the | 6074 // If we reach the end we break out of the loop and let the |
| 6064 // following code report an error. | 6075 // following code report an error. |
| 6065 break; | 6076 break; |
| 6066 } else if (current() == ']') { | 6077 } else if (current() == ']') { |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6242 Expression* cooked_str = cooked_strings->at(i); | 6253 Expression* cooked_str = cooked_strings->at(i); |
| 6243 | 6254 |
| 6244 // Let middle be ToString(sub). | 6255 // Let middle be ToString(sub). |
| 6245 ZoneList<Expression*>* args = | 6256 ZoneList<Expression*>* args = |
| 6246 new (zone()) ZoneList<Expression*>(1, zone()); | 6257 new (zone()) ZoneList<Expression*>(1, zone()); |
| 6247 args->Add(sub, zone()); | 6258 args->Add(sub, zone()); |
| 6248 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString, | 6259 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString, |
| 6249 args, sub->position()); | 6260 args, sub->position()); |
| 6250 | 6261 |
| 6251 expr = factory()->NewBinaryOperation( | 6262 expr = factory()->NewBinaryOperation( |
| 6252 Token::ADD, factory()->NewBinaryOperation( | 6263 Token::ADD, factory()->NewBinaryOperation(Token::ADD, expr, middle, |
| 6253 Token::ADD, expr, middle, expr->position()), | 6264 expr->position()), |
| 6254 cooked_str, sub->position()); | 6265 cooked_str, sub->position()); |
| 6255 } | 6266 } |
| 6256 return expr; | 6267 return expr; |
| 6257 } else { | 6268 } else { |
| 6258 uint32_t hash = ComputeTemplateLiteralHash(lit); | 6269 uint32_t hash = ComputeTemplateLiteralHash(lit); |
| 6259 | 6270 |
| 6260 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); | 6271 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); |
| 6261 int raw_idx = function_state_->NextMaterializedLiteralIndex(); | 6272 int raw_idx = function_state_->NextMaterializedLiteralIndex(); |
| 6262 | 6273 |
| 6263 // $getTemplateCallSite | 6274 // $getTemplateCallSite |
| 6264 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); | 6275 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); |
| 6265 args->Add(factory()->NewArrayLiteral( | 6276 args->Add(factory()->NewArrayLiteral( |
| 6266 const_cast<ZoneList<Expression*>*>(cooked_strings), | 6277 const_cast<ZoneList<Expression*>*>(cooked_strings), |
| 6267 cooked_idx, is_strong(language_mode()), pos), | 6278 cooked_idx, is_strong(language_mode()), pos), |
| 6268 zone()); | 6279 zone()); |
| 6269 args->Add( | 6280 args->Add(factory()->NewArrayLiteral( |
| 6270 factory()->NewArrayLiteral( | 6281 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, |
| 6271 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, | 6282 is_strong(language_mode()), pos), |
| 6272 is_strong(language_mode()), pos), | 6283 zone()); |
| 6273 zone()); | |
| 6274 | 6284 |
| 6275 // Ensure hash is suitable as a Smi value | 6285 // Ensure hash is suitable as a Smi value |
| 6276 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); | 6286 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); |
| 6277 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); | 6287 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); |
| 6278 | 6288 |
| 6279 this->CheckPossibleEvalCall(tag, scope_); | 6289 this->CheckPossibleEvalCall(tag, scope_); |
| 6280 Expression* call_site = factory()->NewCallRuntime( | 6290 Expression* call_site = factory()->NewCallRuntime( |
| 6281 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start); | 6291 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start); |
| 6282 | 6292 |
| 6283 // Call TagFn | 6293 // Call TagFn |
| 6284 ZoneList<Expression*>* call_args = | 6294 ZoneList<Expression*>* call_args = |
| 6285 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); | 6295 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); |
| 6286 call_args->Add(call_site, zone()); | 6296 call_args->Add(call_site, zone()); |
| 6287 call_args->AddAll(*expressions, zone()); | 6297 call_args->AddAll(*expressions, zone()); |
| 6288 return factory()->NewCall(tag, call_args, pos); | 6298 return factory()->NewCall(tag, call_args, pos); |
| 6289 } | 6299 } |
| 6290 } | 6300 } |
| 6291 | 6301 |
| 6292 | 6302 |
| 6293 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { | 6303 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { |
| 6294 const ZoneList<Expression*>* raw_strings = lit->raw(); | 6304 const ZoneList<Expression*>* raw_strings = lit->raw(); |
| 6295 int total = raw_strings->length(); | 6305 int total = raw_strings->length(); |
| 6296 DCHECK(total); | 6306 DCHECK(total); |
| 6297 | 6307 |
| 6298 uint32_t running_hash = 0; | 6308 uint32_t running_hash = 0; |
| 6299 | 6309 |
| 6300 for (int index = 0; index < total; ++index) { | 6310 for (int index = 0; index < total; ++index) { |
| 6301 if (index) { | 6311 if (index) { |
| 6302 running_hash = StringHasher::ComputeRunningHashOneByte( | 6312 running_hash = |
| 6303 running_hash, "${}", 3); | 6313 StringHasher::ComputeRunningHashOneByte(running_hash, "${}", 3); |
| 6304 } | 6314 } |
| 6305 | 6315 |
| 6306 const AstRawString* raw_string = | 6316 const AstRawString* raw_string = |
| 6307 raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); | 6317 raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); |
| 6308 if (raw_string->is_one_byte()) { | 6318 if (raw_string->is_one_byte()) { |
| 6309 const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); | 6319 const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); |
| 6310 running_hash = StringHasher::ComputeRunningHashOneByte( | 6320 running_hash = StringHasher::ComputeRunningHashOneByte( |
| 6311 running_hash, data, raw_string->length()); | 6321 running_hash, data, raw_string->length()); |
| 6312 } else { | 6322 } else { |
| 6313 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 6323 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6455 } | 6465 } |
| 6456 | 6466 |
| 6457 | 6467 |
| 6458 void Parser::RaiseLanguageMode(LanguageMode mode) { | 6468 void Parser::RaiseLanguageMode(LanguageMode mode) { |
| 6459 SetLanguageMode(scope_, | 6469 SetLanguageMode(scope_, |
| 6460 static_cast<LanguageMode>(scope_->language_mode() | mode)); | 6470 static_cast<LanguageMode>(scope_->language_mode() | mode)); |
| 6461 } | 6471 } |
| 6462 | 6472 |
| 6463 } // namespace internal | 6473 } // namespace internal |
| 6464 } // namespace v8 | 6474 } // namespace v8 |
| OLD | NEW |