| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "checks.h" | 31 #include "checks.h" |
| 32 #include "allocation.h" | 32 #include "allocation.h" |
| 33 #include "utils.h" | 33 #include "utils.h" |
| 34 #include "list.h" | 34 #include "list.h" |
| 35 | 35 |
| 36 #include "scanner-base.h" | 36 #include "scanner-base.h" |
| 37 #include "preparse-data-format.h" | 37 #include "preparse-data-format.h" |
| 38 #include "preparse-data.h" | 38 #include "preparse-data.h" |
| 39 #include "preparser.h" | 39 #include "preparser.h" |
| 40 | 40 |
| 41 #include "conversions-inl.h" |
| 42 |
| 41 namespace v8 { | 43 namespace v8 { |
| 42 namespace preparser { | 44 namespace preparser { |
| 43 | 45 |
| 44 // Preparsing checks a JavaScript program and emits preparse-data that helps | 46 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 45 // a later parsing to be faster. | 47 // a later parsing to be faster. |
| 46 // See preparser-data.h for the data. | 48 // See preparser-data.h for the data. |
| 47 | 49 |
| 48 // The PreParser checks that the syntax follows the grammar for JavaScript, | 50 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 49 // and collects some information about the program along the way. | 51 // and collects some information about the program along the way. |
| 50 // The grammar check is only performed in order to understand the program | 52 // The grammar check is only performed in order to understand the program |
| (...skipping 19 matching lines...) Expand all Loading... |
| 70 case i::Token::EOS: | 72 case i::Token::EOS: |
| 71 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 73 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 72 "unexpected_eos", NULL); | 74 "unexpected_eos", NULL); |
| 73 case i::Token::NUMBER: | 75 case i::Token::NUMBER: |
| 74 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 76 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 75 "unexpected_token_number", NULL); | 77 "unexpected_token_number", NULL); |
| 76 case i::Token::STRING: | 78 case i::Token::STRING: |
| 77 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 79 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 78 "unexpected_token_string", NULL); | 80 "unexpected_token_string", NULL); |
| 79 case i::Token::IDENTIFIER: | 81 case i::Token::IDENTIFIER: |
| 82 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 83 "unexpected_token_identifier", NULL); |
| 80 case i::Token::FUTURE_RESERVED_WORD: | 84 case i::Token::FUTURE_RESERVED_WORD: |
| 81 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 85 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 82 "unexpected_token_identifier", NULL); | 86 "unexpected_reserved", NULL); |
| 87 case i::Token::FUTURE_STRICT_RESERVED_WORD: |
| 88 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 89 "unexpected_strict_reserved", NULL); |
| 83 default: | 90 default: |
| 84 const char* name = i::Token::String(token); | 91 const char* name = i::Token::String(token); |
| 85 ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 92 ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 86 "unexpected_token", name); | 93 "unexpected_token", name); |
| 87 } | 94 } |
| 88 } | 95 } |
| 89 | 96 |
| 90 | 97 |
| 91 // Checks whether octal literal last seen is between beg_pos and end_pos. | 98 // Checks whether octal literal last seen is between beg_pos and end_pos. |
| 92 // If so, reports an error. | 99 // If so, reports an error. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 | 209 |
| 203 case i::Token::THROW: | 210 case i::Token::THROW: |
| 204 return ParseThrowStatement(ok); | 211 return ParseThrowStatement(ok); |
| 205 | 212 |
| 206 case i::Token::TRY: | 213 case i::Token::TRY: |
| 207 return ParseTryStatement(ok); | 214 return ParseTryStatement(ok); |
| 208 | 215 |
| 209 case i::Token::FUNCTION: | 216 case i::Token::FUNCTION: |
| 210 return ParseFunctionDeclaration(ok); | 217 return ParseFunctionDeclaration(ok); |
| 211 | 218 |
| 212 case i::Token::NATIVE: | |
| 213 return ParseNativeDeclaration(ok); | |
| 214 | |
| 215 case i::Token::DEBUGGER: | 219 case i::Token::DEBUGGER: |
| 216 return ParseDebuggerStatement(ok); | 220 return ParseDebuggerStatement(ok); |
| 217 | 221 |
| 218 default: | 222 default: |
| 219 return ParseExpressionOrLabelledStatement(ok); | 223 return ParseExpressionOrLabelledStatement(ok); |
| 220 } | 224 } |
| 221 } | 225 } |
| 222 | 226 |
| 223 | 227 |
| 224 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 228 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| 225 // FunctionDeclaration :: | 229 // FunctionDeclaration :: |
| 226 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 230 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 227 Expect(i::Token::FUNCTION, CHECK_OK); | 231 Expect(i::Token::FUNCTION, CHECK_OK); |
| 228 | 232 |
| 229 Identifier identifier = ParseIdentifier(CHECK_OK); | 233 Identifier identifier = ParseIdentifier(CHECK_OK); |
| 230 i::Scanner::Location location = scanner_->location(); | 234 i::Scanner::Location location = scanner_->location(); |
| 231 | 235 |
| 232 Expression function_value = ParseFunctionLiteral(CHECK_OK); | 236 Expression function_value = ParseFunctionLiteral(CHECK_OK); |
| 233 | 237 |
| 234 if (function_value.IsStrictFunction() && | 238 if (function_value.IsStrictFunction() && |
| 235 !identifier.IsValidStrictVariable()) { | 239 !identifier.IsValidStrictVariable()) { |
| 236 // Strict mode violation, using either reserved word or eval/arguments | 240 // Strict mode violation, using either reserved word or eval/arguments |
| 237 // as name of strict function. | 241 // as name of strict function. |
| 238 const char* type = "strict_function_name"; | 242 const char* type = "strict_function_name"; |
| 239 if (identifier.IsFutureReserved()) { | 243 if (identifier.IsFutureStrictReserved()) { |
| 240 type = "strict_reserved_word"; | 244 type = "strict_reserved_word"; |
| 241 } | 245 } |
| 242 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); | 246 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
| 243 *ok = false; | 247 *ok = false; |
| 244 } | 248 } |
| 245 return Statement::FunctionDeclaration(); | 249 return Statement::FunctionDeclaration(); |
| 246 } | 250 } |
| 247 | 251 |
| 248 | 252 |
| 249 // Language extension which is only enabled for source files loaded | |
| 250 // through the API's extension mechanism. A native function | |
| 251 // declaration is resolved by looking up the function through a | |
| 252 // callback provided by the extension. | |
| 253 PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) { | |
| 254 Expect(i::Token::NATIVE, CHECK_OK); | |
| 255 Expect(i::Token::FUNCTION, CHECK_OK); | |
| 256 ParseIdentifier(CHECK_OK); | |
| 257 Expect(i::Token::LPAREN, CHECK_OK); | |
| 258 bool done = (peek() == i::Token::RPAREN); | |
| 259 while (!done) { | |
| 260 ParseIdentifier(CHECK_OK); | |
| 261 done = (peek() == i::Token::RPAREN); | |
| 262 if (!done) { | |
| 263 Expect(i::Token::COMMA, CHECK_OK); | |
| 264 } | |
| 265 } | |
| 266 Expect(i::Token::RPAREN, CHECK_OK); | |
| 267 Expect(i::Token::SEMICOLON, CHECK_OK); | |
| 268 return Statement::Default(); | |
| 269 } | |
| 270 | |
| 271 | |
| 272 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 253 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 273 // Block :: | 254 // Block :: |
| 274 // '{' Statement* '}' | 255 // '{' Statement* '}' |
| 275 | 256 |
| 276 // Note that a Block does not introduce a new execution scope! | 257 // Note that a Block does not introduce a new execution scope! |
| 277 // (ECMA-262, 3rd, 12.2) | 258 // (ECMA-262, 3rd, 12.2) |
| 278 // | 259 // |
| 279 Expect(i::Token::LBRACE, CHECK_OK); | 260 Expect(i::Token::LBRACE, CHECK_OK); |
| 280 while (peek() != i::Token::RBRACE) { | 261 while (peek() != i::Token::RBRACE) { |
| 281 i::Scanner::Location start_location = scanner_->peek_location(); | 262 i::Scanner::Location start_location = scanner_->peek_location(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 return Statement::Default(); | 336 return Statement::Default(); |
| 356 } | 337 } |
| 357 | 338 |
| 358 | 339 |
| 359 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 340 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| 360 // ExpressionStatement | LabelledStatement :: | 341 // ExpressionStatement | LabelledStatement :: |
| 361 // Expression ';' | 342 // Expression ';' |
| 362 // Identifier ':' Statement | 343 // Identifier ':' Statement |
| 363 | 344 |
| 364 Expression expr = ParseExpression(true, CHECK_OK); | 345 Expression expr = ParseExpression(true, CHECK_OK); |
| 365 if (peek() == i::Token::COLON && expr.IsRawIdentifier()) { | 346 if (expr.IsRawIdentifier()) { |
| 366 if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) { | 347 if (peek() == i::Token::COLON && |
| 348 (!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) { |
| 367 Consume(i::Token::COLON); | 349 Consume(i::Token::COLON); |
| 368 i::Scanner::Location start_location = scanner_->peek_location(); | 350 i::Scanner::Location start_location = scanner_->peek_location(); |
| 369 Statement statement = ParseStatement(CHECK_OK); | 351 Statement statement = ParseStatement(CHECK_OK); |
| 370 if (strict_mode() && statement.IsFunctionDeclaration()) { | 352 if (strict_mode() && statement.IsFunctionDeclaration()) { |
| 371 i::Scanner::Location end_location = scanner_->location(); | 353 i::Scanner::Location end_location = scanner_->location(); |
| 372 ReportMessageAt(start_location.beg_pos, end_location.end_pos, | 354 ReportMessageAt(start_location.beg_pos, end_location.end_pos, |
| 373 "strict_function", NULL); | 355 "strict_function", NULL); |
| 374 *ok = false; | 356 *ok = false; |
| 375 } | 357 } |
| 376 return Statement::Default(); | 358 return Statement::Default(); |
| 377 } | 359 } |
| 360 // Preparsing is disabled for extensions (because the extension details |
| 361 // aren't passed to lazily compiled functions), so we don't |
| 362 // accept "native function" in the preparser. |
| 378 } | 363 } |
| 379 // Parsed expression statement. | 364 // Parsed expression statement. |
| 380 ExpectSemicolon(CHECK_OK); | 365 ExpectSemicolon(CHECK_OK); |
| 381 return Statement::ExpressionStatement(expr); | 366 return Statement::ExpressionStatement(expr); |
| 382 } | 367 } |
| 383 | 368 |
| 384 | 369 |
| 385 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { | 370 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
| 386 // IfStatement :: | 371 // IfStatement :: |
| 387 // 'if' '(' Expression ')' Statement ('else' Statement)? | 372 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| (...skipping 10 matching lines...) Expand all Loading... |
| 398 return Statement::Default(); | 383 return Statement::Default(); |
| 399 } | 384 } |
| 400 | 385 |
| 401 | 386 |
| 402 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { | 387 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
| 403 // ContinueStatement :: | 388 // ContinueStatement :: |
| 404 // 'continue' [no line terminator] Identifier? ';' | 389 // 'continue' [no line terminator] Identifier? ';' |
| 405 | 390 |
| 406 Expect(i::Token::CONTINUE, CHECK_OK); | 391 Expect(i::Token::CONTINUE, CHECK_OK); |
| 407 i::Token::Value tok = peek(); | 392 i::Token::Value tok = peek(); |
| 408 if (!scanner_->has_line_terminator_before_next() && | 393 if (!scanner_->HasAnyLineTerminatorBeforeNext() && |
| 409 tok != i::Token::SEMICOLON && | 394 tok != i::Token::SEMICOLON && |
| 410 tok != i::Token::RBRACE && | 395 tok != i::Token::RBRACE && |
| 411 tok != i::Token::EOS) { | 396 tok != i::Token::EOS) { |
| 412 ParseIdentifier(CHECK_OK); | 397 ParseIdentifier(CHECK_OK); |
| 413 } | 398 } |
| 414 ExpectSemicolon(CHECK_OK); | 399 ExpectSemicolon(CHECK_OK); |
| 415 return Statement::Default(); | 400 return Statement::Default(); |
| 416 } | 401 } |
| 417 | 402 |
| 418 | 403 |
| 419 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { | 404 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
| 420 // BreakStatement :: | 405 // BreakStatement :: |
| 421 // 'break' [no line terminator] Identifier? ';' | 406 // 'break' [no line terminator] Identifier? ';' |
| 422 | 407 |
| 423 Expect(i::Token::BREAK, CHECK_OK); | 408 Expect(i::Token::BREAK, CHECK_OK); |
| 424 i::Token::Value tok = peek(); | 409 i::Token::Value tok = peek(); |
| 425 if (!scanner_->has_line_terminator_before_next() && | 410 if (!scanner_->HasAnyLineTerminatorBeforeNext() && |
| 426 tok != i::Token::SEMICOLON && | 411 tok != i::Token::SEMICOLON && |
| 427 tok != i::Token::RBRACE && | 412 tok != i::Token::RBRACE && |
| 428 tok != i::Token::EOS) { | 413 tok != i::Token::EOS) { |
| 429 ParseIdentifier(CHECK_OK); | 414 ParseIdentifier(CHECK_OK); |
| 430 } | 415 } |
| 431 ExpectSemicolon(CHECK_OK); | 416 ExpectSemicolon(CHECK_OK); |
| 432 return Statement::Default(); | 417 return Statement::Default(); |
| 433 } | 418 } |
| 434 | 419 |
| 435 | 420 |
| 436 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | 421 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
| 437 // ReturnStatement :: | 422 // ReturnStatement :: |
| 438 // 'return' [no line terminator] Expression? ';' | 423 // 'return' [no line terminator] Expression? ';' |
| 439 | 424 |
| 440 // Consume the return token. It is necessary to do the before | 425 // Consume the return token. It is necessary to do the before |
| 441 // reporting any errors on it, because of the way errors are | 426 // reporting any errors on it, because of the way errors are |
| 442 // reported (underlining). | 427 // reported (underlining). |
| 443 Expect(i::Token::RETURN, CHECK_OK); | 428 Expect(i::Token::RETURN, CHECK_OK); |
| 444 | 429 |
| 445 // An ECMAScript program is considered syntactically incorrect if it | 430 // An ECMAScript program is considered syntactically incorrect if it |
| 446 // contains a return statement that is not within the body of a | 431 // contains a return statement that is not within the body of a |
| 447 // function. See ECMA-262, section 12.9, page 67. | 432 // function. See ECMA-262, section 12.9, page 67. |
| 448 // This is not handled during preparsing. | 433 // This is not handled during preparsing. |
| 449 | 434 |
| 450 i::Token::Value tok = peek(); | 435 i::Token::Value tok = peek(); |
| 451 if (!scanner_->has_line_terminator_before_next() && | 436 if (!scanner_->HasAnyLineTerminatorBeforeNext() && |
| 452 tok != i::Token::SEMICOLON && | 437 tok != i::Token::SEMICOLON && |
| 453 tok != i::Token::RBRACE && | 438 tok != i::Token::RBRACE && |
| 454 tok != i::Token::EOS) { | 439 tok != i::Token::EOS) { |
| 455 ParseExpression(true, CHECK_OK); | 440 ParseExpression(true, CHECK_OK); |
| 456 } | 441 } |
| 457 ExpectSemicolon(CHECK_OK); | 442 ExpectSemicolon(CHECK_OK); |
| 458 return Statement::Default(); | 443 return Statement::Default(); |
| 459 } | 444 } |
| 460 | 445 |
| 461 | 446 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 ParseStatement(ok); | 577 ParseStatement(ok); |
| 593 return Statement::Default(); | 578 return Statement::Default(); |
| 594 } | 579 } |
| 595 | 580 |
| 596 | 581 |
| 597 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { | 582 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { |
| 598 // ThrowStatement :: | 583 // ThrowStatement :: |
| 599 // 'throw' [no line terminator] Expression ';' | 584 // 'throw' [no line terminator] Expression ';' |
| 600 | 585 |
| 601 Expect(i::Token::THROW, CHECK_OK); | 586 Expect(i::Token::THROW, CHECK_OK); |
| 602 if (scanner_->has_line_terminator_before_next()) { | 587 if (scanner_->HasAnyLineTerminatorBeforeNext()) { |
| 603 i::JavaScriptScanner::Location pos = scanner_->location(); | 588 i::JavaScriptScanner::Location pos = scanner_->location(); |
| 604 ReportMessageAt(pos.beg_pos, pos.end_pos, | 589 ReportMessageAt(pos.beg_pos, pos.end_pos, |
| 605 "newline_after_throw", NULL); | 590 "newline_after_throw", NULL); |
| 606 *ok = false; | 591 *ok = false; |
| 607 return Statement::Default(); | 592 return Statement::Default(); |
| 608 } | 593 } |
| 609 ParseExpression(true, CHECK_OK); | 594 ParseExpression(true, CHECK_OK); |
| 610 ExpectSemicolon(ok); | 595 ExpectSemicolon(ok); |
| 611 return Statement::Default(); | 596 return Statement::Default(); |
| 612 } | 597 } |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 } | 800 } |
| 816 } | 801 } |
| 817 | 802 |
| 818 | 803 |
| 819 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { | 804 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { |
| 820 // PostfixExpression :: | 805 // PostfixExpression :: |
| 821 // LeftHandSideExpression ('++' | '--')? | 806 // LeftHandSideExpression ('++' | '--')? |
| 822 | 807 |
| 823 i::Scanner::Location before = scanner_->peek_location(); | 808 i::Scanner::Location before = scanner_->peek_location(); |
| 824 Expression expression = ParseLeftHandSideExpression(CHECK_OK); | 809 Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
| 825 if (!scanner_->has_line_terminator_before_next() && | 810 if (!scanner_->HasAnyLineTerminatorBeforeNext() && |
| 826 i::Token::IsCountOp(peek())) { | 811 i::Token::IsCountOp(peek())) { |
| 827 if (strict_mode() && expression.IsIdentifier() && | 812 if (strict_mode() && expression.IsIdentifier() && |
| 828 expression.AsIdentifier().IsEvalOrArguments()) { | 813 expression.AsIdentifier().IsEvalOrArguments()) { |
| 829 i::Scanner::Location after = scanner_->location(); | 814 i::Scanner::Location after = scanner_->location(); |
| 830 ReportMessageAt(before.beg_pos, after.end_pos, | 815 ReportMessageAt(before.beg_pos, after.end_pos, |
| 831 "strict_lhs_postfix", NULL); | 816 "strict_lhs_postfix", NULL); |
| 832 *ok = false; | 817 *ok = false; |
| 833 return Expression::Default(); | 818 return Expression::Default(); |
| 834 } | 819 } |
| 835 Next(); | 820 Next(); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 // '(' Expression ')' | 979 // '(' Expression ')' |
| 995 | 980 |
| 996 Expression result = Expression::Default(); | 981 Expression result = Expression::Default(); |
| 997 switch (peek()) { | 982 switch (peek()) { |
| 998 case i::Token::THIS: { | 983 case i::Token::THIS: { |
| 999 Next(); | 984 Next(); |
| 1000 result = Expression::This(); | 985 result = Expression::This(); |
| 1001 break; | 986 break; |
| 1002 } | 987 } |
| 1003 | 988 |
| 1004 case i::Token::FUTURE_RESERVED_WORD: | 989 case i::Token::FUTURE_RESERVED_WORD: { |
| 990 Next(); |
| 991 i::Scanner::Location location = scanner_->location(); |
| 992 ReportMessageAt(location.beg_pos, location.end_pos, |
| 993 "reserved_word", NULL); |
| 994 *ok = false; |
| 995 return Expression::Default(); |
| 996 } |
| 997 |
| 998 case i::Token::FUTURE_STRICT_RESERVED_WORD: |
| 1005 if (strict_mode()) { | 999 if (strict_mode()) { |
| 1006 Next(); | 1000 Next(); |
| 1007 i::Scanner::Location location = scanner_->location(); | 1001 i::Scanner::Location location = scanner_->location(); |
| 1008 ReportMessageAt(location.beg_pos, location.end_pos, | 1002 ReportMessageAt(location.beg_pos, location.end_pos, |
| 1009 "strict_reserved_word", NULL); | 1003 "strict_reserved_word", NULL); |
| 1010 *ok = false; | 1004 *ok = false; |
| 1011 return Expression::Default(); | 1005 return Expression::Default(); |
| 1012 } | 1006 } |
| 1013 // FALLTHROUGH | 1007 // FALLTHROUGH |
| 1014 case i::Token::IDENTIFIER: { | 1008 case i::Token::IDENTIFIER: { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 // '{' ( | 1087 // '{' ( |
| 1094 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 1088 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 1095 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1089 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1096 // )*[','] '}' | 1090 // )*[','] '}' |
| 1097 | 1091 |
| 1098 Expect(i::Token::LBRACE, CHECK_OK); | 1092 Expect(i::Token::LBRACE, CHECK_OK); |
| 1099 while (peek() != i::Token::RBRACE) { | 1093 while (peek() != i::Token::RBRACE) { |
| 1100 i::Token::Value next = peek(); | 1094 i::Token::Value next = peek(); |
| 1101 switch (next) { | 1095 switch (next) { |
| 1102 case i::Token::IDENTIFIER: | 1096 case i::Token::IDENTIFIER: |
| 1103 case i::Token::FUTURE_RESERVED_WORD: { | 1097 case i::Token::FUTURE_RESERVED_WORD: |
| 1098 case i::Token::FUTURE_STRICT_RESERVED_WORD: { |
| 1104 bool is_getter = false; | 1099 bool is_getter = false; |
| 1105 bool is_setter = false; | 1100 bool is_setter = false; |
| 1106 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1101 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 1107 if ((is_getter || is_setter) && peek() != i::Token::COLON) { | 1102 if ((is_getter || is_setter) && peek() != i::Token::COLON) { |
| 1108 i::Token::Value name = Next(); | 1103 i::Token::Value name = Next(); |
| 1109 bool is_keyword = i::Token::IsKeyword(name); | 1104 bool is_keyword = i::Token::IsKeyword(name); |
| 1110 if (name != i::Token::IDENTIFIER && | 1105 if (name != i::Token::IDENTIFIER && |
| 1111 name != i::Token::FUTURE_RESERVED_WORD && | 1106 name != i::Token::FUTURE_RESERVED_WORD && |
| 1107 name != i::Token::FUTURE_STRICT_RESERVED_WORD && |
| 1112 name != i::Token::NUMBER && | 1108 name != i::Token::NUMBER && |
| 1113 name != i::Token::STRING && | 1109 name != i::Token::STRING && |
| 1114 !is_keyword) { | 1110 !is_keyword) { |
| 1115 *ok = false; | 1111 *ok = false; |
| 1116 return Expression::Default(); | 1112 return Expression::Default(); |
| 1117 } | 1113 } |
| 1118 if (!is_keyword) { | 1114 if (!is_keyword) { |
| 1119 LogSymbol(); | 1115 LogSymbol(); |
| 1120 } | 1116 } |
| 1121 ParseFunctionLiteral(CHECK_OK); | 1117 ParseFunctionLiteral(CHECK_OK); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 ParseSourceElements(i::Token::RBRACE, ok); | 1245 ParseSourceElements(i::Token::RBRACE, ok); |
| 1250 log_->ResumeRecording(); | 1246 log_->ResumeRecording(); |
| 1251 if (!*ok) Expression::Default(); | 1247 if (!*ok) Expression::Default(); |
| 1252 | 1248 |
| 1253 Expect(i::Token::RBRACE, CHECK_OK); | 1249 Expect(i::Token::RBRACE, CHECK_OK); |
| 1254 | 1250 |
| 1255 // Position right after terminal '}'. | 1251 // Position right after terminal '}'. |
| 1256 int end_pos = scanner_->location().end_pos; | 1252 int end_pos = scanner_->location().end_pos; |
| 1257 log_->LogFunction(function_block_pos, end_pos, | 1253 log_->LogFunction(function_block_pos, end_pos, |
| 1258 function_scope.materialized_literal_count(), | 1254 function_scope.materialized_literal_count(), |
| 1259 function_scope.expected_properties()); | 1255 function_scope.expected_properties(), |
| 1256 strict_mode() ? 1 : 0); |
| 1260 } else { | 1257 } else { |
| 1261 ParseSourceElements(i::Token::RBRACE, CHECK_OK); | 1258 ParseSourceElements(i::Token::RBRACE, CHECK_OK); |
| 1262 Expect(i::Token::RBRACE, CHECK_OK); | 1259 Expect(i::Token::RBRACE, CHECK_OK); |
| 1263 } | 1260 } |
| 1264 | 1261 |
| 1265 if (strict_mode()) { | 1262 if (strict_mode()) { |
| 1266 int end_position = scanner_->location().end_pos; | 1263 int end_position = scanner_->location().end_pos; |
| 1267 CheckOctalLiteral(start_position, end_position, CHECK_OK); | 1264 CheckOctalLiteral(start_position, end_position, CHECK_OK); |
| 1268 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); | 1265 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); |
| 1269 return Expression::StrictFunction(); | 1266 return Expression::StrictFunction(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1288 | 1285 |
| 1289 | 1286 |
| 1290 void PreParser::ExpectSemicolon(bool* ok) { | 1287 void PreParser::ExpectSemicolon(bool* ok) { |
| 1291 // Check for automatic semicolon insertion according to | 1288 // Check for automatic semicolon insertion according to |
| 1292 // the rules given in ECMA-262, section 7.9, page 21. | 1289 // the rules given in ECMA-262, section 7.9, page 21. |
| 1293 i::Token::Value tok = peek(); | 1290 i::Token::Value tok = peek(); |
| 1294 if (tok == i::Token::SEMICOLON) { | 1291 if (tok == i::Token::SEMICOLON) { |
| 1295 Next(); | 1292 Next(); |
| 1296 return; | 1293 return; |
| 1297 } | 1294 } |
| 1298 if (scanner_->has_line_terminator_before_next() || | 1295 if (scanner_->HasAnyLineTerminatorBeforeNext() || |
| 1299 tok == i::Token::RBRACE || | 1296 tok == i::Token::RBRACE || |
| 1300 tok == i::Token::EOS) { | 1297 tok == i::Token::EOS) { |
| 1301 return; | 1298 return; |
| 1302 } | 1299 } |
| 1303 Expect(i::Token::SEMICOLON, ok); | 1300 Expect(i::Token::SEMICOLON, ok); |
| 1304 } | 1301 } |
| 1305 | 1302 |
| 1306 | 1303 |
| 1307 void PreParser::LogSymbol() { | 1304 void PreParser::LogSymbol() { |
| 1308 int identifier_pos = scanner_->location().beg_pos; | 1305 int identifier_pos = scanner_->location().beg_pos; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1326 return Expression::UseStrictStringLiteral(); | 1323 return Expression::UseStrictStringLiteral(); |
| 1327 } | 1324 } |
| 1328 return Expression::StringLiteral(); | 1325 return Expression::StringLiteral(); |
| 1329 } | 1326 } |
| 1330 | 1327 |
| 1331 | 1328 |
| 1332 PreParser::Identifier PreParser::GetIdentifierSymbol() { | 1329 PreParser::Identifier PreParser::GetIdentifierSymbol() { |
| 1333 LogSymbol(); | 1330 LogSymbol(); |
| 1334 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) { | 1331 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) { |
| 1335 return Identifier::FutureReserved(); | 1332 return Identifier::FutureReserved(); |
| 1333 } else if (scanner_->current_token() == |
| 1334 i::Token::FUTURE_STRICT_RESERVED_WORD) { |
| 1335 return Identifier::FutureStrictReserved(); |
| 1336 } | 1336 } |
| 1337 if (scanner_->is_literal_ascii()) { | 1337 if (scanner_->is_literal_ascii()) { |
| 1338 // Detect strict-mode poison words. | 1338 // Detect strict-mode poison words. |
| 1339 if (scanner_->literal_length() == 4 && | 1339 if (scanner_->literal_length() == 4 && |
| 1340 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) { | 1340 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) { |
| 1341 return Identifier::Eval(); | 1341 return Identifier::Eval(); |
| 1342 } | 1342 } |
| 1343 if (scanner_->literal_length() == 9 && | 1343 if (scanner_->literal_length() == 9 && |
| 1344 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) { | 1344 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) { |
| 1345 return Identifier::Arguments(); | 1345 return Identifier::Arguments(); |
| 1346 } | 1346 } |
| 1347 } | 1347 } |
| 1348 return Identifier::Default(); | 1348 return Identifier::Default(); |
| 1349 } | 1349 } |
| 1350 | 1350 |
| 1351 | 1351 |
| 1352 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { | 1352 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { |
| 1353 if (!Check(i::Token::FUTURE_RESERVED_WORD)) { | 1353 i::Token::Value next = Next(); |
| 1354 Expect(i::Token::IDENTIFIER, ok); | 1354 switch (next) { |
| 1355 if (!*ok) return Identifier::Default(); | 1355 case i::Token::FUTURE_RESERVED_WORD: { |
| 1356 i::Scanner::Location location = scanner_->location(); |
| 1357 ReportMessageAt(location.beg_pos, location.end_pos, |
| 1358 "reserved_word", NULL); |
| 1359 *ok = false; |
| 1360 } |
| 1361 // FALLTHROUGH |
| 1362 case i::Token::FUTURE_STRICT_RESERVED_WORD: |
| 1363 case i::Token::IDENTIFIER: |
| 1364 return GetIdentifierSymbol(); |
| 1365 default: |
| 1366 *ok = false; |
| 1367 return Identifier::Default(); |
| 1356 } | 1368 } |
| 1357 return GetIdentifierSymbol(); | |
| 1358 } | 1369 } |
| 1359 | 1370 |
| 1360 | 1371 |
| 1361 void PreParser::SetStrictModeViolation(i::Scanner::Location location, | 1372 void PreParser::SetStrictModeViolation(i::Scanner::Location location, |
| 1362 const char* type, | 1373 const char* type, |
| 1363 bool* ok) { | 1374 bool* ok) { |
| 1364 if (strict_mode()) { | 1375 if (strict_mode()) { |
| 1365 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); | 1376 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
| 1366 *ok = false; | 1377 *ok = false; |
| 1367 return; | 1378 return; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1387 strict_mode_violation_location_ = i::Scanner::Location::invalid(); | 1398 strict_mode_violation_location_ = i::Scanner::Location::invalid(); |
| 1388 } | 1399 } |
| 1389 | 1400 |
| 1390 | 1401 |
| 1391 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, | 1402 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, |
| 1392 const char* eval_args_type, | 1403 const char* eval_args_type, |
| 1393 Identifier identifier, | 1404 Identifier identifier, |
| 1394 bool* ok) { | 1405 bool* ok) { |
| 1395 const char* type = eval_args_type; | 1406 const char* type = eval_args_type; |
| 1396 if (identifier.IsFutureReserved()) { | 1407 if (identifier.IsFutureReserved()) { |
| 1408 type = "reserved_word"; |
| 1409 } else if (identifier.IsFutureStrictReserved()) { |
| 1397 type = "strict_reserved_word"; | 1410 type = "strict_reserved_word"; |
| 1398 } | 1411 } |
| 1399 if (strict_mode()) { | 1412 if (strict_mode()) { |
| 1400 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); | 1413 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
| 1401 *ok = false; | 1414 *ok = false; |
| 1402 return; | 1415 return; |
| 1403 } | 1416 } |
| 1404 strict_mode_violation_location_ = location; | 1417 strict_mode_violation_location_ = location; |
| 1405 strict_mode_violation_type_ = type; | 1418 strict_mode_violation_type_ = type; |
| 1406 } | 1419 } |
| 1407 | 1420 |
| 1408 | 1421 |
| 1409 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { | 1422 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { |
| 1410 i::Token::Value next = Next(); | 1423 i::Token::Value next = Next(); |
| 1411 if (i::Token::IsKeyword(next)) { | 1424 if (i::Token::IsKeyword(next)) { |
| 1412 int pos = scanner_->location().beg_pos; | 1425 int pos = scanner_->location().beg_pos; |
| 1413 const char* keyword = i::Token::String(next); | 1426 const char* keyword = i::Token::String(next); |
| 1414 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, | 1427 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, |
| 1415 i::StrLength(keyword))); | 1428 i::StrLength(keyword))); |
| 1416 return Identifier::Default(); | 1429 return Identifier::Default(); |
| 1417 } | 1430 } |
| 1418 if (next == i::Token::IDENTIFIER || | 1431 if (next == i::Token::IDENTIFIER || |
| 1419 next == i::Token::FUTURE_RESERVED_WORD) { | 1432 next == i::Token::FUTURE_RESERVED_WORD || |
| 1433 next == i::Token::FUTURE_STRICT_RESERVED_WORD) { |
| 1420 return GetIdentifierSymbol(); | 1434 return GetIdentifierSymbol(); |
| 1421 } | 1435 } |
| 1422 *ok = false; | 1436 *ok = false; |
| 1423 return Identifier::Default(); | 1437 return Identifier::Default(); |
| 1424 } | 1438 } |
| 1425 | 1439 |
| 1426 #undef CHECK_OK | 1440 #undef CHECK_OK |
| 1427 | 1441 |
| 1428 | 1442 |
| 1429 // This function reads an identifier and determines whether or not it | 1443 // This function reads an identifier and determines whether or not it |
| 1430 // is 'get' or 'set'. | 1444 // is 'get' or 'set'. |
| 1431 PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, | 1445 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 1432 bool* is_set, | 1446 bool* is_set, |
| 1433 bool* ok) { | 1447 bool* ok) { |
| 1434 Identifier result = ParseIdentifier(ok); | 1448 Identifier result = ParseIdentifierName(ok); |
| 1435 if (!*ok) return Identifier::Default(); | 1449 if (!*ok) return Identifier::Default(); |
| 1436 if (scanner_->is_literal_ascii() && | 1450 if (scanner_->is_literal_ascii() && |
| 1437 scanner_->literal_length() == 3) { | 1451 scanner_->literal_length() == 3) { |
| 1438 const char* token = scanner_->literal_ascii_string().start(); | 1452 const char* token = scanner_->literal_ascii_string().start(); |
| 1439 *is_get = strncmp(token, "get", 3) == 0; | 1453 *is_get = strncmp(token, "get", 3) == 0; |
| 1440 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 1454 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 1441 } | 1455 } |
| 1442 return result; | 1456 return result; |
| 1443 } | 1457 } |
| 1444 | 1458 |
| 1445 bool PreParser::peek_any_identifier() { | 1459 bool PreParser::peek_any_identifier() { |
| 1446 i::Token::Value next = peek(); | 1460 i::Token::Value next = peek(); |
| 1447 return next == i::Token::IDENTIFIER || | 1461 return next == i::Token::IDENTIFIER || |
| 1448 next == i::Token::FUTURE_RESERVED_WORD; | 1462 next == i::Token::FUTURE_RESERVED_WORD || |
| 1463 next == i::Token::FUTURE_STRICT_RESERVED_WORD; |
| 1449 } | 1464 } |
| 1450 } } // v8::preparser | 1465 } } // v8::preparser |
| OLD | NEW |