| 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 *ok = false; | 157 *ok = false; |
| 158 return Statement::Default(); | 158 return Statement::Default(); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 // PreParser is not able to parse "export default" yet (since PreParser is | 161 // PreParser is not able to parse "export default" yet (since PreParser is |
| 162 // at the moment only used for functions, and it cannot occur | 162 // at the moment only used for functions, and it cannot occur |
| 163 // there). TODO(marja): update this when it is. | 163 // there). TODO(marja): update this when it is. |
| 164 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); | 164 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); |
| 165 } | 165 } |
| 166 | 166 |
| 167 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( | |
| 168 ZoneList<const AstRawString*>* names, | |
| 169 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
| 170 // ExpressionStatement | LabelledStatement :: | |
| 171 // Expression ';' | |
| 172 // Identifier ':' Statement | |
| 173 | |
| 174 switch (peek()) { | |
| 175 case Token::FUNCTION: | |
| 176 case Token::LBRACE: | |
| 177 UNREACHABLE(); // Always handled by the callers. | |
| 178 case Token::CLASS: | |
| 179 ReportUnexpectedToken(Next()); | |
| 180 *ok = false; | |
| 181 return Statement::Default(); | |
| 182 | |
| 183 default: | |
| 184 break; | |
| 185 } | |
| 186 | |
| 187 bool starts_with_identifier = peek_any_identifier(); | |
| 188 ExpressionClassifier classifier(this); | |
| 189 Expression expr = ParseExpressionCoverGrammar(true, CHECK_OK); | |
| 190 ValidateExpression(CHECK_OK); | |
| 191 | |
| 192 // Even if the expression starts with an identifier, it is not necessarily an | |
| 193 // identifier. For example, "foo + bar" starts with an identifier but is not | |
| 194 // an identifier. | |
| 195 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { | |
| 196 // Expression is a single identifier, and not, e.g., a parenthesized | |
| 197 // identifier. | |
| 198 DCHECK(!expr.AsIdentifier().IsEnum()); | |
| 199 DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait()); | |
| 200 DCHECK(is_sloppy(language_mode()) || | |
| 201 !IsFutureStrictReserved(expr.AsIdentifier())); | |
| 202 Consume(Token::COLON); | |
| 203 // ES#sec-labelled-function-declarations Labelled Function Declarations | |
| 204 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | |
| 205 if (allow_function == kAllowLabelledFunctionStatement) { | |
| 206 return ParseFunctionDeclaration(ok); | |
| 207 } else { | |
| 208 return ParseScopedStatement(names, true, ok); | |
| 209 } | |
| 210 } | |
| 211 Statement statement = | |
| 212 ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); | |
| 213 return statement.IsJumpStatement() ? Statement::Default() : statement; | |
| 214 // Preparsing is disabled for extensions (because the extension details | |
| 215 // aren't passed to lazily compiled functions), so we don't | |
| 216 // accept "native function" in the preparser. | |
| 217 } | |
| 218 // Parsed expression statement. | |
| 219 ExpectSemicolon(CHECK_OK); | |
| 220 return Statement::ExpressionStatement(expr); | |
| 221 } | |
| 222 | |
| 223 PreParser::Statement PreParser::ParseIfStatement( | |
| 224 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 225 // IfStatement :: | |
| 226 // 'if' '(' Expression ')' Statement ('else' Statement)? | |
| 227 | |
| 228 Expect(Token::IF, CHECK_OK); | |
| 229 Expect(Token::LPAREN, CHECK_OK); | |
| 230 ParseExpression(true, CHECK_OK); | |
| 231 Expect(Token::RPAREN, CHECK_OK); | |
| 232 Statement stat = ParseScopedStatement(labels, false, CHECK_OK); | |
| 233 if (peek() == Token::ELSE) { | |
| 234 Next(); | |
| 235 Statement else_stat = ParseScopedStatement(labels, false, CHECK_OK); | |
| 236 stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ? | |
| 237 Statement::Jump() : Statement::Default(); | |
| 238 } else { | |
| 239 stat = Statement::Default(); | |
| 240 } | |
| 241 return stat; | |
| 242 } | |
| 243 | |
| 244 | |
| 245 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { | |
| 246 // ContinueStatement :: | |
| 247 // 'continue' [no line terminator] Identifier? ';' | |
| 248 | |
| 249 Expect(Token::CONTINUE, CHECK_OK); | |
| 250 Token::Value tok = peek(); | |
| 251 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 252 tok != Token::SEMICOLON && | |
| 253 tok != Token::RBRACE && | |
| 254 tok != Token::EOS) { | |
| 255 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 256 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 257 } | |
| 258 ExpectSemicolon(CHECK_OK); | |
| 259 return Statement::Jump(); | |
| 260 } | |
| 261 | |
| 262 PreParser::Statement PreParser::ParseBreakStatement( | |
| 263 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 264 // BreakStatement :: | |
| 265 // 'break' [no line terminator] Identifier? ';' | |
| 266 | |
| 267 Expect(Token::BREAK, CHECK_OK); | |
| 268 Token::Value tok = peek(); | |
| 269 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 270 tok != Token::SEMICOLON && | |
| 271 tok != Token::RBRACE && | |
| 272 tok != Token::EOS) { | |
| 273 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
| 274 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 275 } | |
| 276 ExpectSemicolon(CHECK_OK); | |
| 277 return Statement::Jump(); | |
| 278 } | |
| 279 | |
| 280 | |
| 281 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | |
| 282 // ReturnStatement :: | |
| 283 // 'return' [no line terminator] Expression? ';' | |
| 284 | |
| 285 // Consume the return token. It is necessary to do before | |
| 286 // reporting any errors on it, because of the way errors are | |
| 287 // reported (underlining). | |
| 288 Expect(Token::RETURN, CHECK_OK); | |
| 289 | |
| 290 // An ECMAScript program is considered syntactically incorrect if it | |
| 291 // contains a return statement that is not within the body of a | |
| 292 // function. See ECMA-262, section 12.9, page 67. | |
| 293 // This is not handled during preparsing. | |
| 294 | |
| 295 Token::Value tok = peek(); | |
| 296 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 297 tok != Token::SEMICOLON && | |
| 298 tok != Token::RBRACE && | |
| 299 tok != Token::EOS) { | |
| 300 // Because of the return code rewriting that happens in case of a subclass | |
| 301 // constructor we don't want to accept tail calls, therefore we don't set | |
| 302 // ReturnExprScope to kInsideValidReturnStatement here. | |
| 303 ReturnExprContext return_expr_context = | |
| 304 IsSubclassConstructor(function_state_->kind()) | |
| 305 ? function_state_->return_expr_context() | |
| 306 : ReturnExprContext::kInsideValidReturnStatement; | |
| 307 | |
| 308 ReturnExprScope maybe_allow_tail_calls(function_state_, | |
| 309 return_expr_context); | |
| 310 ParseExpression(true, CHECK_OK); | |
| 311 } | |
| 312 ExpectSemicolon(CHECK_OK); | |
| 313 return Statement::Jump(); | |
| 314 } | |
| 315 | |
| 316 PreParser::Statement PreParser::ParseWithStatement( | |
| 317 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 318 // WithStatement :: | |
| 319 // 'with' '(' Expression ')' Statement | |
| 320 Expect(Token::WITH, CHECK_OK); | |
| 321 if (is_strict(language_mode())) { | |
| 322 ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith); | |
| 323 *ok = false; | |
| 324 return Statement::Default(); | |
| 325 } | |
| 326 Expect(Token::LPAREN, CHECK_OK); | |
| 327 ParseExpression(true, CHECK_OK); | |
| 328 Expect(Token::RPAREN, CHECK_OK); | |
| 329 | |
| 330 Scope* with_scope = NewScope(WITH_SCOPE); | |
| 331 BlockState block_state(&scope_state_, with_scope); | |
| 332 ParseScopedStatement(labels, true, CHECK_OK); | |
| 333 return Statement::Default(); | |
| 334 } | |
| 335 | |
| 336 PreParser::Statement PreParser::ParseSwitchStatement( | 167 PreParser::Statement PreParser::ParseSwitchStatement( |
| 337 ZoneList<const AstRawString*>* labels, bool* ok) { | 168 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 338 // SwitchStatement :: | 169 // SwitchStatement :: |
| 339 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 170 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 340 | 171 |
| 341 Expect(Token::SWITCH, CHECK_OK); | 172 Expect(Token::SWITCH, CHECK_OK); |
| 342 Expect(Token::LPAREN, CHECK_OK); | 173 Expect(Token::LPAREN, CHECK_OK); |
| 343 ParseExpression(true, CHECK_OK); | 174 ParseExpression(true, CHECK_OK); |
| 344 Expect(Token::RPAREN, CHECK_OK); | 175 Expect(Token::RPAREN, CHECK_OK); |
| 345 | 176 |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 | 631 |
| 801 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 632 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
| 802 } | 633 } |
| 803 | 634 |
| 804 #undef CHECK_OK | 635 #undef CHECK_OK |
| 805 #undef CHECK_OK_CUSTOM | 636 #undef CHECK_OK_CUSTOM |
| 806 | 637 |
| 807 | 638 |
| 808 } // namespace internal | 639 } // namespace internal |
| 809 } // namespace v8 | 640 } // namespace v8 |
| OLD | NEW |