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 lables or directive prologues, | |
Mads Ager (chromium)
2011/05/18 13:20:48
lables -> labels
Lasse Reichstein
2011/05/19 09:00:31
Done.
| |
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 |