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/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 MessageTemplate::Template message, bool* ok) { | 805 MessageTemplate::Template message, bool* ok) { |
806 Scanner::Location octal = scanner()->octal_position(); | 806 Scanner::Location octal = scanner()->octal_position(); |
807 if (octal.IsValid() && beg_pos <= octal.beg_pos && | 807 if (octal.IsValid() && beg_pos <= octal.beg_pos && |
808 octal.end_pos <= end_pos) { | 808 octal.end_pos <= end_pos) { |
809 impl()->ReportMessageAt(octal, message); | 809 impl()->ReportMessageAt(octal, message); |
810 scanner()->clear_octal_position(); | 810 scanner()->clear_octal_position(); |
811 *ok = false; | 811 *ok = false; |
812 } | 812 } |
813 } | 813 } |
814 // for now, this check just collects statistics. | 814 // for now, this check just collects statistics. |
815 void CheckDecimalLiteralWithLeadingZero(int* use_counts, int beg_pos, | 815 void CheckDecimalLiteralWithLeadingZero(int beg_pos, int end_pos) { |
816 int end_pos) { | |
817 Scanner::Location token_location = | 816 Scanner::Location token_location = |
818 scanner()->decimal_with_leading_zero_position(); | 817 scanner()->decimal_with_leading_zero_position(); |
819 if (token_location.IsValid() && beg_pos <= token_location.beg_pos && | 818 if (token_location.IsValid() && beg_pos <= token_location.beg_pos && |
820 token_location.end_pos <= end_pos) { | 819 token_location.end_pos <= end_pos) { |
821 scanner()->clear_decimal_with_leading_zero_position(); | 820 scanner()->clear_decimal_with_leading_zero_position(); |
822 if (use_counts != nullptr) | 821 impl()->CountUsage(v8::Isolate::kDecimalWithLeadingZeroInStrictMode); |
823 ++use_counts[v8::Isolate::kDecimalWithLeadingZeroInStrictMode]; | |
824 } | 822 } |
825 } | 823 } |
826 | 824 |
827 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { | 825 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
828 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, | 826 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, |
829 ok); | 827 ok); |
830 } | 828 } |
831 | 829 |
832 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { | 830 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
833 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, | 831 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 LazyParsingResult ParseStatementList(StatementListT body, int end_token, | 1162 LazyParsingResult ParseStatementList(StatementListT body, int end_token, |
1165 bool may_abort, bool* ok); | 1163 bool may_abort, bool* ok); |
1166 StatementT ParseStatementListItem(bool* ok); | 1164 StatementT ParseStatementListItem(bool* ok); |
1167 StatementT ParseStatement(ZoneList<const AstRawString*>* labels, | 1165 StatementT ParseStatement(ZoneList<const AstRawString*>* labels, |
1168 AllowLabelledFunctionStatement allow_function, | 1166 AllowLabelledFunctionStatement allow_function, |
1169 bool* ok); | 1167 bool* ok); |
1170 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels, | 1168 StatementT ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels, |
1171 bool* ok); | 1169 bool* ok); |
1172 BlockT ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); | 1170 BlockT ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); |
1173 | 1171 |
| 1172 // Parse a SubStatement in strict mode, or with an extra block scope in |
| 1173 // sloppy mode to handle |
| 1174 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses |
| 1175 // The legacy parameter indicates whether function declarations are |
| 1176 // banned by the ES2015 specification in this location, and they are being |
| 1177 // permitted here to match previous V8 behavior. |
| 1178 StatementT ParseScopedStatement(ZoneList<const AstRawString*>* labels, |
| 1179 bool legacy, bool* ok); |
| 1180 |
| 1181 StatementT ParseVariableStatement(VariableDeclarationContext var_context, |
| 1182 ZoneList<const AstRawString*>* names, |
| 1183 bool* ok); |
| 1184 |
| 1185 // Magical syntax support. |
| 1186 ExpressionT ParseV8Intrinsic(bool* ok); |
| 1187 |
| 1188 StatementT ParseDebuggerStatement(bool* ok); |
| 1189 |
1174 bool IsNextLetKeyword(); | 1190 bool IsNextLetKeyword(); |
1175 bool IsTrivialExpression(); | 1191 bool IsTrivialExpression(); |
1176 | 1192 |
1177 // Checks if the expression is a valid reference expression (e.g., on the | 1193 // Checks if the expression is a valid reference expression (e.g., on the |
1178 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1194 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1179 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1195 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1180 ExpressionT CheckAndRewriteReferenceExpression( | 1196 ExpressionT CheckAndRewriteReferenceExpression( |
1181 ExpressionT expression, int beg_pos, int end_pos, | 1197 ExpressionT expression, int beg_pos, int end_pos, |
1182 MessageTemplate::Template message, bool* ok); | 1198 MessageTemplate::Template message, bool* ok); |
1183 ExpressionT CheckAndRewriteReferenceExpression( | 1199 ExpressionT CheckAndRewriteReferenceExpression( |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1705 } | 1721 } |
1706 | 1722 |
1707 case Token::TEMPLATE_SPAN: | 1723 case Token::TEMPLATE_SPAN: |
1708 case Token::TEMPLATE_TAIL: | 1724 case Token::TEMPLATE_TAIL: |
1709 BindingPatternUnexpectedToken(); | 1725 BindingPatternUnexpectedToken(); |
1710 return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, ok); | 1726 return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, ok); |
1711 | 1727 |
1712 case Token::MOD: | 1728 case Token::MOD: |
1713 if (allow_natives() || extension_ != NULL) { | 1729 if (allow_natives() || extension_ != NULL) { |
1714 BindingPatternUnexpectedToken(); | 1730 BindingPatternUnexpectedToken(); |
1715 return impl()->ParseV8Intrinsic(ok); | 1731 return ParseV8Intrinsic(ok); |
1716 } | 1732 } |
1717 break; | 1733 break; |
1718 | 1734 |
1719 case Token::DO: | 1735 case Token::DO: |
1720 if (allow_harmony_do_expressions()) { | 1736 if (allow_harmony_do_expressions()) { |
1721 BindingPatternUnexpectedToken(); | 1737 BindingPatternUnexpectedToken(); |
1722 return impl()->ParseDoExpression(ok); | 1738 return impl()->ParseDoExpression(ok); |
1723 } | 1739 } |
1724 break; | 1740 break; |
1725 | 1741 |
(...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3436 VariableDeclarationContext var_context, | 3452 VariableDeclarationContext var_context, |
3437 DeclarationParsingResult* parsing_result, | 3453 DeclarationParsingResult* parsing_result, |
3438 ZoneList<const AstRawString*>* names, bool* ok) { | 3454 ZoneList<const AstRawString*>* names, bool* ok) { |
3439 // VariableDeclarations :: | 3455 // VariableDeclarations :: |
3440 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] | 3456 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] |
3441 // | 3457 // |
3442 // ES6: | 3458 // ES6: |
3443 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable | 3459 // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable |
3444 // declaration syntax. | 3460 // declaration syntax. |
3445 | 3461 |
3446 DeclarationParsingResult temp_result; | 3462 DCHECK_NOT_NULL(parsing_result); |
3447 if (parsing_result == nullptr) { | |
3448 parsing_result = &temp_result; | |
3449 } | |
3450 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | 3463 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; |
3451 parsing_result->descriptor.declaration_pos = peek_position(); | 3464 parsing_result->descriptor.declaration_pos = peek_position(); |
3452 parsing_result->descriptor.initialization_pos = peek_position(); | 3465 parsing_result->descriptor.initialization_pos = peek_position(); |
3453 | 3466 |
3454 BlockT init_block = impl()->NullBlock(); | 3467 BlockT init_block = impl()->NullBlock(); |
3455 if (var_context != kForStatement) { | 3468 if (var_context != kForStatement) { |
3456 init_block = impl()->NewBlock(nullptr, 1, true, | 3469 init_block = impl()->NewBlock(nullptr, 1, true, |
3457 parsing_result->descriptor.declaration_pos); | 3470 parsing_result->descriptor.declaration_pos); |
3458 } | 3471 } |
3459 | 3472 |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3928 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, | 3941 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, |
3929 int begin, int end) { | 3942 int begin, int end) { |
3930 if (!IsValidPattern(expression) && !expression->IsAssignment() && | 3943 if (!IsValidPattern(expression) && !expression->IsAssignment() && |
3931 !IsValidReferenceExpression(expression)) { | 3944 !IsValidReferenceExpression(expression)) { |
3932 classifier()->RecordAssignmentPatternError( | 3945 classifier()->RecordAssignmentPatternError( |
3933 Scanner::Location(begin, end), | 3946 Scanner::Location(begin, end), |
3934 MessageTemplate::kInvalidDestructuringTarget); | 3947 MessageTemplate::kInvalidDestructuringTarget); |
3935 } | 3948 } |
3936 } | 3949 } |
3937 | 3950 |
| 3951 template <typename Impl> |
| 3952 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic( |
| 3953 bool* ok) { |
| 3954 // CallRuntime :: |
| 3955 // '%' Identifier Arguments |
| 3956 |
| 3957 int pos = peek_position(); |
| 3958 Expect(Token::MOD, CHECK_OK); |
| 3959 // Allow "eval" or "arguments" for backward compatibility. |
| 3960 IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 3961 Scanner::Location spread_pos; |
| 3962 ExpressionClassifier classifier(this); |
| 3963 ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK); |
| 3964 |
| 3965 DCHECK(!spread_pos.IsValid()); |
| 3966 |
| 3967 return impl()->NewV8Intrinsic(name, args, pos, ok); |
| 3968 } |
| 3969 |
3938 // Redefinition of CHECK_OK for parsing statements. | 3970 // Redefinition of CHECK_OK for parsing statements. |
3939 #undef CHECK_OK | 3971 #undef CHECK_OK |
3940 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement) | 3972 #define CHECK_OK CHECK_OK_CUSTOM(NullStatement) |
3941 | 3973 |
3942 template <typename Impl> | 3974 template <typename Impl> |
3943 typename ParserBase<Impl>::LazyParsingResult | 3975 typename ParserBase<Impl>::LazyParsingResult |
3944 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token, | 3976 ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token, |
3945 bool may_abort, bool* ok) { | 3977 bool may_abort, bool* ok) { |
3946 // StatementList :: | 3978 // StatementList :: |
3947 // (StatementListItem)* <end_token> | 3979 // (StatementListItem)* <end_token> |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4055 // LetOrConst BindingList[?In, ?Yield] ; | 4087 // LetOrConst BindingList[?In, ?Yield] ; |
4056 | 4088 |
4057 switch (peek()) { | 4089 switch (peek()) { |
4058 case Token::FUNCTION: | 4090 case Token::FUNCTION: |
4059 return impl()->ParseHoistableDeclaration(nullptr, false, ok); | 4091 return impl()->ParseHoistableDeclaration(nullptr, false, ok); |
4060 case Token::CLASS: | 4092 case Token::CLASS: |
4061 Consume(Token::CLASS); | 4093 Consume(Token::CLASS); |
4062 return impl()->ParseClassDeclaration(nullptr, false, ok); | 4094 return impl()->ParseClassDeclaration(nullptr, false, ok); |
4063 case Token::VAR: | 4095 case Token::VAR: |
4064 case Token::CONST: | 4096 case Token::CONST: |
4065 return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); | 4097 return ParseVariableStatement(kStatementListItem, nullptr, ok); |
4066 case Token::LET: | 4098 case Token::LET: |
4067 if (IsNextLetKeyword()) { | 4099 if (IsNextLetKeyword()) { |
4068 return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); | 4100 return ParseVariableStatement(kStatementListItem, nullptr, ok); |
4069 } | 4101 } |
4070 break; | 4102 break; |
4071 case Token::ASYNC: | 4103 case Token::ASYNC: |
4072 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && | 4104 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
4073 !scanner()->HasAnyLineTerminatorAfterNext()) { | 4105 !scanner()->HasAnyLineTerminatorAfterNext()) { |
4074 Consume(Token::ASYNC); | 4106 Consume(Token::ASYNC); |
4075 return impl()->ParseAsyncFunctionDeclaration(nullptr, false, ok); | 4107 return impl()->ParseAsyncFunctionDeclaration(nullptr, false, ok); |
4076 } | 4108 } |
4077 /* falls through */ | 4109 /* falls through */ |
4078 default: | 4110 default: |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4152 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses | 4184 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses |
4153 // are handled by calling ParseScopedStatement rather than | 4185 // are handled by calling ParseScopedStatement rather than |
4154 // ParseStatement directly. | 4186 // ParseStatement directly. |
4155 impl()->ReportMessageAt(scanner()->peek_location(), | 4187 impl()->ReportMessageAt(scanner()->peek_location(), |
4156 is_strict(language_mode()) | 4188 is_strict(language_mode()) |
4157 ? MessageTemplate::kStrictFunction | 4189 ? MessageTemplate::kStrictFunction |
4158 : MessageTemplate::kSloppyFunction); | 4190 : MessageTemplate::kSloppyFunction); |
4159 *ok = false; | 4191 *ok = false; |
4160 return impl()->NullStatement(); | 4192 return impl()->NullStatement(); |
4161 case Token::DEBUGGER: | 4193 case Token::DEBUGGER: |
4162 return impl()->ParseDebuggerStatement(ok); | 4194 return ParseDebuggerStatement(ok); |
4163 case Token::VAR: | 4195 case Token::VAR: |
4164 return impl()->ParseVariableStatement(kStatement, nullptr, ok); | 4196 return ParseVariableStatement(kStatement, nullptr, ok); |
4165 default: | 4197 default: |
4166 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, | 4198 return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, |
4167 ok); | 4199 ok); |
4168 } | 4200 } |
4169 } | 4201 } |
4170 | 4202 |
4171 // This method parses a subset of statements (break, continue, return, throw, | 4203 // This method parses a subset of statements (break, continue, return, throw, |
4172 // try) which are to be grouped because they all require their labeles to be | 4204 // try) which are to be grouped because they all require their labeles to be |
4173 // preserved in an enclosing block. | 4205 // preserved in an enclosing block. |
4174 template <typename Impl> | 4206 template <typename Impl> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4215 } | 4247 } |
4216 } | 4248 } |
4217 | 4249 |
4218 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); | 4250 Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullBlock)); |
4219 block_state.set_end_position(scanner()->location().end_pos); | 4251 block_state.set_end_position(scanner()->location().end_pos); |
4220 body->set_scope(block_state.FinalizedBlockScope()); | 4252 body->set_scope(block_state.FinalizedBlockScope()); |
4221 } | 4253 } |
4222 return body; | 4254 return body; |
4223 } | 4255 } |
4224 | 4256 |
| 4257 template <typename Impl> |
| 4258 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( |
| 4259 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { |
| 4260 if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
| 4261 (legacy && allow_harmony_restrictive_declarations())) { |
| 4262 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); |
| 4263 } else { |
| 4264 if (legacy) { |
| 4265 impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); |
| 4266 } |
| 4267 // Make a block around the statement for a lexical binding |
| 4268 // is introduced by a FunctionDeclaration. |
| 4269 BlockState block_state(&scope_state_); |
| 4270 block_state.set_start_position(scanner()->location().beg_pos); |
| 4271 BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); |
| 4272 StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); |
| 4273 block->statements()->Add(body, zone()); |
| 4274 block_state.set_end_position(scanner()->location().end_pos); |
| 4275 block->set_scope(block_state.FinalizedBlockScope()); |
| 4276 return block; |
| 4277 } |
| 4278 } |
| 4279 |
| 4280 template <typename Impl> |
| 4281 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement( |
| 4282 VariableDeclarationContext var_context, |
| 4283 ZoneList<const AstRawString*>* names, bool* ok) { |
| 4284 // VariableStatement :: |
| 4285 // VariableDeclarations ';' |
| 4286 |
| 4287 // The scope of a var declared variable anywhere inside a function |
| 4288 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
| 4289 // transform a source-level var declaration into a (Function) Scope |
| 4290 // declaration, and rewrite the source-level initialization into an assignment |
| 4291 // statement. We use a block to collect multiple assignments. |
| 4292 // |
| 4293 // We mark the block as initializer block because we don't want the |
| 4294 // rewriter to add a '.result' assignment to such a block (to get compliant |
| 4295 // behavior for code such as print(eval('var x = 7')), and for cosmetic |
| 4296 // reasons when pretty-printing. Also, unless an assignment (initialization) |
| 4297 // is inside an initializer block, it is ignored. |
| 4298 |
| 4299 DeclarationParsingResult parsing_result; |
| 4300 StatementT result = |
| 4301 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK); |
| 4302 ExpectSemicolon(CHECK_OK); |
| 4303 return result; |
| 4304 } |
| 4305 |
| 4306 template <typename Impl> |
| 4307 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDebuggerStatement( |
| 4308 bool* ok) { |
| 4309 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 4310 // contexts this is used as a statement which invokes the debugger as i a |
| 4311 // break point is present. |
| 4312 // DebuggerStatement :: |
| 4313 // 'debugger' ';' |
| 4314 |
| 4315 int pos = peek_position(); |
| 4316 Expect(Token::DEBUGGER, CHECK_OK); |
| 4317 ExpectSemicolon(CHECK_OK); |
| 4318 return factory()->NewDebuggerStatement(pos); |
| 4319 } |
| 4320 |
4225 #undef CHECK_OK | 4321 #undef CHECK_OK |
4226 #undef CHECK_OK_CUSTOM | 4322 #undef CHECK_OK_CUSTOM |
4227 | 4323 |
4228 template <typename Impl> | 4324 template <typename Impl> |
4229 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 4325 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
4230 Token::Value property) { | 4326 Token::Value property) { |
4231 if (property == Token::SMI || property == Token::NUMBER) return; | 4327 if (property == Token::SMI || property == Token::NUMBER) return; |
4232 | 4328 |
4233 if (IsProto()) { | 4329 if (IsProto()) { |
4234 if (has_seen_proto_) { | 4330 if (has_seen_proto_) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4273 has_seen_constructor_ = true; | 4369 has_seen_constructor_ = true; |
4274 return; | 4370 return; |
4275 } | 4371 } |
4276 } | 4372 } |
4277 | 4373 |
4278 | 4374 |
4279 } // namespace internal | 4375 } // namespace internal |
4280 } // namespace v8 | 4376 } // namespace v8 |
4281 | 4377 |
4282 #endif // V8_PARSING_PARSER_BASE_H | 4378 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |