| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <cmath> | 5 #include <cmath> |
| 6 | 6 |
| 7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
| 8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
| 9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 if (allow_harmony_restrictive_declarations()) { | 193 if (allow_harmony_restrictive_declarations()) { |
| 194 ReportMessageAt(scanner()->location(), | 194 ReportMessageAt(scanner()->location(), |
| 195 MessageTemplate::kGeneratorInLegacyContext); | 195 MessageTemplate::kGeneratorInLegacyContext); |
| 196 *ok = false; | 196 *ok = false; |
| 197 return Statement::Default(); | 197 return Statement::Default(); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); | 200 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); |
| 201 } | 201 } |
| 202 | 202 |
| 203 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( | |
| 204 ZoneList<const AstRawString*>* names, | |
| 205 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
| 206 // ExpressionStatement | LabelledStatement :: | |
| 207 // Expression ';' | |
| 208 // Identifier ':' Statement | |
| 209 | |
| 210 switch (peek()) { | |
| 211 case Token::FUNCTION: | |
| 212 case Token::LBRACE: | |
| 213 UNREACHABLE(); // Always handled by the callers. | |
| 214 case Token::CLASS: | |
| 215 ReportUnexpectedToken(Next()); | |
| 216 *ok = false; | |
| 217 return Statement::Default(); | |
| 218 | |
| 219 default: | |
| 220 break; | |
| 221 } | |
| 222 | |
| 223 bool starts_with_identifier = peek_any_identifier(); | |
| 224 ExpressionClassifier classifier(this); | |
| 225 Expression expr = ParseExpressionCoverGrammar(true, CHECK_OK); | |
| 226 ValidateExpression(CHECK_OK); | |
| 227 | |
| 228 // Even if the expression starts with an identifier, it is not necessarily an | |
| 229 // identifier. For example, "foo + bar" starts with an identifier but is not | |
| 230 // an identifier. | |
| 231 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { | |
| 232 // Expression is a single identifier, and not, e.g., a parenthesized | |
| 233 // identifier. | |
| 234 DCHECK(!expr.AsIdentifier().IsEnum()); | |
| 235 DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait()); | |
| 236 DCHECK(is_sloppy(language_mode()) || | |
| 237 !IsFutureStrictReserved(expr.AsIdentifier())); | |
| 238 Consume(Token::COLON); | |
| 239 // ES#sec-labelled-function-declarations Labelled Function Declarations | |
| 240 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | |
| 241 if (allow_function == kAllowLabelledFunctionStatement) { | |
| 242 return ParseFunctionDeclaration(ok); | |
| 243 } else { | |
| 244 return ParseScopedStatement(names, true, ok); | |
| 245 } | |
| 246 } | |
| 247 Statement statement = | |
| 248 ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); | |
| 249 return statement.IsJumpStatement() ? Statement::Default() : statement; | |
| 250 // Preparsing is disabled for extensions (because the extension details | |
| 251 // aren't passed to lazily compiled functions), so we don't | |
| 252 // accept "native function" in the preparser. | |
| 253 } | |
| 254 // Parsed expression statement. | |
| 255 ExpectSemicolon(CHECK_OK); | |
| 256 return Statement::ExpressionStatement(expr); | |
| 257 } | |
| 258 | |
| 259 PreParser::Statement PreParser::ParseIfStatement( | |
| 260 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 261 // IfStatement :: | |
| 262 // 'if' '(' Expression ')' Statement ('else' Statement)? | |
| 263 | |
| 264 Expect(Token::IF, CHECK_OK); | |
| 265 Expect(Token::LPAREN, CHECK_OK); | |
| 266 ParseExpression(true, CHECK_OK); | |
| 267 Expect(Token::RPAREN, CHECK_OK); | |
| 268 Statement stat = ParseScopedStatement(labels, false, CHECK_OK); | |
| 269 if (peek() == Token::ELSE) { | |
| 270 Next(); | |
| 271 Statement else_stat = ParseScopedStatement(labels, false, CHECK_OK); | |
| 272 stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ? | |
| 273 Statement::Jump() : Statement::Default(); | |
| 274 } else { | |
| 275 stat = Statement::Default(); | |
| 276 } | |
| 277 return stat; | |
| 278 } | |
| 279 | |
| 280 | |
| 281 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { | |
| 282 // ContinueStatement :: | |
| 283 // 'continue' [no line terminator] Identifier? ';' | |
| 284 | |
| 285 Expect(Token::CONTINUE, CHECK_OK); | |
| 286 Token::Value tok = peek(); | |
| 287 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 288 tok != Token::SEMICOLON && | |
| 289 tok != Token::RBRACE && | |
| 290 tok != Token::EOS) { | |
| 291 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 292 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 293 } | |
| 294 ExpectSemicolon(CHECK_OK); | |
| 295 return Statement::Jump(); | |
| 296 } | |
| 297 | |
| 298 PreParser::Statement PreParser::ParseBreakStatement( | |
| 299 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 300 // BreakStatement :: | |
| 301 // 'break' [no line terminator] Identifier? ';' | |
| 302 | |
| 303 Expect(Token::BREAK, CHECK_OK); | |
| 304 Token::Value tok = peek(); | |
| 305 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 306 tok != Token::SEMICOLON && | |
| 307 tok != Token::RBRACE && | |
| 308 tok != Token::EOS) { | |
| 309 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 310 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 311 } | |
| 312 ExpectSemicolon(CHECK_OK); | |
| 313 return Statement::Jump(); | |
| 314 } | |
| 315 | |
| 316 | |
| 317 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | |
| 318 // ReturnStatement :: | |
| 319 // 'return' [no line terminator] Expression? ';' | |
| 320 | |
| 321 // Consume the return token. It is necessary to do before | |
| 322 // reporting any errors on it, because of the way errors are | |
| 323 // reported (underlining). | |
| 324 Expect(Token::RETURN, CHECK_OK); | |
| 325 | |
| 326 // An ECMAScript program is considered syntactically incorrect if it | |
| 327 // contains a return statement that is not within the body of a | |
| 328 // function. See ECMA-262, section 12.9, page 67. | |
| 329 // This is not handled during preparsing. | |
| 330 | |
| 331 Token::Value tok = peek(); | |
| 332 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 333 tok != Token::SEMICOLON && | |
| 334 tok != Token::RBRACE && | |
| 335 tok != Token::EOS) { | |
| 336 // Because of the return code rewriting that happens in case of a subclass | |
| 337 // constructor we don't want to accept tail calls, therefore we don't set | |
| 338 // ReturnExprScope to kInsideValidReturnStatement here. | |
| 339 ReturnExprContext return_expr_context = | |
| 340 IsSubclassConstructor(function_state_->kind()) | |
| 341 ? function_state_->return_expr_context() | |
| 342 : ReturnExprContext::kInsideValidReturnStatement; | |
| 343 | |
| 344 ReturnExprScope maybe_allow_tail_calls(function_state_, | |
| 345 return_expr_context); | |
| 346 ParseExpression(true, CHECK_OK); | |
| 347 } | |
| 348 ExpectSemicolon(CHECK_OK); | |
| 349 return Statement::Jump(); | |
| 350 } | |
| 351 | |
| 352 PreParser::Statement PreParser::ParseWithStatement( | |
| 353 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 354 // WithStatement :: | |
| 355 // 'with' '(' Expression ')' Statement | |
| 356 Expect(Token::WITH, CHECK_OK); | |
| 357 if (is_strict(language_mode())) { | |
| 358 ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith); | |
| 359 *ok = false; | |
| 360 return Statement::Default(); | |
| 361 } | |
| 362 Expect(Token::LPAREN, CHECK_OK); | |
| 363 ParseExpression(true, CHECK_OK); | |
| 364 Expect(Token::RPAREN, CHECK_OK); | |
| 365 | |
| 366 Scope* with_scope = NewScope(WITH_SCOPE); | |
| 367 BlockState block_state(&scope_state_, with_scope); | |
| 368 ParseScopedStatement(labels, true, CHECK_OK); | |
| 369 return Statement::Default(); | |
| 370 } | |
| 371 | |
| 372 PreParser::Statement PreParser::ParseSwitchStatement( | 203 PreParser::Statement PreParser::ParseSwitchStatement( |
| 373 ZoneList<const AstRawString*>* labels, bool* ok) { | 204 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 374 // SwitchStatement :: | 205 // SwitchStatement :: |
| 375 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 206 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 376 | 207 |
| 377 Expect(Token::SWITCH, CHECK_OK); | 208 Expect(Token::SWITCH, CHECK_OK); |
| 378 Expect(Token::LPAREN, CHECK_OK); | 209 Expect(Token::LPAREN, CHECK_OK); |
| 379 ParseExpression(true, CHECK_OK); | 210 ParseExpression(true, CHECK_OK); |
| 380 Expect(Token::RPAREN, CHECK_OK); | 211 Expect(Token::RPAREN, CHECK_OK); |
| 381 | 212 |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 | 667 |
| 837 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 668 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
| 838 } | 669 } |
| 839 | 670 |
| 840 #undef CHECK_OK | 671 #undef CHECK_OK |
| 841 #undef CHECK_OK_CUSTOM | 672 #undef CHECK_OK_CUSTOM |
| 842 | 673 |
| 843 | 674 |
| 844 } // namespace internal | 675 } // namespace internal |
| 845 } // namespace v8 | 676 } // namespace v8 |
| OLD | NEW |