yangguo@chromium.org | ab30bb8 | 2012-02-24 14:41:46 +0000 | [diff] [blame] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #ifndef V8_PREPARSER_H |
| 29 | #define V8_PREPARSER_H |
| 30 | |
yangguo@chromium.org | ab30bb8 | 2012-02-24 14:41:46 +0000 | [diff] [blame] | 31 | #include "hashmap.h" |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 32 | #include "token.h" |
| 33 | #include "scanner.h" |
| 34 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 35 | namespace v8 { |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 36 | namespace internal { |
mvstanton@chromium.org | dd6d9ee | 2013-10-11 10:35:37 +0000 | [diff] [blame] | 37 | |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 38 | // Common base class shared between parser and pre-parser. |
| 39 | class ParserBase { |
| 40 | public: |
| 41 | ParserBase(Scanner* scanner, uintptr_t stack_limit) |
| 42 | : scanner_(scanner), |
| 43 | stack_limit_(stack_limit), |
| 44 | stack_overflow_(false), |
| 45 | allow_lazy_(false), |
| 46 | allow_natives_syntax_(false), |
| 47 | allow_generators_(false), |
| 48 | allow_for_of_(false) { } |
| 49 | // TODO(mstarzinger): Only virtual until message reporting has been unified. |
| 50 | virtual ~ParserBase() { } |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 51 | |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 52 | // Getters that indicate whether certain syntactical constructs are |
| 53 | // allowed to be parsed by this instance of the parser. |
| 54 | bool allow_lazy() const { return allow_lazy_; } |
| 55 | bool allow_natives_syntax() const { return allow_natives_syntax_; } |
| 56 | bool allow_generators() const { return allow_generators_; } |
| 57 | bool allow_for_of() const { return allow_for_of_; } |
| 58 | bool allow_modules() const { return scanner()->HarmonyModules(); } |
| 59 | bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); } |
| 60 | bool allow_harmony_numeric_literals() const { |
| 61 | return scanner()->HarmonyNumericLiterals(); |
| 62 | } |
| 63 | |
| 64 | // Setters that determine whether certain syntactical constructs are |
| 65 | // allowed to be parsed by this instance of the parser. |
| 66 | void set_allow_lazy(bool allow) { allow_lazy_ = allow; } |
| 67 | void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; } |
| 68 | void set_allow_generators(bool allow) { allow_generators_ = allow; } |
| 69 | void set_allow_for_of(bool allow) { allow_for_of_ = allow; } |
| 70 | void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); } |
| 71 | void set_allow_harmony_scoping(bool allow) { |
| 72 | scanner()->SetHarmonyScoping(allow); |
| 73 | } |
| 74 | void set_allow_harmony_numeric_literals(bool allow) { |
| 75 | scanner()->SetHarmonyNumericLiterals(allow); |
| 76 | } |
| 77 | |
| 78 | protected: |
| 79 | Scanner* scanner() const { return scanner_; } |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 80 | int position() { return scanner_->location().beg_pos; } |
| 81 | int peek_position() { return scanner_->peek_location().beg_pos; } |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 82 | bool stack_overflow() const { return stack_overflow_; } |
| 83 | void set_stack_overflow() { stack_overflow_ = true; } |
| 84 | |
| 85 | INLINE(Token::Value peek()) { |
| 86 | if (stack_overflow_) return Token::ILLEGAL; |
| 87 | return scanner()->peek(); |
| 88 | } |
| 89 | |
| 90 | INLINE(Token::Value Next()) { |
| 91 | if (stack_overflow_) return Token::ILLEGAL; |
| 92 | { |
| 93 | int marker; |
| 94 | if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) { |
| 95 | // Any further calls to Next or peek will return the illegal token. |
| 96 | // The current call must return the next token, which might already |
| 97 | // have been peek'ed. |
| 98 | stack_overflow_ = true; |
| 99 | } |
| 100 | } |
| 101 | return scanner()->Next(); |
| 102 | } |
| 103 | |
| 104 | void Consume(Token::Value token) { |
| 105 | Token::Value next = Next(); |
| 106 | USE(next); |
| 107 | USE(token); |
| 108 | ASSERT(next == token); |
| 109 | } |
| 110 | |
| 111 | bool Check(Token::Value token) { |
| 112 | Token::Value next = peek(); |
| 113 | if (next == token) { |
| 114 | Consume(next); |
| 115 | return true; |
| 116 | } |
| 117 | return false; |
| 118 | } |
| 119 | |
| 120 | void Expect(Token::Value token, bool* ok) { |
| 121 | Token::Value next = Next(); |
| 122 | if (next != token) { |
| 123 | ReportUnexpectedToken(next); |
| 124 | *ok = false; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | bool peek_any_identifier(); |
| 129 | void ExpectSemicolon(bool* ok); |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 130 | bool CheckContextualKeyword(Vector<const char> keyword); |
| 131 | void ExpectContextualKeyword(Vector<const char> keyword, bool* ok); |
| 132 | |
| 133 | // Strict mode octal literal validation. |
| 134 | void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok); |
| 135 | |
| 136 | // Determine precedence of given token. |
| 137 | static int Precedence(Token::Value token, bool accept_IN); |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 138 | |
| 139 | // Report syntax errors. |
| 140 | virtual void ReportUnexpectedToken(Token::Value token) = 0; |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 141 | virtual void ReportMessageAt(Scanner::Location loc, const char* type) = 0; |
| 142 | |
| 143 | // Used to detect duplicates in object literals. Each of the values |
| 144 | // kGetterProperty, kSetterProperty and kValueProperty represents |
| 145 | // a type of object literal property. When parsing a property, its |
| 146 | // type value is stored in the DuplicateFinder for the property name. |
| 147 | // Values are chosen so that having intersection bits means the there is |
| 148 | // an incompatibility. |
| 149 | // I.e., you can add a getter to a property that already has a setter, since |
| 150 | // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
| 151 | // already has a getter or a value. Adding the getter to an existing |
| 152 | // setter will store the value (kGetterProperty | kSetterProperty), which |
| 153 | // is incompatible with adding any further properties. |
| 154 | enum PropertyKind { |
| 155 | kNone = 0, |
| 156 | // Bit patterns representing different object literal property types. |
| 157 | kGetterProperty = 1, |
| 158 | kSetterProperty = 2, |
| 159 | kValueProperty = 7, |
| 160 | // Helper constants. |
| 161 | kValueFlag = 4 |
| 162 | }; |
| 163 | |
| 164 | // Validation per ECMA 262 - 11.1.5 "Object Initialiser". |
| 165 | class ObjectLiteralChecker { |
| 166 | public: |
| 167 | ObjectLiteralChecker(ParserBase* parser, LanguageMode mode) |
| 168 | : parser_(parser), |
| 169 | finder_(scanner()->unicode_cache()), |
| 170 | language_mode_(mode) { } |
| 171 | |
| 172 | void CheckProperty(Token::Value property, PropertyKind type, bool* ok); |
| 173 | |
| 174 | private: |
| 175 | ParserBase* parser() const { return parser_; } |
| 176 | Scanner* scanner() const { return parser_->scanner(); } |
| 177 | |
| 178 | // Checks the type of conflict based on values coming from PropertyType. |
| 179 | bool HasConflict(PropertyKind type1, PropertyKind type2) { |
| 180 | return (type1 & type2) != 0; |
| 181 | } |
| 182 | bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { |
| 183 | return ((type1 & type2) & kValueFlag) != 0; |
| 184 | } |
| 185 | bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { |
| 186 | return ((type1 ^ type2) & kValueFlag) != 0; |
| 187 | } |
| 188 | bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { |
| 189 | return ((type1 | type2) & kValueFlag) == 0; |
| 190 | } |
| 191 | |
| 192 | ParserBase* parser_; |
| 193 | DuplicateFinder finder_; |
| 194 | LanguageMode language_mode_; |
| 195 | }; |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 196 | |
| 197 | private: |
| 198 | Scanner* scanner_; |
| 199 | uintptr_t stack_limit_; |
| 200 | bool stack_overflow_; |
| 201 | |
| 202 | bool allow_lazy_; |
| 203 | bool allow_natives_syntax_; |
| 204 | bool allow_generators_; |
| 205 | bool allow_for_of_; |
| 206 | }; |
| 207 | |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 208 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 209 | // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 210 | // a later parsing to be faster. |
lrn@chromium.org | 1c09276 | 2011-05-09 09:42:16 +0000 | [diff] [blame] | 211 | // See preparse-data-format.h for the data format. |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 212 | |
| 213 | // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 214 | // and collects some information about the program along the way. |
| 215 | // The grammar check is only performed in order to understand the program |
| 216 | // sufficiently to deduce some information about it, that can be used |
| 217 | // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 218 | // rather it is to speed up properly written and correct programs. |
| 219 | // That means that contextual checks (like a label being declared where |
| 220 | // it is used) are generally omitted. |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 221 | class PreParser : public ParserBase { |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 222 | public: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 223 | enum PreParseResult { |
| 224 | kPreParseStackOverflow, |
| 225 | kPreParseSuccess |
| 226 | }; |
| 227 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 228 | PreParser(Scanner* scanner, |
| 229 | ParserRecorder* log, |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 230 | uintptr_t stack_limit) |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 231 | : ParserBase(scanner, stack_limit), |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 232 | log_(log), |
| 233 | scope_(NULL), |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 234 | strict_mode_violation_location_(Scanner::Location::invalid()), |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 235 | strict_mode_violation_type_(NULL), |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 236 | parenthesized_function_(false) { } |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 237 | |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 238 | ~PreParser() {} |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 239 | |
| 240 | // Pre-parse the program from the character stream; returns true on |
| 241 | // success (even if parsing failed, the pre-parse data successfully |
| 242 | // captured the syntax error), and false if a stack-overflow happened |
| 243 | // during parsing. |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 244 | PreParseResult PreParseProgram() { |
| 245 | Scope top_scope(&scope_, kTopLevelScope); |
| 246 | bool ok = true; |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 247 | int start_position = scanner()->peek_location().beg_pos; |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 248 | ParseSourceElements(Token::EOS, &ok); |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 249 | if (stack_overflow()) return kPreParseStackOverflow; |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 250 | if (!ok) { |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 251 | ReportUnexpectedToken(scanner()->current_token()); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 252 | } else if (!scope_->is_classic_mode()) { |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 253 | CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 254 | } |
| 255 | return kPreParseSuccess; |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 256 | } |
| 257 | |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 258 | // Parses a single function literal, from the opening parentheses before |
| 259 | // parameters to the closing brace after the body. |
rossberg@chromium.org | cddc71f | 2012-12-07 12:40:13 +0000 | [diff] [blame] | 260 | // Returns a FunctionEntry describing the body of the function in enough |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 261 | // detail that it can be lazily compiled. |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 262 | // The scanner is expected to have matched the "function" or "function*" |
| 263 | // keyword and parameters, and have consumed the initial '{'. |
rossberg@chromium.org | cddc71f | 2012-12-07 12:40:13 +0000 | [diff] [blame] | 264 | // At return, unless an error occurred, the scanner is positioned before the |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 265 | // the final '}'. |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 266 | PreParseResult PreParseLazyFunction(LanguageMode mode, |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 267 | bool is_generator, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 268 | ParserRecorder* log); |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 269 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 270 | private: |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 271 | // These types form an algebra over syntactic categories that is just |
| 272 | // rich enough to let us recognize and propagate the constructs that |
| 273 | // are either being counted in the preparser data, or is important |
| 274 | // to throw the correct syntax error exceptions. |
| 275 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 276 | enum ScopeType { |
| 277 | kTopLevelScope, |
| 278 | kFunctionScope |
| 279 | }; |
| 280 | |
danno@chromium.org | b645116 | 2011-08-17 14:33:23 +0000 | [diff] [blame] | 281 | enum VariableDeclarationContext { |
| 282 | kSourceElement, |
| 283 | kStatement, |
| 284 | kForStatement |
| 285 | }; |
| 286 | |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 287 | // If a list of variable declarations includes any initializers. |
| 288 | enum VariableDeclarationProperties { |
| 289 | kHasInitializers, |
| 290 | kHasNoInitializers |
| 291 | }; |
| 292 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 293 | class Expression; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 294 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 295 | class Identifier { |
| 296 | public: |
| 297 | static Identifier Default() { |
| 298 | return Identifier(kUnknownIdentifier); |
| 299 | } |
| 300 | static Identifier Eval() { |
| 301 | return Identifier(kEvalIdentifier); |
| 302 | } |
| 303 | static Identifier Arguments() { |
| 304 | return Identifier(kArgumentsIdentifier); |
| 305 | } |
| 306 | static Identifier FutureReserved() { |
| 307 | return Identifier(kFutureReservedIdentifier); |
| 308 | } |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 309 | static Identifier FutureStrictReserved() { |
| 310 | return Identifier(kFutureStrictReservedIdentifier); |
| 311 | } |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 312 | static Identifier Yield() { |
| 313 | return Identifier(kYieldIdentifier); |
| 314 | } |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 315 | bool IsEval() { return type_ == kEvalIdentifier; } |
| 316 | bool IsArguments() { return type_ == kArgumentsIdentifier; } |
| 317 | bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 318 | bool IsYield() { return type_ == kYieldIdentifier; } |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 319 | bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 320 | bool IsFutureStrictReserved() { |
| 321 | return type_ == kFutureStrictReservedIdentifier; |
| 322 | } |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 323 | bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } |
jkummerow@chromium.org | e297f59 | 2011-06-08 10:05:15 +0000 | [diff] [blame] | 324 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 325 | private: |
| 326 | enum Type { |
| 327 | kUnknownIdentifier, |
| 328 | kFutureReservedIdentifier, |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 329 | kFutureStrictReservedIdentifier, |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 330 | kYieldIdentifier, |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 331 | kEvalIdentifier, |
| 332 | kArgumentsIdentifier |
| 333 | }; |
| 334 | explicit Identifier(Type type) : type_(type) { } |
| 335 | Type type_; |
| 336 | |
| 337 | friend class Expression; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 338 | }; |
| 339 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 340 | // Bits 0 and 1 are used to identify the type of expression: |
| 341 | // If bit 0 is set, it's an identifier. |
| 342 | // if bit 1 is set, it's a string literal. |
| 343 | // If neither is set, it's no particular type, and both set isn't |
| 344 | // use yet. |
| 345 | // Bit 2 is used to mark the expression as being parenthesized, |
| 346 | // so "(foo)" isn't recognized as a pure identifier (and possible label). |
| 347 | class Expression { |
| 348 | public: |
| 349 | static Expression Default() { |
| 350 | return Expression(kUnknownExpression); |
| 351 | } |
| 352 | |
| 353 | static Expression FromIdentifier(Identifier id) { |
| 354 | return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift)); |
| 355 | } |
| 356 | |
| 357 | static Expression StringLiteral() { |
| 358 | return Expression(kUnknownStringLiteral); |
| 359 | } |
| 360 | |
| 361 | static Expression UseStrictStringLiteral() { |
| 362 | return Expression(kUseStrictString); |
| 363 | } |
| 364 | |
| 365 | static Expression This() { |
| 366 | return Expression(kThisExpression); |
| 367 | } |
| 368 | |
| 369 | static Expression ThisProperty() { |
| 370 | return Expression(kThisPropertyExpression); |
| 371 | } |
| 372 | |
| 373 | static Expression StrictFunction() { |
| 374 | return Expression(kStrictFunctionExpression); |
| 375 | } |
| 376 | |
| 377 | bool IsIdentifier() { |
| 378 | return (code_ & kIdentifierFlag) != 0; |
| 379 | } |
| 380 | |
| 381 | // Only works corretly if it is actually an identifier expression. |
| 382 | PreParser::Identifier AsIdentifier() { |
| 383 | return PreParser::Identifier( |
| 384 | static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); |
| 385 | } |
| 386 | |
| 387 | bool IsParenthesized() { |
| 388 | // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized. |
| 389 | return (code_ & 7) > 4; |
| 390 | } |
| 391 | |
| 392 | bool IsRawIdentifier() { |
| 393 | return !IsParenthesized() && IsIdentifier(); |
| 394 | } |
| 395 | |
| 396 | bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } |
| 397 | |
| 398 | bool IsRawStringLiteral() { |
| 399 | return !IsParenthesized() && IsStringLiteral(); |
| 400 | } |
| 401 | |
| 402 | bool IsUseStrictLiteral() { |
| 403 | return (code_ & kStringLiteralMask) == kUseStrictString; |
| 404 | } |
| 405 | |
| 406 | bool IsThis() { |
| 407 | return code_ == kThisExpression; |
| 408 | } |
| 409 | |
| 410 | bool IsThisProperty() { |
| 411 | return code_ == kThisPropertyExpression; |
| 412 | } |
| 413 | |
| 414 | bool IsStrictFunction() { |
| 415 | return code_ == kStrictFunctionExpression; |
| 416 | } |
| 417 | |
| 418 | Expression Parenthesize() { |
| 419 | int type = code_ & 3; |
| 420 | if (type != 0) { |
| 421 | // Identifiers and string literals can be parenthesized. |
| 422 | // They no longer work as labels or directive prologues, |
| 423 | // but are still recognized in other contexts. |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 424 | return Expression(code_ | kParenthesizedExpressionFlag); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 425 | } |
| 426 | // For other types of expressions, it's not important to remember |
| 427 | // the parentheses. |
| 428 | return *this; |
| 429 | } |
| 430 | |
| 431 | private: |
| 432 | // First two/three bits are used as flags. |
| 433 | // Bit 0 and 1 represent identifiers or strings literals, and are |
| 434 | // mutually exclusive, but can both be absent. |
| 435 | // If bit 0 or 1 are set, bit 2 marks that the expression has |
| 436 | // been wrapped in parentheses (a string literal can no longer |
| 437 | // be a directive prologue, and an identifier can no longer be |
| 438 | // a label. |
| 439 | enum { |
| 440 | kUnknownExpression = 0, |
| 441 | // Identifiers |
| 442 | kIdentifierFlag = 1, // Used to detect labels. |
| 443 | kIdentifierShift = 3, |
| 444 | |
| 445 | kStringLiteralFlag = 2, // Used to detect directive prologue. |
| 446 | kUnknownStringLiteral = kStringLiteralFlag, |
| 447 | kUseStrictString = kStringLiteralFlag | 8, |
| 448 | kStringLiteralMask = kUseStrictString, |
| 449 | |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 450 | // Only if identifier or string literal. |
| 451 | kParenthesizedExpressionFlag = 4, |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 452 | |
| 453 | // Below here applies if neither identifier nor string literal. |
| 454 | kThisExpression = 4, |
| 455 | kThisPropertyExpression = 8, |
| 456 | kStrictFunctionExpression = 12 |
| 457 | }; |
| 458 | |
| 459 | explicit Expression(int expression_code) : code_(expression_code) { } |
| 460 | |
| 461 | int code_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 462 | }; |
| 463 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 464 | class Statement { |
| 465 | public: |
| 466 | static Statement Default() { |
| 467 | return Statement(kUnknownStatement); |
| 468 | } |
| 469 | |
danno@chromium.org | 40cb878 | 2011-05-25 07:58:50 +0000 | [diff] [blame] | 470 | static Statement FunctionDeclaration() { |
| 471 | return Statement(kFunctionDeclaration); |
| 472 | } |
| 473 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 474 | // Creates expression statement from expression. |
| 475 | // Preserves being an unparenthesized string literal, possibly |
| 476 | // "use strict". |
| 477 | static Statement ExpressionStatement(Expression expression) { |
| 478 | if (!expression.IsParenthesized()) { |
| 479 | if (expression.IsUseStrictLiteral()) { |
| 480 | return Statement(kUseStrictExpressionStatement); |
| 481 | } |
| 482 | if (expression.IsStringLiteral()) { |
| 483 | return Statement(kStringLiteralExpressionStatement); |
| 484 | } |
| 485 | } |
| 486 | return Default(); |
| 487 | } |
| 488 | |
| 489 | bool IsStringLiteral() { |
mstarzinger@chromium.org | 2efc3e4 | 2013-10-14 08:45:38 +0000 | [diff] [blame] | 490 | return code_ == kStringLiteralExpressionStatement; |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 491 | } |
| 492 | |
| 493 | bool IsUseStrictLiteral() { |
| 494 | return code_ == kUseStrictExpressionStatement; |
| 495 | } |
| 496 | |
danno@chromium.org | 40cb878 | 2011-05-25 07:58:50 +0000 | [diff] [blame] | 497 | bool IsFunctionDeclaration() { |
| 498 | return code_ == kFunctionDeclaration; |
| 499 | } |
| 500 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 501 | private: |
| 502 | enum Type { |
| 503 | kUnknownStatement, |
| 504 | kStringLiteralExpressionStatement, |
danno@chromium.org | 40cb878 | 2011-05-25 07:58:50 +0000 | [diff] [blame] | 505 | kUseStrictExpressionStatement, |
| 506 | kFunctionDeclaration |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 507 | }; |
| 508 | |
| 509 | explicit Statement(Type code) : code_(code) {} |
| 510 | Type code_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 511 | }; |
| 512 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 513 | enum SourceElements { |
| 514 | kUnknownSourceElements |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 515 | }; |
| 516 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 517 | typedef int Arguments; |
| 518 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 519 | class Scope { |
| 520 | public: |
| 521 | Scope(Scope** variable, ScopeType type) |
| 522 | : variable_(variable), |
| 523 | prev_(*variable), |
| 524 | type_(type), |
| 525 | materialized_literal_count_(0), |
| 526 | expected_properties_(0), |
lrn@chromium.org | 1c09276 | 2011-05-09 09:42:16 +0000 | [diff] [blame] | 527 | with_nesting_count_(0), |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 528 | language_mode_( |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 529 | (prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE), |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 530 | is_generator_(false) { |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 531 | *variable = this; |
| 532 | } |
| 533 | ~Scope() { *variable_ = prev_; } |
| 534 | void NextMaterializedLiteralIndex() { materialized_literal_count_++; } |
| 535 | void AddProperty() { expected_properties_++; } |
| 536 | ScopeType type() { return type_; } |
| 537 | int expected_properties() { return expected_properties_; } |
| 538 | int materialized_literal_count() { return materialized_literal_count_; } |
| 539 | bool IsInsideWith() { return with_nesting_count_ != 0; } |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 540 | bool is_generator() { return is_generator_; } |
| 541 | void set_is_generator(bool is_generator) { is_generator_ = is_generator; } |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 542 | bool is_classic_mode() { |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 543 | return language_mode_ == CLASSIC_MODE; |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 544 | } |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 545 | LanguageMode language_mode() { |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 546 | return language_mode_; |
| 547 | } |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 548 | void set_language_mode(LanguageMode language_mode) { |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 549 | language_mode_ = language_mode; |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 550 | } |
danno@chromium.org | 2c26cb1 | 2012-05-03 09:06:43 +0000 | [diff] [blame] | 551 | |
| 552 | class InsideWith { |
| 553 | public: |
| 554 | explicit InsideWith(Scope* scope) : scope_(scope) { |
| 555 | scope->with_nesting_count_++; |
| 556 | } |
| 557 | |
| 558 | ~InsideWith() { scope_->with_nesting_count_--; } |
| 559 | |
| 560 | private: |
| 561 | Scope* scope_; |
| 562 | DISALLOW_COPY_AND_ASSIGN(InsideWith); |
| 563 | }; |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 564 | |
| 565 | private: |
| 566 | Scope** const variable_; |
| 567 | Scope* const prev_; |
| 568 | const ScopeType type_; |
| 569 | int materialized_literal_count_; |
| 570 | int expected_properties_; |
| 571 | int with_nesting_count_; |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 572 | LanguageMode language_mode_; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 573 | bool is_generator_; |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 574 | }; |
| 575 | |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 576 | // Report syntax error |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 577 | void ReportUnexpectedToken(Token::Value token); |
| 578 | void ReportMessageAt(Scanner::Location location, const char* type) { |
| 579 | ReportMessageAt(location, type, NULL); |
| 580 | } |
| 581 | void ReportMessageAt(Scanner::Location location, |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 582 | const char* type, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 583 | const char* name_opt) { |
ricow@chromium.org | 55ee807 | 2011-09-08 16:33:10 +0000 | [diff] [blame] | 584 | log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt); |
| 585 | } |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 586 | void ReportMessageAt(int start_pos, |
| 587 | int end_pos, |
| 588 | const char* type, |
| 589 | const char* name_opt) { |
| 590 | log_->LogMessage(start_pos, end_pos, type, name_opt); |
| 591 | } |
| 592 | |
| 593 | // All ParseXXX functions take as the last argument an *ok parameter |
| 594 | // which is set to false if parsing failed; it is unchanged otherwise. |
| 595 | // By making the 'exception handling' explicit, we are forced to check |
| 596 | // for failure at the call sites. |
danno@chromium.org | b645116 | 2011-08-17 14:33:23 +0000 | [diff] [blame] | 597 | Statement ParseSourceElement(bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 598 | SourceElements ParseSourceElements(int end_token, bool* ok); |
| 599 | Statement ParseStatement(bool* ok); |
| 600 | Statement ParseFunctionDeclaration(bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 601 | Statement ParseBlock(bool* ok); |
danno@chromium.org | b645116 | 2011-08-17 14:33:23 +0000 | [diff] [blame] | 602 | Statement ParseVariableStatement(VariableDeclarationContext var_context, |
| 603 | bool* ok); |
| 604 | Statement ParseVariableDeclarations(VariableDeclarationContext var_context, |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 605 | VariableDeclarationProperties* decl_props, |
danno@chromium.org | b645116 | 2011-08-17 14:33:23 +0000 | [diff] [blame] | 606 | int* num_decl, |
| 607 | bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 608 | Statement ParseExpressionOrLabelledStatement(bool* ok); |
| 609 | Statement ParseIfStatement(bool* ok); |
| 610 | Statement ParseContinueStatement(bool* ok); |
| 611 | Statement ParseBreakStatement(bool* ok); |
| 612 | Statement ParseReturnStatement(bool* ok); |
| 613 | Statement ParseWithStatement(bool* ok); |
| 614 | Statement ParseSwitchStatement(bool* ok); |
| 615 | Statement ParseDoWhileStatement(bool* ok); |
| 616 | Statement ParseWhileStatement(bool* ok); |
| 617 | Statement ParseForStatement(bool* ok); |
| 618 | Statement ParseThrowStatement(bool* ok); |
| 619 | Statement ParseTryStatement(bool* ok); |
| 620 | Statement ParseDebuggerStatement(bool* ok); |
| 621 | |
| 622 | Expression ParseExpression(bool accept_IN, bool* ok); |
| 623 | Expression ParseAssignmentExpression(bool accept_IN, bool* ok); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 624 | Expression ParseYieldExpression(bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 625 | Expression ParseConditionalExpression(bool accept_IN, bool* ok); |
| 626 | Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok); |
| 627 | Expression ParseUnaryExpression(bool* ok); |
| 628 | Expression ParsePostfixExpression(bool* ok); |
| 629 | Expression ParseLeftHandSideExpression(bool* ok); |
| 630 | Expression ParseNewExpression(bool* ok); |
| 631 | Expression ParseMemberExpression(bool* ok); |
whesse@chromium.org | f0ac72d | 2010-11-08 12:47:26 +0000 | [diff] [blame] | 632 | Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 633 | Expression ParsePrimaryExpression(bool* ok); |
| 634 | Expression ParseArrayLiteral(bool* ok); |
| 635 | Expression ParseObjectLiteral(bool* ok); |
| 636 | Expression ParseRegExpLiteral(bool seen_equal, bool* ok); |
| 637 | Expression ParseV8Intrinsic(bool* ok); |
| 638 | |
| 639 | Arguments ParseArguments(bool* ok); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 640 | Expression ParseFunctionLiteral(bool is_generator, bool* ok); |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 641 | void ParseLazyFunctionLiteralBody(bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 642 | |
| 643 | Identifier ParseIdentifier(bool* ok); |
| 644 | Identifier ParseIdentifierName(bool* ok); |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 645 | Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 646 | bool* is_set, |
| 647 | bool* ok); |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 648 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 649 | // Logs the currently parsed literal as a symbol in the preparser data. |
| 650 | void LogSymbol(); |
| 651 | // Log the currently parsed identifier. |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 652 | Identifier GetIdentifierSymbol(); |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 653 | // Log the currently parsed string literal. |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 654 | Expression GetStringSymbol(); |
| 655 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 656 | void set_language_mode(LanguageMode language_mode) { |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 657 | scope_->set_language_mode(language_mode); |
lrn@chromium.org | 1c09276 | 2011-05-09 09:42:16 +0000 | [diff] [blame] | 658 | } |
| 659 | |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 660 | bool is_classic_mode() { |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 661 | return scope_->language_mode() == CLASSIC_MODE; |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 662 | } |
erik.corry@gmail.com | 6e28b56 | 2011-10-27 14:20:17 +0000 | [diff] [blame] | 663 | |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 664 | bool is_extended_mode() { |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 665 | return scope_->language_mode() == EXTENDED_MODE; |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 666 | } |
| 667 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 668 | LanguageMode language_mode() { return scope_->language_mode(); } |
lrn@chromium.org | 1c09276 | 2011-05-09 09:42:16 +0000 | [diff] [blame] | 669 | |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 670 | bool CheckInOrOf(bool accept_OF); |
danno@chromium.org | 1fd77d5 | 2013-06-07 16:01:45 +0000 | [diff] [blame] | 671 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 672 | void SetStrictModeViolation(Scanner::Location, |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 673 | const char* type, |
erik.corry@gmail.com | f2038fb | 2012-01-16 11:42:08 +0000 | [diff] [blame] | 674 | bool* ok); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 675 | |
| 676 | void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); |
| 677 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 678 | void StrictModeIdentifierViolation(Scanner::Location, |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 679 | const char* eval_args_type, |
| 680 | Identifier identifier, |
| 681 | bool* ok); |
| 682 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 683 | ParserRecorder* log_; |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 684 | Scope* scope_; |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame^] | 685 | Scanner::Location strict_mode_violation_location_; |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 686 | const char* strict_mode_violation_type_; |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 687 | bool parenthesized_function_; |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 688 | }; |
mvstanton@chromium.org | dd6d9ee | 2013-10-11 10:35:37 +0000 | [diff] [blame] | 689 | |
mstarzinger@chromium.org | a2e1a40 | 2013-10-15 08:25:05 +0000 | [diff] [blame] | 690 | } } // v8::internal |
lrn@chromium.org | fa943b7 | 2010-11-03 08:14:36 +0000 | [diff] [blame] | 691 | |
| 692 | #endif // V8_PREPARSER_H |