| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1 | // Copyright 2011 the V8 project authors. All rights reserved. |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 4 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 5 | #include <cmath> |
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 6 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 7 | #include "include/v8stdint.h" |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 8 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 9 | #include "src/allocation.h" |
| 10 | #include "src/base/logging.h" |
| 11 | #include "src/conversions-inl.h" |
| 12 | #include "src/conversions.h" |
| 13 | #include "src/globals.h" |
| 14 | #include "src/hashmap.h" |
| 15 | #include "src/list.h" |
| 16 | #include "src/preparse-data.h" |
| 17 | #include "src/preparse-data-format.h" |
| 18 | #include "src/preparser.h" |
| 19 | #include "src/unicode.h" |
| 20 | #include "src/utils.h" |
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 21 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 22 | #if V8_LIBC_MSVCRT && (_MSC_VER < 1800) |
| 23 | namespace std { |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 24 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 25 | // Usually defined in math.h, but not in MSVC until VS2013+. |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 26 | // Abstracted to work |
| 27 | int isfinite(double value); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 28 | |
| 29 | } // namespace std |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 30 | #endif |
| 31 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 32 | namespace v8 { |
| 33 | namespace internal { |
| 34 | |
| 35 | class PreParserTraits::Checkpoint |
| 36 | : public ParserBase<PreParserTraits>::CheckpointBase { |
| 37 | public: |
| 38 | explicit Checkpoint(ParserBase<PreParserTraits>* parser) |
| 39 | : ParserBase<PreParserTraits>::CheckpointBase(parser) {} |
| 40 | }; |
| 41 | |
| 42 | void PreParserTraits::ReportMessageAt(Scanner::Location location, |
| 43 | const char* message, |
| 44 | const char* arg, |
| 45 | bool is_reference_error) { |
| 46 | ReportMessageAt(location.beg_pos, |
| 47 | location.end_pos, |
| 48 | message, |
| 49 | arg, |
| 50 | is_reference_error); |
| 51 | } |
| 52 | |
| 53 | |
| 54 | void PreParserTraits::ReportMessageAt(int start_pos, |
| 55 | int end_pos, |
| 56 | const char* message, |
| 57 | const char* arg, |
| 58 | bool is_reference_error) { |
| 59 | pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, |
| 60 | is_reference_error); |
| 61 | } |
| 62 | |
| 63 | |
| 64 | PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { |
| 65 | if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) { |
| 66 | return PreParserIdentifier::FutureReserved(); |
| 67 | } else if (scanner->current_token() == |
| 68 | Token::FUTURE_STRICT_RESERVED_WORD) { |
| 69 | return PreParserIdentifier::FutureStrictReserved(); |
| 70 | } else if (scanner->current_token() == Token::LET) { |
| 71 | return PreParserIdentifier::Let(); |
| 72 | } else if (scanner->current_token() == Token::YIELD) { |
| 73 | return PreParserIdentifier::Yield(); |
| 74 | } |
| 75 | if (scanner->UnescapedLiteralMatches("eval", 4)) { |
| 76 | return PreParserIdentifier::Eval(); |
| 77 | } |
| 78 | if (scanner->UnescapedLiteralMatches("arguments", 9)) { |
| 79 | return PreParserIdentifier::Arguments(); |
| 80 | } |
| 81 | if (scanner->UnescapedLiteralMatches("prototype", 9)) { |
| 82 | return PreParserIdentifier::Prototype(); |
| 83 | } |
| 84 | if (scanner->UnescapedLiteralMatches("constructor", 11)) { |
| 85 | return PreParserIdentifier::Constructor(); |
| 86 | } |
| 87 | return PreParserIdentifier::Default(); |
| 88 | } |
| 89 | |
| 90 | |
| 91 | PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) { |
| 92 | return PreParserIdentifier::Default(); |
| 93 | } |
| 94 | |
| 95 | |
| 96 | PreParserExpression PreParserTraits::ExpressionFromString( |
| 97 | int pos, Scanner* scanner, PreParserFactory* factory) { |
| 98 | if (scanner->UnescapedLiteralMatches("use strict", 10)) { |
| 99 | return PreParserExpression::UseStrictStringLiteral(); |
| 100 | } |
| 101 | return PreParserExpression::StringLiteral(); |
| 102 | } |
| 103 | |
| 104 | |
| 105 | PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) { |
| 106 | return pre_parser_->ParseV8Intrinsic(ok); |
| 107 | } |
| 108 | |
| 109 | |
| 110 | PreParserExpression PreParserTraits::ParseFunctionLiteral( |
| 111 | PreParserIdentifier name, Scanner::Location function_name_location, |
| 112 | bool name_is_strict_reserved, FunctionKind kind, |
| 113 | int function_token_position, FunctionLiteral::FunctionType type, |
| 114 | FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { |
| 115 | return pre_parser_->ParseFunctionLiteral( |
| 116 | name, function_name_location, name_is_strict_reserved, kind, |
| 117 | function_token_position, type, arity_restriction, ok); |
| 118 | } |
| 119 | |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 120 | |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 121 | PreParser::PreParseResult PreParser::PreParseLazyFunction( |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 122 | StrictMode strict_mode, bool is_generator, ParserRecorder* log) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 123 | log_ = log; |
| 124 | // Lazy functions always have trivial outer scopes (no with/catch scopes). |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 125 | PreParserScope top_scope(scope_, GLOBAL_SCOPE); |
| 126 | FunctionState top_state(&function_state_, &scope_, &top_scope, NULL, |
| 127 | this->ast_value_factory()); |
| 128 | scope_->SetStrictMode(strict_mode); |
| 129 | PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| 130 | FunctionState function_state(&function_state_, &scope_, &function_scope, NULL, |
| 131 | this->ast_value_factory()); |
| 132 | function_state.set_is_generator(is_generator); |
| 133 | DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 134 | bool ok = true; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 135 | int start_position = peek_position(); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 136 | ParseLazyFunctionLiteralBody(&ok); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 137 | if (stack_overflow()) return kPreParseStackOverflow; |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 138 | if (!ok) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 139 | ReportUnexpectedToken(scanner()->current_token()); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 140 | } else { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 141 | DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| 142 | if (scope_->strict_mode() == STRICT) { |
| 143 | int end_pos = scanner()->location().end_pos; |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 144 | CheckOctalLiteral(start_position, end_pos, &ok); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 145 | } |
| 146 | } |
| 147 | return kPreParseSuccess; |
| 148 | } |
| 149 | |
| 150 | |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 151 | // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 152 | // a later parsing to be faster. |
| 153 | // See preparser-data.h for the data. |
| 154 | |
| 155 | // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 156 | // and collects some information about the program along the way. |
| 157 | // The grammar check is only performed in order to understand the program |
| 158 | // sufficiently to deduce some information about it, that can be used |
| 159 | // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 160 | // rather it is to speed up properly written and correct programs. |
| 161 | // That means that contextual checks (like a label being declared where |
| 162 | // it is used) are generally omitted. |
| 163 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 164 | |
| 165 | #define CHECK_OK ok); \ |
| 166 | if (!*ok) return kUnknownSourceElements; \ |
| 167 | ((void)0 |
| 168 | #define DUMMY ) // to make indentation work |
| 169 | #undef DUMMY |
| 170 | |
| 171 | |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 172 | PreParser::Statement PreParser::ParseSourceElement(bool* ok) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 173 | // (Ecma 262 5th Edition, clause 14): |
| 174 | // SourceElement: |
| 175 | // Statement |
| 176 | // FunctionDeclaration |
| 177 | // |
| 178 | // In harmony mode we allow additionally the following productions |
| 179 | // SourceElement: |
| 180 | // LetDeclaration |
| 181 | // ConstDeclaration |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 182 | // GeneratorDeclaration |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 183 | |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 184 | switch (peek()) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 185 | case Token::FUNCTION: |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 186 | return ParseFunctionDeclaration(ok); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 187 | case Token::CLASS: |
| 188 | return ParseClassDeclaration(ok); |
| 189 | case Token::CONST: |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 190 | return ParseVariableStatement(kSourceElement, ok); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 191 | case Token::LET: |
| 192 | DCHECK(allow_harmony_scoping()); |
| 193 | if (strict_mode() == STRICT) { |
| 194 | return ParseVariableStatement(kSourceElement, ok); |
| 195 | } |
| 196 | // Fall through. |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 197 | default: |
| 198 | return ParseStatement(ok); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 203 | PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
| 204 | bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 205 | // SourceElements :: |
| 206 | // (Statement)* <end_token> |
| 207 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 208 | bool directive_prologue = true; |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 209 | while (peek() != end_token) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 210 | if (directive_prologue && peek() != Token::STRING) { |
| 211 | directive_prologue = false; |
| 212 | } |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 213 | Statement statement = ParseSourceElement(CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 214 | if (directive_prologue) { |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 215 | if (statement.IsUseStrictLiteral()) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 216 | scope_->SetStrictMode(STRICT); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 217 | } else if (!statement.IsStringLiteral()) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 218 | directive_prologue = false; |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 219 | } |
| 220 | } |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 221 | } |
| 222 | return kUnknownSourceElements; |
| 223 | } |
| 224 | |
| 225 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 226 | #undef CHECK_OK |
| 227 | #define CHECK_OK ok); \ |
| 228 | if (!*ok) return Statement::Default(); \ |
| 229 | ((void)0 |
| 230 | #define DUMMY ) // to make indentation work |
| 231 | #undef DUMMY |
| 232 | |
| 233 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 234 | PreParser::Statement PreParser::ParseStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 235 | // Statement :: |
| 236 | // Block |
| 237 | // VariableStatement |
| 238 | // EmptyStatement |
| 239 | // ExpressionStatement |
| 240 | // IfStatement |
| 241 | // IterationStatement |
| 242 | // ContinueStatement |
| 243 | // BreakStatement |
| 244 | // ReturnStatement |
| 245 | // WithStatement |
| 246 | // LabelledStatement |
| 247 | // SwitchStatement |
| 248 | // ThrowStatement |
| 249 | // TryStatement |
| 250 | // DebuggerStatement |
| 251 | |
| 252 | // Note: Since labels can only be used by 'break' and 'continue' |
| 253 | // statements, which themselves are only valid within blocks, |
| 254 | // iterations or 'switch' statements (i.e., BreakableStatements), |
| 255 | // labels can be simply ignored in all other cases; except for |
| 256 | // trivial labeled break statements 'label: break label' which is |
| 257 | // parsed into an empty statement. |
| 258 | |
| 259 | // Keep the source position of the statement |
| 260 | switch (peek()) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 261 | case Token::LBRACE: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 262 | return ParseBlock(ok); |
| 263 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 264 | case Token::SEMICOLON: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 265 | Next(); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 266 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 267 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 268 | case Token::IF: |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 269 | return ParseIfStatement(ok); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 270 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 271 | case Token::DO: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 272 | return ParseDoWhileStatement(ok); |
| 273 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 274 | case Token::WHILE: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 275 | return ParseWhileStatement(ok); |
| 276 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 277 | case Token::FOR: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 278 | return ParseForStatement(ok); |
| 279 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 280 | case Token::CONTINUE: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 281 | return ParseContinueStatement(ok); |
| 282 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 283 | case Token::BREAK: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 284 | return ParseBreakStatement(ok); |
| 285 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 286 | case Token::RETURN: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 287 | return ParseReturnStatement(ok); |
| 288 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 289 | case Token::WITH: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 290 | return ParseWithStatement(ok); |
| 291 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 292 | case Token::SWITCH: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 293 | return ParseSwitchStatement(ok); |
| 294 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 295 | case Token::THROW: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 296 | return ParseThrowStatement(ok); |
| 297 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 298 | case Token::TRY: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 299 | return ParseTryStatement(ok); |
| 300 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 301 | case Token::FUNCTION: { |
| 302 | Scanner::Location start_location = scanner()->peek_location(); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 303 | Statement statement = ParseFunctionDeclaration(CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 304 | Scanner::Location end_location = scanner()->location(); |
| 305 | if (strict_mode() == STRICT) { |
| 306 | PreParserTraits::ReportMessageAt(start_location.beg_pos, |
| 307 | end_location.end_pos, |
| 308 | "strict_function"); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 309 | *ok = false; |
| 310 | return Statement::Default(); |
| 311 | } else { |
| 312 | return statement; |
| 313 | } |
| 314 | } |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 315 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 316 | case Token::CLASS: |
| 317 | return ParseClassDeclaration(CHECK_OK); |
| 318 | |
| 319 | case Token::DEBUGGER: |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 320 | return ParseDebuggerStatement(ok); |
| 321 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 322 | case Token::VAR: |
| 323 | case Token::CONST: |
| 324 | return ParseVariableStatement(kStatement, ok); |
| 325 | |
| 326 | case Token::LET: |
| 327 | DCHECK(allow_harmony_scoping()); |
| 328 | if (strict_mode() == STRICT) { |
| 329 | return ParseVariableStatement(kStatement, ok); |
| 330 | } |
| 331 | // Fall through. |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 332 | default: |
| 333 | return ParseExpressionOrLabelledStatement(ok); |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 338 | PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 339 | // FunctionDeclaration :: |
| 340 | // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 341 | // GeneratorDeclaration :: |
| 342 | // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 343 | // '{' FunctionBody '}' |
| 344 | Expect(Token::FUNCTION, CHECK_OK); |
| 345 | int pos = position(); |
| 346 | bool is_generator = Check(Token::MUL); |
| 347 | bool is_strict_reserved = false; |
| 348 | Identifier name = ParseIdentifierOrStrictReservedWord( |
| 349 | &is_strict_reserved, CHECK_OK); |
| 350 | ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved, |
| 351 | is_generator ? FunctionKind::kGeneratorFunction |
| 352 | : FunctionKind::kNormalFunction, |
| 353 | pos, FunctionLiteral::DECLARATION, |
| 354 | FunctionLiteral::NORMAL_ARITY, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 355 | return Statement::FunctionDeclaration(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 356 | } |
| 357 | |
| 358 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 359 | PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { |
| 360 | Expect(Token::CLASS, CHECK_OK); |
| 361 | int pos = position(); |
| 362 | bool is_strict_reserved = false; |
| 363 | Identifier name = |
| 364 | ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 365 | ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, |
| 366 | CHECK_OK); |
| 367 | return Statement::Default(); |
| 368 | } |
| 369 | |
| 370 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 371 | PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 372 | // Block :: |
| 373 | // '{' Statement* '}' |
| 374 | |
| 375 | // Note that a Block does not introduce a new execution scope! |
| 376 | // (ECMA-262, 3rd, 12.2) |
| 377 | // |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 378 | Expect(Token::LBRACE, CHECK_OK); |
| 379 | while (peek() != Token::RBRACE) { |
| 380 | if (allow_harmony_scoping() && strict_mode() == STRICT) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 381 | ParseSourceElement(CHECK_OK); |
| 382 | } else { |
| 383 | ParseStatement(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 384 | } |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 385 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 386 | Expect(Token::RBRACE, ok); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 387 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 388 | } |
| 389 | |
| 390 | |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 391 | PreParser::Statement PreParser::ParseVariableStatement( |
| 392 | VariableDeclarationContext var_context, |
| 393 | bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 394 | // VariableStatement :: |
| 395 | // VariableDeclarations ';' |
| 396 | |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 397 | Statement result = ParseVariableDeclarations(var_context, |
| 398 | NULL, |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 399 | NULL, |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 400 | CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 401 | ExpectSemicolon(CHECK_OK); |
| 402 | return result; |
| 403 | } |
| 404 | |
| 405 | |
| 406 | // If the variable declaration declares exactly one non-const |
| 407 | // variable, then *var is set to that variable. In all other cases, |
| 408 | // *var is untouched; in particular, it is the caller's responsibility |
| 409 | // to initialize it properly. This mechanism is also used for the parsing |
| 410 | // of 'for-in' loops. |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 411 | PreParser::Statement PreParser::ParseVariableDeclarations( |
| 412 | VariableDeclarationContext var_context, |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 413 | VariableDeclarationProperties* decl_props, |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 414 | int* num_decl, |
| 415 | bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 416 | // VariableDeclarations :: |
| 417 | // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 418 | // |
| 419 | // The ES6 Draft Rev3 specifies the following grammar for const declarations |
| 420 | // |
| 421 | // ConstDeclaration :: |
| 422 | // const ConstBinding (',' ConstBinding)* ';' |
| 423 | // ConstBinding :: |
| 424 | // Identifier '=' AssignmentExpression |
| 425 | // |
| 426 | // TODO(ES6): |
| 427 | // ConstBinding :: |
| 428 | // BindingPattern '=' AssignmentExpression |
| 429 | bool require_initializer = false; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 430 | if (peek() == Token::VAR) { |
| 431 | Consume(Token::VAR); |
| 432 | } else if (peek() == Token::CONST) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 433 | // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
| 434 | // |
| 435 | // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
| 436 | // |
| 437 | // * It is a Syntax Error if the code that matches this production is not |
| 438 | // contained in extended code. |
| 439 | // |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 440 | // However disallowing const in sloppy mode will break compatibility with |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 441 | // existing pages. Therefore we keep allowing const with the old |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 442 | // non-harmony semantics in sloppy mode. |
| 443 | Consume(Token::CONST); |
| 444 | if (strict_mode() == STRICT) { |
| 445 | if (allow_harmony_scoping()) { |
| 446 | if (var_context != kSourceElement && var_context != kForStatement) { |
| 447 | ReportMessageAt(scanner()->peek_location(), "unprotected_const"); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 448 | *ok = false; |
| 449 | return Statement::Default(); |
| 450 | } |
| 451 | require_initializer = true; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 452 | } else { |
| 453 | Scanner::Location location = scanner()->peek_location(); |
| 454 | ReportMessageAt(location, "strict_const"); |
| 455 | *ok = false; |
| 456 | return Statement::Default(); |
| 457 | } |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 458 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 459 | } else if (peek() == Token::LET && strict_mode() == STRICT) { |
| 460 | Consume(Token::LET); |
| 461 | if (var_context != kSourceElement && var_context != kForStatement) { |
| 462 | ReportMessageAt(scanner()->peek_location(), "unprotected_let"); |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 463 | *ok = false; |
| 464 | return Statement::Default(); |
| 465 | } |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 466 | } else { |
| 467 | *ok = false; |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 468 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 469 | } |
| 470 | |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 471 | // The scope of a var/const declared variable anywhere inside a function |
| 472 | // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
| 473 | // of a let declared variable is the scope of the immediately enclosing |
| 474 | // block. |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 475 | int nvars = 0; // the number of variables declared |
| 476 | do { |
| 477 | // Parse variable name. |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 478 | if (nvars > 0) Consume(Token::COMMA); |
| 479 | ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 480 | nvars++; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 481 | if (peek() == Token::ASSIGN || require_initializer) { |
| 482 | Expect(Token::ASSIGN, CHECK_OK); |
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 483 | ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 484 | if (decl_props != NULL) *decl_props = kHasInitializers; |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 485 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 486 | } while (peek() == Token::COMMA); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 487 | |
| 488 | if (num_decl != NULL) *num_decl = nvars; |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 489 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 490 | } |
| 491 | |
| 492 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 493 | PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 494 | // ExpressionStatement | LabelledStatement :: |
| 495 | // Expression ';' |
| 496 | // Identifier ':' Statement |
| 497 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 498 | bool starts_with_identifier = peek_any_identifier(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 499 | Expression expr = ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 500 | // Even if the expression starts with an identifier, it is not necessarily an |
| 501 | // identifier. For example, "foo + bar" starts with an identifier but is not |
| 502 | // an identifier. |
| 503 | if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
| 504 | // Expression is a single identifier, and not, e.g., a parenthesized |
| 505 | // identifier. |
| 506 | DCHECK(!expr.AsIdentifier().IsFutureReserved()); |
| 507 | DCHECK(strict_mode() == SLOPPY || |
| 508 | (!expr.AsIdentifier().IsFutureStrictReserved() && |
| 509 | !expr.AsIdentifier().IsYield())); |
| 510 | Consume(Token::COLON); |
| 511 | return ParseStatement(ok); |
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 512 | // Preparsing is disabled for extensions (because the extension details |
| 513 | // aren't passed to lazily compiled functions), so we don't |
| 514 | // accept "native function" in the preparser. |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 515 | } |
| 516 | // Parsed expression statement. |
| 517 | ExpectSemicolon(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 518 | return Statement::ExpressionStatement(expr); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 519 | } |
| 520 | |
| 521 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 522 | PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 523 | // IfStatement :: |
| 524 | // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 525 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 526 | Expect(Token::IF, CHECK_OK); |
| 527 | Expect(Token::LPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 528 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 529 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 530 | ParseStatement(CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 531 | if (peek() == Token::ELSE) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 532 | Next(); |
| 533 | ParseStatement(CHECK_OK); |
| 534 | } |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 535 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 536 | } |
| 537 | |
| 538 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 539 | PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 540 | // ContinueStatement :: |
| 541 | // 'continue' [no line terminator] Identifier? ';' |
| 542 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 543 | Expect(Token::CONTINUE, CHECK_OK); |
| 544 | Token::Value tok = peek(); |
| 545 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 546 | tok != Token::SEMICOLON && |
| 547 | tok != Token::RBRACE && |
| 548 | tok != Token::EOS) { |
| 549 | // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 550 | ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 551 | } |
| 552 | ExpectSemicolon(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 553 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 554 | } |
| 555 | |
| 556 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 557 | PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 558 | // BreakStatement :: |
| 559 | // 'break' [no line terminator] Identifier? ';' |
| 560 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 561 | Expect(Token::BREAK, CHECK_OK); |
| 562 | Token::Value tok = peek(); |
| 563 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 564 | tok != Token::SEMICOLON && |
| 565 | tok != Token::RBRACE && |
| 566 | tok != Token::EOS) { |
| 567 | // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 568 | ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 569 | } |
| 570 | ExpectSemicolon(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 571 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 572 | } |
| 573 | |
| 574 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 575 | PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 576 | // ReturnStatement :: |
| 577 | // 'return' [no line terminator] Expression? ';' |
| 578 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 579 | // Consume the return token. It is necessary to do before |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 580 | // reporting any errors on it, because of the way errors are |
| 581 | // reported (underlining). |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 582 | Expect(Token::RETURN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 583 | |
| 584 | // An ECMAScript program is considered syntactically incorrect if it |
| 585 | // contains a return statement that is not within the body of a |
| 586 | // function. See ECMA-262, section 12.9, page 67. |
| 587 | // This is not handled during preparsing. |
| 588 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 589 | Token::Value tok = peek(); |
| 590 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 591 | tok != Token::SEMICOLON && |
| 592 | tok != Token::RBRACE && |
| 593 | tok != Token::EOS) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 594 | ParseExpression(true, CHECK_OK); |
| 595 | } |
| 596 | ExpectSemicolon(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 597 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 598 | } |
| 599 | |
| 600 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 601 | PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 602 | // WithStatement :: |
| 603 | // 'with' '(' Expression ')' Statement |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 604 | Expect(Token::WITH, CHECK_OK); |
| 605 | if (strict_mode() == STRICT) { |
| 606 | ReportMessageAt(scanner()->location(), "strict_mode_with"); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 607 | *ok = false; |
| 608 | return Statement::Default(); |
| 609 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 610 | Expect(Token::LPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 611 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 612 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 613 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 614 | PreParserScope with_scope(scope_, WITH_SCOPE); |
| 615 | BlockState block_state(&scope_, &with_scope); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 616 | ParseStatement(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 617 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 618 | } |
| 619 | |
| 620 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 621 | PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 622 | // SwitchStatement :: |
| 623 | // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 624 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 625 | Expect(Token::SWITCH, CHECK_OK); |
| 626 | Expect(Token::LPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 627 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 628 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 629 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 630 | Expect(Token::LBRACE, CHECK_OK); |
| 631 | Token::Value token = peek(); |
| 632 | while (token != Token::RBRACE) { |
| 633 | if (token == Token::CASE) { |
| 634 | Expect(Token::CASE, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 635 | ParseExpression(true, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 636 | } else { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 637 | Expect(Token::DEFAULT, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 638 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 639 | Expect(Token::COLON, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 640 | token = peek(); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 641 | while (token != Token::CASE && |
| 642 | token != Token::DEFAULT && |
| 643 | token != Token::RBRACE) { |
| 644 | ParseStatement(CHECK_OK); |
| 645 | token = peek(); |
| 646 | } |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 647 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 648 | Expect(Token::RBRACE, ok); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 649 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 650 | } |
| 651 | |
| 652 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 653 | PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 654 | // DoStatement :: |
| 655 | // 'do' Statement 'while' '(' Expression ')' ';' |
| 656 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 657 | Expect(Token::DO, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 658 | ParseStatement(CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 659 | Expect(Token::WHILE, CHECK_OK); |
| 660 | Expect(Token::LPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 661 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 662 | Expect(Token::RPAREN, ok); |
| 663 | if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 664 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 665 | } |
| 666 | |
| 667 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 668 | PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 669 | // WhileStatement :: |
| 670 | // 'while' '(' Expression ')' Statement |
| 671 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 672 | Expect(Token::WHILE, CHECK_OK); |
| 673 | Expect(Token::LPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 674 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 675 | Expect(Token::RPAREN, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 676 | ParseStatement(ok); |
| 677 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 678 | } |
| 679 | |
| 680 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 681 | bool PreParser::CheckInOrOf(bool accept_OF) { |
| 682 | if (Check(Token::IN) || |
| 683 | (accept_OF && CheckContextualKeyword(CStrVector("of")))) { |
| 684 | return true; |
| 685 | } |
| 686 | return false; |
| 687 | } |
| 688 | |
| 689 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 690 | PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 691 | // ForStatement :: |
| 692 | // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 693 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 694 | Expect(Token::FOR, CHECK_OK); |
| 695 | Expect(Token::LPAREN, CHECK_OK); |
| 696 | if (peek() != Token::SEMICOLON) { |
| 697 | if (peek() == Token::VAR || peek() == Token::CONST || |
| 698 | (peek() == Token::LET && strict_mode() == STRICT)) { |
| 699 | bool is_let = peek() == Token::LET; |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 700 | int decl_count; |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 701 | VariableDeclarationProperties decl_props = kHasNoInitializers; |
| 702 | ParseVariableDeclarations( |
| 703 | kForStatement, &decl_props, &decl_count, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 704 | bool has_initializers = decl_props == kHasInitializers; |
| 705 | bool accept_IN = decl_count == 1 && !(is_let && has_initializers); |
| 706 | bool accept_OF = !has_initializers; |
| 707 | if (accept_IN && CheckInOrOf(accept_OF)) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 708 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 709 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 710 | |
| 711 | ParseStatement(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 712 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 713 | } |
| 714 | } else { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 715 | Expression lhs = ParseExpression(false, CHECK_OK); |
| 716 | if (CheckInOrOf(lhs.IsIdentifier())) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 717 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 718 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 719 | |
| 720 | ParseStatement(CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 721 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 722 | } |
| 723 | } |
| 724 | } |
| 725 | |
| 726 | // Parsed initializer at this point. |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 727 | Expect(Token::SEMICOLON, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 728 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 729 | if (peek() != Token::SEMICOLON) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 730 | ParseExpression(true, CHECK_OK); |
| 731 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 732 | Expect(Token::SEMICOLON, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 733 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 734 | if (peek() != Token::RPAREN) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 735 | ParseExpression(true, CHECK_OK); |
| 736 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 737 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 738 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 739 | ParseStatement(ok); |
| 740 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 741 | } |
| 742 | |
| 743 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 744 | PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 745 | // ThrowStatement :: |
| 746 | // 'throw' [no line terminator] Expression ';' |
| 747 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 748 | Expect(Token::THROW, CHECK_OK); |
| 749 | if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 750 | ReportMessageAt(scanner()->location(), "newline_after_throw"); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 751 | *ok = false; |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 752 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 753 | } |
| 754 | ParseExpression(true, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 755 | ExpectSemicolon(ok); |
| 756 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 757 | } |
| 758 | |
| 759 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 760 | PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 761 | // TryStatement :: |
| 762 | // 'try' Block Catch |
| 763 | // 'try' Block Finally |
| 764 | // 'try' Block Catch Finally |
| 765 | // |
| 766 | // Catch :: |
| 767 | // 'catch' '(' Identifier ')' Block |
| 768 | // |
| 769 | // Finally :: |
| 770 | // 'finally' Block |
| 771 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 772 | Expect(Token::TRY, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 773 | |
| 774 | ParseBlock(CHECK_OK); |
| 775 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 776 | Token::Value tok = peek(); |
| 777 | if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 778 | ReportMessageAt(scanner()->location(), "no_catch_or_finally"); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 779 | *ok = false; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 780 | return Statement::Default(); |
| 781 | } |
| 782 | if (tok == Token::CATCH) { |
| 783 | Consume(Token::CATCH); |
| 784 | Expect(Token::LPAREN, CHECK_OK); |
| 785 | ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 786 | Expect(Token::RPAREN, CHECK_OK); |
| 787 | { |
| 788 | PreParserScope with_scope(scope_, WITH_SCOPE); |
| 789 | BlockState block_state(&scope_, &with_scope); |
| 790 | ParseBlock(CHECK_OK); |
| 791 | } |
| 792 | tok = peek(); |
| 793 | } |
| 794 | if (tok == Token::FINALLY) { |
| 795 | Consume(Token::FINALLY); |
| 796 | ParseBlock(CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 797 | } |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 798 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 799 | } |
| 800 | |
| 801 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 802 | PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 803 | // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 804 | // contexts this is used as a statement which invokes the debugger as if a |
| 805 | // break point is present. |
| 806 | // DebuggerStatement :: |
| 807 | // 'debugger' ';' |
| 808 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 809 | Expect(Token::DEBUGGER, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 810 | ExpectSemicolon(ok); |
| 811 | return Statement::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 812 | } |
| 813 | |
| 814 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 815 | #undef CHECK_OK |
| 816 | #define CHECK_OK ok); \ |
| 817 | if (!*ok) return Expression::Default(); \ |
| 818 | ((void)0 |
| 819 | #define DUMMY ) // to make indentation work |
| 820 | #undef DUMMY |
| 821 | |
| 822 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 823 | PreParser::Expression PreParser::ParseFunctionLiteral( |
| 824 | Identifier function_name, Scanner::Location function_name_location, |
| 825 | bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, |
| 826 | FunctionLiteral::FunctionType function_type, |
| 827 | FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 828 | // Function :: |
| 829 | // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 830 | |
| 831 | // Parse function body. |
| 832 | ScopeType outer_scope_type = scope_->type(); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 833 | PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| 834 | FunctionState function_state(&function_state_, &scope_, &function_scope, NULL, |
| 835 | this->ast_value_factory()); |
| 836 | function_state.set_is_generator(IsGeneratorFunction(kind)); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 837 | // FormalParameterList :: |
| 838 | // '(' (Identifier)*[','] ')' |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 839 | Expect(Token::LPAREN, CHECK_OK); |
| 840 | int start_position = position(); |
| 841 | DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
| 842 | // We don't yet know if the function will be strict, so we cannot yet produce |
| 843 | // errors for parameter names or duplicates. However, we remember the |
| 844 | // locations of these errors if they occur and produce the errors later. |
| 845 | Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
| 846 | Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
| 847 | Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
| 848 | |
| 849 | bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || |
| 850 | (peek() == Token::RPAREN && |
| 851 | arity_restriction != FunctionLiteral::SETTER_ARITY); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 852 | while (!done) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 853 | bool is_strict_reserved = false; |
| 854 | Identifier param_name = |
| 855 | ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 856 | if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { |
| 857 | eval_args_error_loc = scanner()->location(); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 858 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 859 | if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
| 860 | reserved_error_loc = scanner()->location(); |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 861 | } |
| 862 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 863 | int prev_value = scanner()->FindSymbol(&duplicate_finder, 1); |
| 864 | |
| 865 | if (!dupe_error_loc.IsValid() && prev_value != 0) { |
| 866 | dupe_error_loc = scanner()->location(); |
| Ben Murdoch | 589d697 | 2011-11-30 16:04:58 +0000 | [diff] [blame] | 867 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 868 | |
| 869 | if (arity_restriction == FunctionLiteral::SETTER_ARITY) break; |
| 870 | done = (peek() == Token::RPAREN); |
| 871 | if (!done) Expect(Token::COMMA, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 872 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 873 | Expect(Token::RPAREN, CHECK_OK); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 874 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 875 | // See Parser::ParseFunctionLiteral for more information about lazy parsing |
| 876 | // and lazy compilation. |
| 877 | bool is_lazily_parsed = (outer_scope_type == GLOBAL_SCOPE && allow_lazy() && |
| 878 | !parenthesized_function_); |
| Ben Murdoch | b8e0da2 | 2011-05-16 14:20:40 +0100 | [diff] [blame] | 879 | parenthesized_function_ = false; |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 880 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 881 | Expect(Token::LBRACE, CHECK_OK); |
| 882 | if (is_lazily_parsed) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 883 | ParseLazyFunctionLiteralBody(CHECK_OK); |
| Ben Murdoch | 85b7179 | 2012-04-11 18:30:58 +0100 | [diff] [blame] | 884 | } else { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 885 | ParseSourceElements(Token::RBRACE, ok); |
| Ben Murdoch | 85b7179 | 2012-04-11 18:30:58 +0100 | [diff] [blame] | 886 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 887 | Expect(Token::RBRACE, CHECK_OK); |
| Ben Murdoch | 85b7179 | 2012-04-11 18:30:58 +0100 | [diff] [blame] | 888 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 889 | // Validate strict mode. We can do this only after parsing the function, |
| 890 | // since the function can declare itself strict. |
| 891 | // Concise methods use StrictFormalParameters. |
| 892 | if (strict_mode() == STRICT || IsConciseMethod(kind)) { |
| 893 | if (function_name.IsEvalOrArguments()) { |
| 894 | ReportMessageAt(function_name_location, "strict_eval_arguments"); |
| 895 | *ok = false; |
| 896 | return Expression::Default(); |
| 897 | } |
| 898 | if (name_is_strict_reserved) { |
| 899 | ReportMessageAt(function_name_location, "unexpected_strict_reserved"); |
| 900 | *ok = false; |
| 901 | return Expression::Default(); |
| 902 | } |
| 903 | if (eval_args_error_loc.IsValid()) { |
| 904 | ReportMessageAt(eval_args_error_loc, "strict_eval_arguments"); |
| 905 | *ok = false; |
| 906 | return Expression::Default(); |
| 907 | } |
| 908 | if (dupe_error_loc.IsValid()) { |
| 909 | ReportMessageAt(dupe_error_loc, "strict_param_dupe"); |
| 910 | *ok = false; |
| 911 | return Expression::Default(); |
| 912 | } |
| 913 | if (reserved_error_loc.IsValid()) { |
| 914 | ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved"); |
| 915 | *ok = false; |
| 916 | return Expression::Default(); |
| 917 | } |
| 918 | |
| 919 | int end_position = scanner()->location().end_pos; |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 920 | CheckOctalLiteral(start_position, end_position, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 921 | } |
| 922 | |
| 923 | return Expression::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 924 | } |
| 925 | |
| 926 | |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 927 | void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 928 | int body_start = position(); |
| 929 | ParseSourceElements(Token::RBRACE, ok); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 930 | if (!*ok) return; |
| 931 | |
| 932 | // Position right after terminal '}'. |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 933 | DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| 934 | int body_end = scanner()->peek_location().end_pos; |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 935 | log_->LogFunction(body_start, body_end, |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 936 | function_state_->materialized_literal_count(), |
| 937 | function_state_->expected_property_count(), |
| 938 | strict_mode()); |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 939 | } |
| 940 | |
| 941 | |
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 942 | PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 943 | // CallRuntime :: |
| 944 | // '%' Identifier Arguments |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 945 | Expect(Token::MOD, CHECK_OK); |
| 946 | if (!allow_natives_syntax()) { |
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame] | 947 | *ok = false; |
| 948 | return Expression::Default(); |
| 949 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 950 | // Allow "eval" or "arguments" for backward compatibility. |
| 951 | ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 952 | ParseArguments(ok); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 953 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 954 | return Expression::Default(); |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 955 | } |
| 956 | |
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 957 | #undef CHECK_OK |
| 958 | |
| Shimeng (Simon) Wang | 8a31eba | 2010-12-06 19:01:33 -0800 | [diff] [blame] | 959 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 960 | } } // v8::internal |