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 15 matching lines...) Expand all Loading... |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
30 | 30 |
31 namespace v8 { | 31 namespace v8 { |
32 namespace preparser { | 32 namespace preparser { |
33 | 33 |
34 // Preparsing checks a JavaScript program and emits preparse-data that helps | 34 // Preparsing checks a JavaScript program and emits preparse-data that helps |
35 // a later parsing to be faster. | 35 // a later parsing to be faster. |
36 // See preparse-data.h for the data. | 36 // See preparse-data-format.h for the data format. |
37 | 37 |
38 // The PreParser checks that the syntax follows the grammar for JavaScript, | 38 // The PreParser checks that the syntax follows the grammar for JavaScript, |
39 // and collects some information about the program along the way. | 39 // and collects some information about the program along the way. |
40 // The grammar check is only performed in order to understand the program | 40 // The grammar check is only performed in order to understand the program |
41 // sufficiently to deduce some information about it, that can be used | 41 // sufficiently to deduce some information about it, that can be used |
42 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 42 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
43 // rather it is to speed up properly written and correct programs. | 43 // rather it is to speed up properly written and correct programs. |
44 // That means that contextual checks (like a label being declared where | 44 // That means that contextual checks (like a label being declared where |
45 // it is used) are generally omitted. | 45 // it is used) are generally omitted. |
46 | 46 |
(...skipping 26 matching lines...) Expand all Loading... |
73 }; | 73 }; |
74 | 74 |
75 // Types that allow us to recognize simple this-property assignments. | 75 // Types that allow us to recognize simple this-property assignments. |
76 // A simple this-property assignment is a statement on the form | 76 // A simple this-property assignment is a statement on the form |
77 // "this.propertyName = {primitive constant or function parameter name);" | 77 // "this.propertyName = {primitive constant or function parameter name);" |
78 // where propertyName isn't "__proto__". | 78 // where propertyName isn't "__proto__". |
79 // The result is only relevant if the function body contains only | 79 // The result is only relevant if the function body contains only |
80 // simple this-property assignments. | 80 // simple this-property assignments. |
81 | 81 |
82 enum StatementType { | 82 enum StatementType { |
83 kUnknownStatement | 83 kUnknownStatement, |
| 84 kStringLiteralExpressionStatement, |
| 85 kUseStrictExpressionStatement |
84 }; | 86 }; |
85 | 87 |
86 enum ExpressionType { | 88 enum ExpressionType { |
87 kUnknownExpression, | 89 kUnknownExpression, |
88 kIdentifierExpression, // Used to detect labels. | 90 kIdentifierExpression, // Used to detect labels. |
89 kThisExpression, | 91 kThisExpression, |
90 kThisPropertyExpression | 92 kThisPropertyExpression, |
| 93 kStringLiteralExpression, |
| 94 kUseStrictString |
91 }; | 95 }; |
92 | 96 |
93 enum IdentifierType { | 97 enum IdentifierType { |
94 kUnknownIdentifier | 98 kUnknownIdentifier |
95 }; | 99 }; |
96 | 100 |
97 enum SourceElementTypes { | 101 enum SourceElementTypes { |
98 kUnknownSourceElements | 102 kUnknownSourceElements, |
| 103 kDirectivePrologue, |
| 104 kUseStrictDirective |
99 }; | 105 }; |
100 | 106 |
101 typedef int SourceElements; | 107 typedef int SourceElements; |
102 typedef int Expression; | 108 typedef int Expression; |
103 typedef int Statement; | 109 typedef int Statement; |
104 typedef int Identifier; | 110 typedef int Identifier; |
105 typedef int Arguments; | 111 typedef int Arguments; |
106 | 112 |
107 class Scope { | 113 class Scope { |
108 public: | 114 public: |
109 Scope(Scope** variable, ScopeType type) | 115 Scope(Scope** variable, ScopeType type) |
110 : variable_(variable), | 116 : variable_(variable), |
111 prev_(*variable), | 117 prev_(*variable), |
112 type_(type), | 118 type_(type), |
113 materialized_literal_count_(0), | 119 materialized_literal_count_(0), |
114 expected_properties_(0), | 120 expected_properties_(0), |
115 with_nesting_count_(0) { | 121 with_nesting_count_(0), |
| 122 strict_((prev_ != NULL) && prev_->is_strict()) { |
116 *variable = this; | 123 *variable = this; |
117 } | 124 } |
118 ~Scope() { *variable_ = prev_; } | 125 ~Scope() { *variable_ = prev_; } |
119 void NextMaterializedLiteralIndex() { materialized_literal_count_++; } | 126 void NextMaterializedLiteralIndex() { materialized_literal_count_++; } |
120 void AddProperty() { expected_properties_++; } | 127 void AddProperty() { expected_properties_++; } |
121 ScopeType type() { return type_; } | 128 ScopeType type() { return type_; } |
122 int expected_properties() { return expected_properties_; } | 129 int expected_properties() { return expected_properties_; } |
123 int materialized_literal_count() { return materialized_literal_count_; } | 130 int materialized_literal_count() { return materialized_literal_count_; } |
124 bool IsInsideWith() { return with_nesting_count_ != 0; } | 131 bool IsInsideWith() { return with_nesting_count_ != 0; } |
| 132 bool is_strict() { return strict_; } |
| 133 void set_strict() { strict_ = true; } |
125 void EnterWith() { with_nesting_count_++; } | 134 void EnterWith() { with_nesting_count_++; } |
126 void LeaveWith() { with_nesting_count_--; } | 135 void LeaveWith() { with_nesting_count_--; } |
127 | 136 |
128 private: | 137 private: |
129 Scope** const variable_; | 138 Scope** const variable_; |
130 Scope* const prev_; | 139 Scope* const prev_; |
131 const ScopeType type_; | 140 const ScopeType type_; |
132 int materialized_literal_count_; | 141 int materialized_literal_count_; |
133 int expected_properties_; | 142 int expected_properties_; |
134 int with_nesting_count_; | 143 int with_nesting_count_; |
| 144 bool strict_; |
135 }; | 145 }; |
136 | 146 |
137 // Private constructor only used in PreParseProgram. | 147 // Private constructor only used in PreParseProgram. |
138 PreParser(i::JavaScriptScanner* scanner, | 148 PreParser(i::JavaScriptScanner* scanner, |
139 i::ParserRecorder* log, | 149 i::ParserRecorder* log, |
140 uintptr_t stack_limit, | 150 uintptr_t stack_limit, |
141 bool allow_lazy) | 151 bool allow_lazy) |
142 : scanner_(scanner), | 152 : scanner_(scanner), |
143 log_(log), | 153 log_(log), |
144 scope_(NULL), | 154 scope_(NULL), |
145 stack_limit_(stack_limit), | 155 stack_limit_(stack_limit), |
146 stack_overflow_(false), | 156 stack_overflow_(false), |
147 allow_lazy_(true), | 157 allow_lazy_(true), |
148 parenthesized_function_(false) { } | 158 parenthesized_function_(false) { } |
149 | 159 |
150 // Preparse the program. Only called in PreParseProgram after creating | 160 // Preparse the program. Only called in PreParseProgram after creating |
151 // the instance. | 161 // the instance. |
152 PreParseResult PreParse() { | 162 PreParseResult PreParse() { |
153 Scope top_scope(&scope_, kTopLevelScope); | 163 Scope top_scope(&scope_, kTopLevelScope); |
154 bool ok = true; | 164 bool ok = true; |
| 165 int start_position = scanner_->peek_location().beg_pos; |
155 ParseSourceElements(i::Token::EOS, &ok); | 166 ParseSourceElements(i::Token::EOS, &ok); |
156 if (stack_overflow_) return kPreParseStackOverflow; | 167 if (stack_overflow_) return kPreParseStackOverflow; |
157 if (!ok) { | 168 if (!ok) { |
158 ReportUnexpectedToken(scanner_->current_token()); | 169 ReportUnexpectedToken(scanner_->current_token()); |
| 170 } else if (scope_->is_strict()) { |
| 171 CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok); |
159 } | 172 } |
160 return kPreParseSuccess; | 173 return kPreParseSuccess; |
161 } | 174 } |
162 | 175 |
163 // Report syntax error | 176 // Report syntax error |
164 void ReportUnexpectedToken(i::Token::Value token); | 177 void ReportUnexpectedToken(i::Token::Value token); |
165 void ReportMessageAt(int start_pos, | 178 void ReportMessageAt(int start_pos, |
166 int end_pos, | 179 int end_pos, |
167 const char* type, | 180 const char* type, |
168 const char* name_opt) { | 181 const char* name_opt) { |
169 log_->LogMessage(start_pos, end_pos, type, name_opt); | 182 log_->LogMessage(start_pos, end_pos, type, name_opt); |
170 } | 183 } |
171 | 184 |
| 185 void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok); |
| 186 |
172 // All ParseXXX functions take as the last argument an *ok parameter | 187 // All ParseXXX functions take as the last argument an *ok parameter |
173 // which is set to false if parsing failed; it is unchanged otherwise. | 188 // which is set to false if parsing failed; it is unchanged otherwise. |
174 // By making the 'exception handling' explicit, we are forced to check | 189 // By making the 'exception handling' explicit, we are forced to check |
175 // for failure at the call sites. | 190 // for failure at the call sites. |
176 SourceElements ParseSourceElements(int end_token, bool* ok); | 191 SourceElements ParseSourceElements(int end_token, bool* ok); |
177 Statement ParseStatement(bool* ok); | 192 Statement ParseStatement(bool* ok); |
178 Statement ParseFunctionDeclaration(bool* ok); | 193 Statement ParseFunctionDeclaration(bool* ok); |
179 Statement ParseNativeDeclaration(bool* ok); | 194 Statement ParseNativeDeclaration(bool* ok); |
180 Statement ParseBlock(bool* ok); | 195 Statement ParseBlock(bool* ok); |
181 Statement ParseVariableStatement(bool* ok); | 196 Statement ParseVariableStatement(bool* ok); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 // The current one will still be returned. It might already | 253 // The current one will still be returned. It might already |
239 // have been seen using peek. | 254 // have been seen using peek. |
240 stack_overflow_ = true; | 255 stack_overflow_ = true; |
241 } | 256 } |
242 } | 257 } |
243 return scanner_->Next(); | 258 return scanner_->Next(); |
244 } | 259 } |
245 | 260 |
246 bool peek_any_identifier(); | 261 bool peek_any_identifier(); |
247 | 262 |
| 263 void set_strict_mode() { |
| 264 scope_->set_strict(); |
| 265 } |
| 266 |
| 267 bool is_strict_mode() { return scope_->is_strict(); } |
| 268 |
248 void Consume(i::Token::Value token) { Next(); } | 269 void Consume(i::Token::Value token) { Next(); } |
249 | 270 |
250 void Expect(i::Token::Value token, bool* ok) { | 271 void Expect(i::Token::Value token, bool* ok) { |
251 if (Next() != token) { | 272 if (Next() != token) { |
252 *ok = false; | 273 *ok = false; |
253 } | 274 } |
254 } | 275 } |
255 | 276 |
256 bool Check(i::Token::Value token) { | 277 bool Check(i::Token::Value token) { |
257 i::Token::Value next = peek(); | 278 i::Token::Value next = peek(); |
(...skipping 11 matching lines...) Expand all Loading... |
269 i::ParserRecorder* log_; | 290 i::ParserRecorder* log_; |
270 Scope* scope_; | 291 Scope* scope_; |
271 uintptr_t stack_limit_; | 292 uintptr_t stack_limit_; |
272 bool stack_overflow_; | 293 bool stack_overflow_; |
273 bool allow_lazy_; | 294 bool allow_lazy_; |
274 bool parenthesized_function_; | 295 bool parenthesized_function_; |
275 }; | 296 }; |
276 } } // v8::preparser | 297 } } // v8::preparser |
277 | 298 |
278 #endif // V8_PREPARSER_H | 299 #endif // V8_PREPARSER_H |
OLD | NEW |