Chromium Code Reviews| Index: src/parsing/parser-base.h |
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
| index 4774e04b2481ce6925585ab53251852fe2398849..bcd5941c0a8f67b45f01745c61f7ede6b272e0f9 100644 |
| --- a/src/parsing/parser-base.h |
| +++ b/src/parsing/parser-base.h |
| @@ -1077,6 +1077,8 @@ class ParserBase : public Traits { |
| ExpressionT ParseAssignmentExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| bool* ok); |
| + ExpressionT ParseTrivialAssignmentExpression(ExpressionClassifier* classifier, |
| + bool* ok); |
| ExpressionT ParseYieldExpression(bool accept_IN, |
| ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier, |
| @@ -1550,8 +1552,6 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| case Token::NULL_LITERAL: |
| case Token::TRUE_LITERAL: |
| case Token::FALSE_LITERAL: |
| - BindingPatternUnexpectedToken(classifier); |
| - return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory()); |
| case Token::SMI: |
| case Token::NUMBER: |
| BindingPatternUnexpectedToken(classifier); |
| @@ -2277,6 +2277,11 @@ typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| bool* ok) { |
| + // Try to parse a simple sub-grammar and early-out if successful. |
| + typename ParserBase<Traits>::ExpressionT trivial_result = |
| + this->ParseTrivialAssignmentExpression(classifier, ok); |
| + if (!Traits::IsEmptyExpression(trivial_result)) return trivial_result; |
|
marja
2016/07/29 07:56:04
Ah right, since we have 2 expression types, this c
vogelheim
2016/08/09 11:26:08
Done. (2nd version)
|
| + |
| // AssignmentExpression :: |
| // ConditionalExpression |
| // ArrowFunction |
| @@ -2465,6 +2470,90 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| +ParserBase<Traits>::ParseTrivialAssignmentExpression( |
| + ExpressionClassifier* classifier, bool* ok) { |
| + // Parser shortcut: The following scope is a micro-optimization to reduce |
|
adamk
2016/07/28 17:51:55
This can be rewritten now that it's in its own fun
vogelheim
2016/08/09 11:26:08
Done.
|
| + // parsing time. It should be functionally neutral and deliver either nullptr |
| + // or the same result as the canonical ParseAssignmentExpression. |
| + // When we encounter |
| + // [SMI|NUMBER|{NULL,TRUE,FALSE}_LITERAL|THIS|STRING|IDENTIFIER] |
| + // followed by |
| + // [COMMA|RPAREN|RBRACK|SEMICOLON] |
| + // then this will result in a single AST node. Instead of parsing this |
| + // 'properly' (a call chain 11-levels deep), we will just generate the |
| + // appropriate AST nodes right here. |
| + Token::Value peek_token = peek(); |
| + bool is_number = peek_token == Token::SMI || peek_token == Token::NUMBER; |
| + bool is_literal = peek_token == Token::NULL_LITERAL || |
| + peek_token == Token::TRUE_LITERAL || |
| + peek_token == Token::FALSE_LITERAL; |
| + bool is_string = peek_token == Token::STRING; |
| + bool is_identifier = peek_token == Token::IDENTIFIER; |
| + bool is_this = peek_token == Token::THIS; |
| + if (is_number || is_literal || is_string || is_identifier || is_this) { |
| + // PeekAhead() is expensive & may not always be called, so we only call it |
| + // after checking peek(). |
| + Token::Value peek_ahead = PeekAhead(); |
| + if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN || |
| + peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK) { |
| + Scanner::Location pos = scanner()->peek_location(); |
| + if (is_string) { |
| + FuncNameInferrer::State fni_state(fni_); |
| + classifier->RecordBindingPatternError( |
| + pos, MessageTemplate::kUnexpectedTokenString); |
| + Consume(Token::STRING); |
| + return this->ExpressionFromString(pos.beg_pos, scanner(), factory()); |
| + } else if (is_this) { |
| + classifier->RecordBindingPatternError( |
| + pos, MessageTemplate::kUnexpectedToken, Token::Name(Token::THIS)); |
| + Consume(Token::THIS); |
| + return this->ThisExpression(scope(), factory(), pos.beg_pos); |
| + } else if (is_number) { |
| + classifier->RecordBindingPatternError( |
| + pos, MessageTemplate::kUnexpectedTokenNumber); |
| + Consume(peek_token); |
| + return this->ExpressionFromLiteral(peek_token, pos.beg_pos, scanner(), |
| + factory()); |
| + } else if (is_literal) { |
| + classifier->RecordBindingPatternError( |
| + pos, MessageTemplate::kUnexpectedToken, Token::Name(peek_token)); |
| + Consume(peek_token); |
| + return this->ExpressionFromLiteral(peek_token, pos.beg_pos, scanner(), |
| + factory()); |
| + } else if (is_identifier) { |
| + FuncNameInferrer::State fni_state(fni_); |
| + ExpressionClassifier arrow_formals_classifier( |
| + this, classifier->duplicate_finder()); |
| + IdentifierT name = |
| + ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK); |
| + typename ParserBase<Traits>::ExpressionT shortcut_result = |
| + this->ExpressionFromIdentifier(name, pos.beg_pos, pos.end_pos, |
| + scope(), factory()); |
| + if (this->IsAssignableIdentifier(shortcut_result)) { |
| + arrow_formals_classifier.ForgiveAssignmentPatternError(); |
| + } |
| + classifier->Accumulate( |
| + &arrow_formals_classifier, |
| + ExpressionClassifier::StandardProductions | |
| + ExpressionClassifier::FormalParametersProductions | |
| + ExpressionClassifier::CoverInitializedNameProduction | |
| + ExpressionClassifier::AsyncArrowFormalParametersProduction | |
| + ExpressionClassifier::AsyncBindingPatternProduction, |
| + false); |
| + DCHECK(!Token::IsAssignmentOp(peek_ahead)); |
| + classifier->MergeNonPatterns(&arrow_formals_classifier); |
| + return shortcut_result; |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } |
| + } |
| + // No applicable shortcut found: Proceed w/ regular parsing. |
| + return this->EmptyExpression(); |
| +} |
| + |
| +template <class Traits> |
| +typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseYieldExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| bool* ok) { |