OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 // captured the syntax error), and false if a stack-overflow happened | 60 // captured the syntax error), and false if a stack-overflow happened |
61 // during parsing. | 61 // during parsing. |
62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, | 62 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner, |
63 i::ParserRecorder* log, | 63 i::ParserRecorder* log, |
64 bool allow_lazy, | 64 bool allow_lazy, |
65 uintptr_t stack_limit) { | 65 uintptr_t stack_limit) { |
66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); | 66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse(); |
67 } | 67 } |
68 | 68 |
69 private: | 69 private: |
| 70 // These types form an algebra over syntactic categories that is just |
| 71 // rich enough to let us recognize and propagate the constructs that |
| 72 // are either being counted in the preparser data, or is important |
| 73 // to throw the correct syntax error exceptions. |
| 74 |
70 enum ScopeType { | 75 enum ScopeType { |
71 kTopLevelScope, | 76 kTopLevelScope, |
72 kFunctionScope | 77 kFunctionScope |
73 }; | 78 }; |
74 | 79 |
75 // Types that allow us to recognize simple this-property assignments. | 80 class Expression; |
76 // A simple this-property assignment is a statement on the form | 81 |
77 // "this.propertyName = {primitive constant or function parameter name);" | 82 class Identifier { |
78 // where propertyName isn't "__proto__". | 83 public: |
79 // The result is only relevant if the function body contains only | 84 static Identifier Default() { |
80 // simple this-property assignments. | 85 return Identifier(kUnknownIdentifier); |
81 | 86 } |
82 enum StatementType { | 87 static Identifier Eval() { |
83 kUnknownStatement, | 88 return Identifier(kEvalIdentifier); |
84 kStringLiteralExpressionStatement, | 89 } |
85 kUseStrictExpressionStatement | 90 static Identifier Arguments() { |
86 }; | 91 return Identifier(kArgumentsIdentifier); |
87 | 92 } |
88 enum ExpressionType { | 93 static Identifier FutureReserved() { |
89 kUnknownExpression, | 94 return Identifier(kFutureReservedIdentifier); |
90 kIdentifierExpression, // Used to detect labels. | 95 } |
91 kThisExpression, | 96 bool IsEval() { return type_ == kEvalIdentifier; } |
92 kThisPropertyExpression, | 97 bool IsArguments() { return type_ == kArgumentsIdentifier; } |
93 kStringLiteralExpression, | 98 bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; } |
94 kUseStrictString | 99 bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; } |
95 }; | 100 bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; } |
96 | 101 private: |
97 enum IdentifierType { | 102 enum Type { |
98 kUnknownIdentifier | 103 kUnknownIdentifier, |
99 }; | 104 kFutureReservedIdentifier, |
100 | 105 kEvalIdentifier, |
101 enum SourceElementTypes { | 106 kArgumentsIdentifier |
102 kUnknownSourceElements, | 107 }; |
103 kDirectivePrologue, | 108 explicit Identifier(Type type) : type_(type) { } |
104 kUseStrictDirective | 109 Type type_; |
105 }; | 110 |
106 | 111 friend class Expression; |
107 typedef int SourceElements; | 112 }; |
108 typedef int Expression; | 113 |
109 typedef int Statement; | 114 // Bits 0 and 1 are used to identify the type of expression: |
110 typedef int Identifier; | 115 // If bit 0 is set, it's an identifier. |
| 116 // if bit 1 is set, it's a string literal. |
| 117 // If neither is set, it's no particular type, and both set isn't |
| 118 // use yet. |
| 119 // Bit 2 is used to mark the expression as being parenthesized, |
| 120 // so "(foo)" isn't recognized as a pure identifier (and possible label). |
| 121 class Expression { |
| 122 public: |
| 123 static Expression Default() { |
| 124 return Expression(kUnknownExpression); |
| 125 } |
| 126 |
| 127 static Expression Identifier(Identifier id) { |
| 128 return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift)); |
| 129 } |
| 130 |
| 131 static Expression StringLiteral() { |
| 132 return Expression(kUnknownStringLiteral); |
| 133 } |
| 134 |
| 135 static Expression UseStrictStringLiteral() { |
| 136 return Expression(kUseStrictString); |
| 137 } |
| 138 |
| 139 static Expression This() { |
| 140 return Expression(kThisExpression); |
| 141 } |
| 142 |
| 143 static Expression ThisProperty() { |
| 144 return Expression(kThisPropertyExpression); |
| 145 } |
| 146 |
| 147 static Expression StrictFunction() { |
| 148 return Expression(kStrictFunctionExpression); |
| 149 } |
| 150 |
| 151 bool IsIdentifier() { |
| 152 return (code_ & kIdentifierFlag) != 0; |
| 153 } |
| 154 |
| 155 // Only works corretly if it is actually an identifier expression. |
| 156 PreParser::Identifier AsIdentifier() { |
| 157 return PreParser::Identifier( |
| 158 static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); |
| 159 } |
| 160 |
| 161 bool IsParenthesized() { |
| 162 // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized. |
| 163 return (code_ & 7) > 4; |
| 164 } |
| 165 |
| 166 bool IsRawIdentifier() { |
| 167 return !IsParenthesized() && IsIdentifier(); |
| 168 } |
| 169 |
| 170 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } |
| 171 |
| 172 bool IsRawStringLiteral() { |
| 173 return !IsParenthesized() && IsStringLiteral(); |
| 174 } |
| 175 |
| 176 bool IsUseStrictLiteral() { |
| 177 return (code_ & kStringLiteralMask) == kUseStrictString; |
| 178 } |
| 179 |
| 180 bool IsThis() { |
| 181 return code_ == kThisExpression; |
| 182 } |
| 183 |
| 184 bool IsThisProperty() { |
| 185 return code_ == kThisPropertyExpression; |
| 186 } |
| 187 |
| 188 bool IsStrictFunction() { |
| 189 return code_ == kStrictFunctionExpression; |
| 190 } |
| 191 |
| 192 Expression Parenthesize() { |
| 193 int type = code_ & 3; |
| 194 if (type != 0) { |
| 195 // Identifiers and string literals can be parenthesized. |
| 196 // They no longer work as labels or directive prologues, |
| 197 // but are still recognized in other contexts. |
| 198 return Expression(code_ | kParentesizedExpressionFlag); |
| 199 } |
| 200 // For other types of expressions, it's not important to remember |
| 201 // the parentheses. |
| 202 return *this; |
| 203 } |
| 204 |
| 205 private: |
| 206 // First two/three bits are used as flags. |
| 207 // Bit 0 and 1 represent identifiers or strings literals, and are |
| 208 // mutually exclusive, but can both be absent. |
| 209 // If bit 0 or 1 are set, bit 2 marks that the expression has |
| 210 // been wrapped in parentheses (a string literal can no longer |
| 211 // be a directive prologue, and an identifier can no longer be |
| 212 // a label. |
| 213 enum { |
| 214 kUnknownExpression = 0, |
| 215 // Identifiers |
| 216 kIdentifierFlag = 1, // Used to detect labels. |
| 217 kIdentifierShift = 3, |
| 218 |
| 219 kStringLiteralFlag = 2, // Used to detect directive prologue. |
| 220 kUnknownStringLiteral = kStringLiteralFlag, |
| 221 kUseStrictString = kStringLiteralFlag | 8, |
| 222 kStringLiteralMask = kUseStrictString, |
| 223 |
| 224 kParentesizedExpressionFlag = 4, // Only if identifier or string literal. |
| 225 |
| 226 // Below here applies if neither identifier nor string literal. |
| 227 kThisExpression = 4, |
| 228 kThisPropertyExpression = 8, |
| 229 kStrictFunctionExpression = 12 |
| 230 }; |
| 231 |
| 232 explicit Expression(int expression_code) : code_(expression_code) { } |
| 233 |
| 234 int code_; |
| 235 }; |
| 236 |
| 237 class Statement { |
| 238 public: |
| 239 static Statement Default() { |
| 240 return Statement(kUnknownStatement); |
| 241 } |
| 242 |
| 243 // Creates expression statement from expression. |
| 244 // Preserves being an unparenthesized string literal, possibly |
| 245 // "use strict". |
| 246 static Statement ExpressionStatement(Expression expression) { |
| 247 if (!expression.IsParenthesized()) { |
| 248 if (expression.IsUseStrictLiteral()) { |
| 249 return Statement(kUseStrictExpressionStatement); |
| 250 } |
| 251 if (expression.IsStringLiteral()) { |
| 252 return Statement(kStringLiteralExpressionStatement); |
| 253 } |
| 254 } |
| 255 return Default(); |
| 256 } |
| 257 |
| 258 bool IsStringLiteral() { |
| 259 return code_ != kUnknownStatement; |
| 260 } |
| 261 |
| 262 bool IsUseStrictLiteral() { |
| 263 return code_ == kUseStrictExpressionStatement; |
| 264 } |
| 265 |
| 266 private: |
| 267 enum Type { |
| 268 kUnknownStatement, |
| 269 kStringLiteralExpressionStatement, |
| 270 kUseStrictExpressionStatement |
| 271 }; |
| 272 |
| 273 explicit Statement(Type code) : code_(code) {} |
| 274 Type code_; |
| 275 }; |
| 276 |
| 277 enum SourceElements { |
| 278 kUnknownSourceElements |
| 279 }; |
| 280 |
111 typedef int Arguments; | 281 typedef int Arguments; |
112 | 282 |
113 class Scope { | 283 class Scope { |
114 public: | 284 public: |
115 Scope(Scope** variable, ScopeType type) | 285 Scope(Scope** variable, ScopeType type) |
116 : variable_(variable), | 286 : variable_(variable), |
117 prev_(*variable), | 287 prev_(*variable), |
118 type_(type), | 288 type_(type), |
119 materialized_literal_count_(0), | 289 materialized_literal_count_(0), |
120 expected_properties_(0), | 290 expected_properties_(0), |
(...skipping 25 matching lines...) Expand all Loading... |
146 | 316 |
147 // Private constructor only used in PreParseProgram. | 317 // Private constructor only used in PreParseProgram. |
148 PreParser(i::JavaScriptScanner* scanner, | 318 PreParser(i::JavaScriptScanner* scanner, |
149 i::ParserRecorder* log, | 319 i::ParserRecorder* log, |
150 uintptr_t stack_limit, | 320 uintptr_t stack_limit, |
151 bool allow_lazy) | 321 bool allow_lazy) |
152 : scanner_(scanner), | 322 : scanner_(scanner), |
153 log_(log), | 323 log_(log), |
154 scope_(NULL), | 324 scope_(NULL), |
155 stack_limit_(stack_limit), | 325 stack_limit_(stack_limit), |
| 326 strict_mode_violation_location_(i::Scanner::Location::invalid()), |
| 327 strict_mode_violation_type_(NULL), |
156 stack_overflow_(false), | 328 stack_overflow_(false), |
157 allow_lazy_(true), | 329 allow_lazy_(true), |
158 parenthesized_function_(false) { } | 330 parenthesized_function_(false) { } |
159 | 331 |
160 // Preparse the program. Only called in PreParseProgram after creating | 332 // Preparse the program. Only called in PreParseProgram after creating |
161 // the instance. | 333 // the instance. |
162 PreParseResult PreParse() { | 334 PreParseResult PreParse() { |
163 Scope top_scope(&scope_, kTopLevelScope); | 335 Scope top_scope(&scope_, kTopLevelScope); |
164 bool ok = true; | 336 bool ok = true; |
165 int start_position = scanner_->peek_location().beg_pos; | 337 int start_position = scanner_->peek_location().beg_pos; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } | 429 } |
258 return scanner_->Next(); | 430 return scanner_->Next(); |
259 } | 431 } |
260 | 432 |
261 bool peek_any_identifier(); | 433 bool peek_any_identifier(); |
262 | 434 |
263 void set_strict_mode() { | 435 void set_strict_mode() { |
264 scope_->set_strict(); | 436 scope_->set_strict(); |
265 } | 437 } |
266 | 438 |
267 bool is_strict_mode() { return scope_->is_strict(); } | 439 bool strict_mode() { return scope_->is_strict(); } |
268 | 440 |
269 void Consume(i::Token::Value token) { Next(); } | 441 void Consume(i::Token::Value token) { Next(); } |
270 | 442 |
271 void Expect(i::Token::Value token, bool* ok) { | 443 void Expect(i::Token::Value token, bool* ok) { |
272 if (Next() != token) { | 444 if (Next() != token) { |
273 *ok = false; | 445 *ok = false; |
274 } | 446 } |
275 } | 447 } |
276 | 448 |
277 bool Check(i::Token::Value token) { | 449 bool Check(i::Token::Value token) { |
278 i::Token::Value next = peek(); | 450 i::Token::Value next = peek(); |
279 if (next == token) { | 451 if (next == token) { |
280 Consume(next); | 452 Consume(next); |
281 return true; | 453 return true; |
282 } | 454 } |
283 return false; | 455 return false; |
284 } | 456 } |
285 void ExpectSemicolon(bool* ok); | 457 void ExpectSemicolon(bool* ok); |
286 | 458 |
287 static int Precedence(i::Token::Value tok, bool accept_IN); | 459 static int Precedence(i::Token::Value tok, bool accept_IN); |
288 | 460 |
| 461 void SetStrictModeViolation(i::Scanner::Location, |
| 462 const char* type, |
| 463 bool *ok); |
| 464 |
| 465 void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); |
| 466 |
| 467 void StrictModeIdentifierViolation(i::Scanner::Location, |
| 468 const char* eval_args_type, |
| 469 Identifier identifier, |
| 470 bool* ok); |
| 471 |
289 i::JavaScriptScanner* scanner_; | 472 i::JavaScriptScanner* scanner_; |
290 i::ParserRecorder* log_; | 473 i::ParserRecorder* log_; |
291 Scope* scope_; | 474 Scope* scope_; |
292 uintptr_t stack_limit_; | 475 uintptr_t stack_limit_; |
| 476 i::Scanner::Location strict_mode_violation_location_; |
| 477 const char* strict_mode_violation_type_; |
293 bool stack_overflow_; | 478 bool stack_overflow_; |
294 bool allow_lazy_; | 479 bool allow_lazy_; |
295 bool parenthesized_function_; | 480 bool parenthesized_function_; |
296 }; | 481 }; |
297 } } // v8::preparser | 482 } } // v8::preparser |
298 | 483 |
299 #endif // V8_PREPARSER_H | 484 #endif // V8_PREPARSER_H |
OLD | NEW |