| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
| 6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
| 7 | 7 |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/base/hashmap.h" | 10 #include "src/base/hashmap.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 119 |
| 120 | 120 |
| 121 // ---------------------------------------------------------------------------- | 121 // ---------------------------------------------------------------------------- |
| 122 // The CHECK_OK macro is a convenient macro to enforce error | 122 // The CHECK_OK macro is a convenient macro to enforce error |
| 123 // handling for functions that may fail (by returning !*ok). | 123 // handling for functions that may fail (by returning !*ok). |
| 124 // | 124 // |
| 125 // CAUTION: This macro appends extra statements after a call, | 125 // CAUTION: This macro appends extra statements after a call, |
| 126 // thus it must never be used where only a single statement | 126 // thus it must never be used where only a single statement |
| 127 // is correct (e.g. an if statement branch w/o braces)! | 127 // is correct (e.g. an if statement branch w/o braces)! |
| 128 | 128 |
| 129 #define CHECK_OK_CUSTOM(x) ok); \ | 129 #define CHECK_OK_CUSTOM(x, ...) ok); \ |
| 130 if (!*ok) return impl()->x(); \ | 130 if (!*ok) return impl()->x(__VA_ARGS__); \ |
| 131 ((void)0 | 131 ((void)0 |
| 132 #define DUMMY ) // to make indentation work | 132 #define DUMMY ) // to make indentation work |
| 133 #undef DUMMY | 133 #undef DUMMY |
| 134 | 134 |
| 135 // Used in functions where the return type is ExpressionT. | 135 // Used in functions where the return type is ExpressionT. |
| 136 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) | 136 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) |
| 137 | 137 |
| 138 // Common base class template shared between parser and pre-parser. | 138 // Common base class template shared between parser and pre-parser. |
| 139 // The Impl parameter is the actual class of the parser/pre-parser, | 139 // The Impl parameter is the actual class of the parser/pre-parser, |
| 140 // following the Curiously Recurring Template Pattern (CRTP). | 140 // following the Curiously Recurring Template Pattern (CRTP). |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 | 266 |
| 267 uintptr_t stack_limit() const { return stack_limit_; } | 267 uintptr_t stack_limit() const { return stack_limit_; } |
| 268 | 268 |
| 269 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 269 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
| 270 | 270 |
| 271 Zone* zone() const { return zone_; } | 271 Zone* zone() const { return zone_; } |
| 272 | 272 |
| 273 protected: | 273 protected: |
| 274 friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>; | 274 friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>; |
| 275 | 275 |
| 276 // clang-format off |
| 276 enum AllowRestrictedIdentifiers { | 277 enum AllowRestrictedIdentifiers { |
| 277 kAllowRestrictedIdentifiers, | 278 kAllowRestrictedIdentifiers, |
| 278 kDontAllowRestrictedIdentifiers | 279 kDontAllowRestrictedIdentifiers |
| 279 }; | 280 }; |
| 280 | 281 |
| 281 enum Mode { | 282 enum Mode { |
| 282 PARSE_LAZILY, | 283 PARSE_LAZILY, |
| 283 PARSE_EAGERLY | 284 PARSE_EAGERLY |
| 284 }; | 285 }; |
| 285 | 286 |
| 287 enum LazyParsingResult { |
| 288 kLazyParsingComplete, |
| 289 kLazyParsingAborted |
| 290 }; |
| 291 |
| 286 enum VariableDeclarationContext { | 292 enum VariableDeclarationContext { |
| 287 kStatementListItem, | 293 kStatementListItem, |
| 288 kStatement, | 294 kStatement, |
| 289 kForStatement | 295 kForStatement |
| 290 }; | 296 }; |
| 297 // clang-format on |
| 291 | 298 |
| 292 class Checkpoint; | 299 class Checkpoint; |
| 293 class ObjectLiteralCheckerBase; | 300 class ObjectLiteralCheckerBase; |
| 294 | 301 |
| 295 // --------------------------------------------------------------------------- | 302 // --------------------------------------------------------------------------- |
| 296 // ScopeState and its subclasses implement the parser's scope stack. | 303 // ScopeState and its subclasses implement the parser's scope stack. |
| 297 // ScopeState keeps track of the current scope, and the outer ScopeState. The | 304 // ScopeState keeps track of the current scope, and the outer ScopeState. The |
| 298 // parser's scope_state_ points to the top ScopeState. ScopeState's | 305 // parser's scope_state_ points to the top ScopeState. ScopeState's |
| 299 // constructor push on the scope stack and the destructors pop. BlockState and | 306 // constructor push on the scope stack and the destructors pop. BlockState and |
| 300 // FunctionState are used to hold additional per-block and per-function state. | 307 // FunctionState are used to hold additional per-block and per-function state. |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 return; | 785 return; |
| 779 } | 786 } |
| 780 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 787 if (scanner()->HasAnyLineTerminatorBeforeNext() || |
| 781 tok == Token::RBRACE || | 788 tok == Token::RBRACE || |
| 782 tok == Token::EOS) { | 789 tok == Token::EOS) { |
| 783 return; | 790 return; |
| 784 } | 791 } |
| 785 Expect(Token::SEMICOLON, ok); | 792 Expect(Token::SEMICOLON, ok); |
| 786 } | 793 } |
| 787 | 794 |
| 788 // A dummy function, just useful as an argument to CHECK_OK_CUSTOM. | 795 // Dummy functions, just useful as arguments to CHECK_OK_CUSTOM. |
| 789 static void Void() {} | 796 static void Void() {} |
| 797 template <typename T> |
| 798 static T Return(T result) { |
| 799 return result; |
| 800 } |
| 790 | 801 |
| 791 bool is_any_identifier(Token::Value token) { | 802 bool is_any_identifier(Token::Value token) { |
| 792 return token == Token::IDENTIFIER || token == Token::ENUM || | 803 return token == Token::IDENTIFIER || token == Token::ENUM || |
| 793 token == Token::AWAIT || token == Token::ASYNC || | 804 token == Token::AWAIT || token == Token::ASYNC || |
| 794 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || | 805 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || |
| 795 token == Token::STATIC || token == Token::YIELD; | 806 token == Token::STATIC || token == Token::YIELD; |
| 796 } | 807 } |
| 797 bool peek_any_identifier() { return is_any_identifier(peek()); } | 808 bool peek_any_identifier() { return is_any_identifier(peek()); } |
| 798 | 809 |
| 799 bool CheckContextualKeyword(Vector<const char> keyword) { | 810 bool CheckContextualKeyword(Vector<const char> keyword) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 813 const char* full_name, int pos, bool* ok); | 824 const char* full_name, int pos, bool* ok); |
| 814 | 825 |
| 815 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | 826 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { |
| 816 Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void)); | 827 Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void)); |
| 817 if (!scanner()->is_literal_contextual_keyword(keyword)) { | 828 if (!scanner()->is_literal_contextual_keyword(keyword)) { |
| 818 ReportUnexpectedToken(scanner()->current_token()); | 829 ReportUnexpectedToken(scanner()->current_token()); |
| 819 *ok = false; | 830 *ok = false; |
| 820 } | 831 } |
| 821 } | 832 } |
| 822 | 833 |
| 823 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { | 834 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode) { |
| 824 if (Check(Token::IN)) { | 835 if (Check(Token::IN)) { |
| 825 *visit_mode = ForEachStatement::ENUMERATE; | 836 *visit_mode = ForEachStatement::ENUMERATE; |
| 826 return true; | 837 return true; |
| 827 } else if (CheckContextualKeyword(CStrVector("of"))) { | 838 } else if (CheckContextualKeyword(CStrVector("of"))) { |
| 828 *visit_mode = ForEachStatement::ITERATE; | 839 *visit_mode = ForEachStatement::ITERATE; |
| 829 return true; | 840 return true; |
| 830 } | 841 } |
| 831 return false; | 842 return false; |
| 832 } | 843 } |
| 833 | 844 |
| (...skipping 2643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3477 bool* ok) { | 3488 bool* ok) { |
| 3478 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { | 3489 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { |
| 3479 // ASI inserts `;` after arrow parameters if a line terminator is found. | 3490 // ASI inserts `;` after arrow parameters if a line terminator is found. |
| 3480 // `=> ...` is never a valid expression, so report as syntax error. | 3491 // `=> ...` is never a valid expression, so report as syntax error. |
| 3481 // If next token is not `=>`, it's a syntax error anyways. | 3492 // If next token is not `=>`, it's a syntax error anyways. |
| 3482 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW); | 3493 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW); |
| 3483 *ok = false; | 3494 *ok = false; |
| 3484 return impl()->EmptyExpression(); | 3495 return impl()->EmptyExpression(); |
| 3485 } | 3496 } |
| 3486 | 3497 |
| 3487 typename Types::StatementList body; | 3498 typename Types::StatementList body = impl()->NullStatementList(); |
| 3488 int num_parameters = formal_parameters.scope->num_parameters(); | 3499 int num_parameters = formal_parameters.scope->num_parameters(); |
| 3489 int materialized_literal_count = -1; | 3500 int materialized_literal_count = -1; |
| 3490 int expected_property_count = -1; | 3501 int expected_property_count = -1; |
| 3491 | 3502 |
| 3492 FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction; | 3503 FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction; |
| 3504 FunctionLiteral::EagerCompileHint eager_compile_hint = |
| 3505 FunctionLiteral::kShouldLazyCompile; |
| 3506 bool should_be_used_once_hint = false; |
| 3493 { | 3507 { |
| 3494 FunctionState function_state(&function_state_, &scope_state_, | 3508 FunctionState function_state(&function_state_, &scope_state_, |
| 3495 formal_parameters.scope, arrow_kind); | 3509 formal_parameters.scope, arrow_kind); |
| 3496 | 3510 |
| 3497 function_state.SkipMaterializedLiterals( | 3511 function_state.SkipMaterializedLiterals( |
| 3498 formal_parameters.materialized_literals_count); | 3512 formal_parameters.materialized_literals_count); |
| 3499 | 3513 |
| 3500 impl()->ReindexLiterals(formal_parameters); | 3514 impl()->ReindexLiterals(formal_parameters); |
| 3501 | 3515 |
| 3502 Expect(Token::ARROW, CHECK_OK); | 3516 Expect(Token::ARROW, CHECK_OK); |
| 3503 | 3517 |
| 3504 if (peek() == Token::LBRACE) { | 3518 if (peek() == Token::LBRACE) { |
| 3505 // Multiple statement body | 3519 // Multiple statement body |
| 3506 Consume(Token::LBRACE); | 3520 Consume(Token::LBRACE); |
| 3507 DCHECK_EQ(scope(), formal_parameters.scope); | 3521 DCHECK_EQ(scope(), formal_parameters.scope); |
| 3508 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 3522 bool is_lazily_parsed = (mode() == PARSE_LAZILY && |
| 3509 formal_parameters.scope->AllowsLazyParsing()); | 3523 formal_parameters.scope->AllowsLazyParsing()); |
| 3510 if (is_lazily_parsed) { | 3524 if (is_lazily_parsed) { |
| 3511 body = impl()->NewStatementList(0); | 3525 Scanner::BookmarkScope bookmark(scanner()); |
| 3512 impl()->SkipLazyFunctionBody(&materialized_literal_count, | 3526 bool may_abort = bookmark.Set(); |
| 3513 &expected_property_count, CHECK_OK); | 3527 LazyParsingResult result = impl()->SkipLazyFunctionBody( |
| 3528 &materialized_literal_count, &expected_property_count, may_abort, |
| 3529 CHECK_OK); |
| 3530 |
| 3514 if (formal_parameters.materialized_literals_count > 0) { | 3531 if (formal_parameters.materialized_literals_count > 0) { |
| 3515 materialized_literal_count += | 3532 materialized_literal_count += |
| 3516 formal_parameters.materialized_literals_count; | 3533 formal_parameters.materialized_literals_count; |
| 3517 } | 3534 } |
| 3518 } else { | 3535 |
| 3536 if (result == kLazyParsingAborted) { |
| 3537 bookmark.Reset(); |
| 3538 // Trigger eager (re-)parsing, just below this block. |
| 3539 is_lazily_parsed = false; |
| 3540 |
| 3541 // This is probably an initialization function. Inform the compiler it |
| 3542 // should also eager-compile this function, and that we expect it to |
| 3543 // be used once. |
| 3544 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
| 3545 should_be_used_once_hint = true; |
| 3546 } |
| 3547 } |
| 3548 if (!is_lazily_parsed) { |
| 3519 body = impl()->ParseEagerFunctionBody( | 3549 body = impl()->ParseEagerFunctionBody( |
| 3520 impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, | 3550 impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, |
| 3521 arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); | 3551 arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); |
| 3522 materialized_literal_count = | 3552 materialized_literal_count = |
| 3523 function_state.materialized_literal_count(); | 3553 function_state.materialized_literal_count(); |
| 3524 expected_property_count = function_state.expected_property_count(); | 3554 expected_property_count = function_state.expected_property_count(); |
| 3525 } | 3555 } |
| 3526 } else { | 3556 } else { |
| 3527 // Single-expression body | 3557 // Single-expression body |
| 3528 int pos = position(); | 3558 int pos = position(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3569 } | 3599 } |
| 3570 impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); | 3600 impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); |
| 3571 | 3601 |
| 3572 impl()->RewriteDestructuringAssignments(); | 3602 impl()->RewriteDestructuringAssignments(); |
| 3573 } | 3603 } |
| 3574 | 3604 |
| 3575 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( | 3605 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( |
| 3576 impl()->EmptyIdentifierString(), formal_parameters.scope, body, | 3606 impl()->EmptyIdentifierString(), formal_parameters.scope, body, |
| 3577 materialized_literal_count, expected_property_count, num_parameters, | 3607 materialized_literal_count, expected_property_count, num_parameters, |
| 3578 FunctionLiteral::kNoDuplicateParameters, | 3608 FunctionLiteral::kNoDuplicateParameters, |
| 3579 FunctionLiteral::kAnonymousExpression, | 3609 FunctionLiteral::kAnonymousExpression, eager_compile_hint, arrow_kind, |
| 3580 FunctionLiteral::kShouldLazyCompile, arrow_kind, | |
| 3581 formal_parameters.scope->start_position()); | 3610 formal_parameters.scope->start_position()); |
| 3582 | 3611 |
| 3583 function_literal->set_function_token_position( | 3612 function_literal->set_function_token_position( |
| 3584 formal_parameters.scope->start_position()); | 3613 formal_parameters.scope->start_position()); |
| 3614 if (should_be_used_once_hint) { |
| 3615 function_literal->set_should_be_used_once_hint(); |
| 3616 } |
| 3585 | 3617 |
| 3586 if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal); | 3618 if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal); |
| 3587 | 3619 |
| 3588 return function_literal; | 3620 return function_literal; |
| 3589 } | 3621 } |
| 3590 | 3622 |
| 3591 template <typename Impl> | 3623 template <typename Impl> |
| 3592 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( | 3624 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
| 3593 ExpressionT tag, int start, bool* ok) { | 3625 ExpressionT tag, int start, bool* ok) { |
| 3594 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal | 3626 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3726 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, | 3758 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, |
| 3727 int begin, int end) { | 3759 int begin, int end) { |
| 3728 if (!IsValidPattern(expression) && !expression->IsAssignment() && | 3760 if (!IsValidPattern(expression) && !expression->IsAssignment() && |
| 3729 !IsValidReferenceExpression(expression)) { | 3761 !IsValidReferenceExpression(expression)) { |
| 3730 classifier()->RecordAssignmentPatternError( | 3762 classifier()->RecordAssignmentPatternError( |
| 3731 Scanner::Location(begin, end), | 3763 Scanner::Location(begin, end), |
| 3732 MessageTemplate::kInvalidDestructuringTarget); | 3764 MessageTemplate::kInvalidDestructuringTarget); |
| 3733 } | 3765 } |
| 3734 } | 3766 } |
| 3735 | 3767 |
| 3736 | |
| 3737 #undef CHECK_OK | 3768 #undef CHECK_OK |
| 3738 #undef CHECK_OK_CUSTOM | 3769 #undef CHECK_OK_CUSTOM |
| 3739 | 3770 |
| 3740 template <typename Impl> | 3771 template <typename Impl> |
| 3741 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( | 3772 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( |
| 3742 Token::Value property, PropertyKind type, MethodKind method_type, | 3773 Token::Value property, PropertyKind type, MethodKind method_type, |
| 3743 bool* ok) { | 3774 bool* ok) { |
| 3744 DCHECK(!IsStaticMethod(method_type)); | 3775 DCHECK(!IsStaticMethod(method_type)); |
| 3745 DCHECK(!IsSpecialMethod(method_type) || | 3776 DCHECK(!IsSpecialMethod(method_type) || |
| 3746 type == PropertyKind::kMethodProperty); | 3777 type == PropertyKind::kMethodProperty); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3792 has_seen_constructor_ = true; | 3823 has_seen_constructor_ = true; |
| 3793 return; | 3824 return; |
| 3794 } | 3825 } |
| 3795 } | 3826 } |
| 3796 | 3827 |
| 3797 | 3828 |
| 3798 } // namespace internal | 3829 } // namespace internal |
| 3799 } // namespace v8 | 3830 } // namespace v8 |
| 3800 | 3831 |
| 3801 #endif // V8_PARSING_PARSER_BASE_H | 3832 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |