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 |