blob: b7fa6c73bd4db1eb6c9be286df86576a58758758 [file] [log] [blame]
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001// Copyright 2010 the V8 project authors. All rights reserved.
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
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080031namespace v8 {
32namespace preparser {
33
34// Preparsing checks a JavaScript program and emits preparse-data that helps
35// a later parsing to be faster.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080036// See preparse-data.h for the data.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080037
38// The PreParser checks that the syntax follows the grammar for JavaScript,
39// and collects some information about the program along the way.
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
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.
44// That means that contextual checks (like a label being declared where
45// it is used) are generally omitted.
46
47namespace i = v8::internal;
48
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080049class PreParser {
50 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +010051 enum PreParseResult {
52 kPreParseStackOverflow,
53 kPreParseSuccess
54 };
55
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080056 ~PreParser() { }
57
58 // Pre-parse the program from the character stream; returns true on
59 // success (even if parsing failed, the pre-parse data successfully
60 // captured the syntax error), and false if a stack-overflow happened
61 // during parsing.
Ben Murdochb0fe1622011-05-05 13:52:32 +010062 static PreParseResult PreParseProgram(i::JavaScriptScanner* scanner,
63 i::ParserRecorder* log,
64 bool allow_lazy,
65 uintptr_t stack_limit) {
66 return PreParser(scanner, log, stack_limit, allow_lazy).PreParse();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080067 }
68
69 private:
70 enum ScopeType {
71 kTopLevelScope,
72 kFunctionScope
73 };
74
Ben Murdochb0fe1622011-05-05 13:52:32 +010075 // Types that allow us to recognize simple this-property assignments.
76 // A simple this-property assignment is a statement on the form
77 // "this.propertyName = {primitive constant or function parameter name);"
78 // where propertyName isn't "__proto__".
79 // The result is only relevant if the function body contains only
80 // simple this-property assignments.
81
82 enum StatementType {
83 kUnknownStatement
84 };
85
86 enum ExpressionType {
87 kUnknownExpression,
88 kIdentifierExpression, // Used to detect labels.
89 kThisExpression,
90 kThisPropertyExpression
91 };
92
93 enum IdentifierType {
94 kUnknownIdentifier
95 };
96
97 enum SourceElementTypes {
98 kUnknownSourceElements
99 };
100
101 typedef int SourceElements;
102 typedef int Expression;
103 typedef int Statement;
104 typedef int Identifier;
105 typedef int Arguments;
106
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800107 class Scope {
108 public:
109 Scope(Scope** variable, ScopeType type)
110 : variable_(variable),
111 prev_(*variable),
112 type_(type),
113 materialized_literal_count_(0),
114 expected_properties_(0),
115 with_nesting_count_(0) {
116 *variable = this;
117 }
118 ~Scope() { *variable_ = prev_; }
119 void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
120 void AddProperty() { expected_properties_++; }
121 ScopeType type() { return type_; }
122 int expected_properties() { return expected_properties_; }
123 int materialized_literal_count() { return materialized_literal_count_; }
124 bool IsInsideWith() { return with_nesting_count_ != 0; }
125 void EnterWith() { with_nesting_count_++; }
126 void LeaveWith() { with_nesting_count_--; }
127
128 private:
129 Scope** const variable_;
130 Scope* const prev_;
131 const ScopeType type_;
132 int materialized_literal_count_;
133 int expected_properties_;
134 int with_nesting_count_;
135 };
136
Ben Murdochb0fe1622011-05-05 13:52:32 +0100137 // Private constructor only used in PreParseProgram.
138 PreParser(i::JavaScriptScanner* scanner,
139 i::ParserRecorder* log,
140 uintptr_t stack_limit,
141 bool allow_lazy)
142 : scanner_(scanner),
143 log_(log),
144 scope_(NULL),
145 stack_limit_(stack_limit),
146 stack_overflow_(false),
Ben Murdochb8e0da22011-05-16 14:20:40 +0100147 allow_lazy_(true),
148 parenthesized_function_(false) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100149
150 // Preparse the program. Only called in PreParseProgram after creating
151 // the instance.
152 PreParseResult PreParse() {
153 Scope top_scope(&scope_, kTopLevelScope);
154 bool ok = true;
155 ParseSourceElements(i::Token::EOS, &ok);
156 if (stack_overflow_) return kPreParseStackOverflow;
157 if (!ok) {
158 ReportUnexpectedToken(scanner_->current_token());
159 }
160 return kPreParseSuccess;
161 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800162
163 // Report syntax error
164 void ReportUnexpectedToken(i::Token::Value token);
165 void ReportMessageAt(int start_pos,
166 int end_pos,
167 const char* type,
168 const char* name_opt) {
169 log_->LogMessage(start_pos, end_pos, type, name_opt);
170 }
171
172 // All ParseXXX functions take as the last argument an *ok parameter
173 // which is set to false if parsing failed; it is unchanged otherwise.
174 // By making the 'exception handling' explicit, we are forced to check
175 // for failure at the call sites.
176 SourceElements ParseSourceElements(int end_token, bool* ok);
177 Statement ParseStatement(bool* ok);
178 Statement ParseFunctionDeclaration(bool* ok);
179 Statement ParseNativeDeclaration(bool* ok);
180 Statement ParseBlock(bool* ok);
181 Statement ParseVariableStatement(bool* ok);
182 Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok);
183 Statement ParseExpressionOrLabelledStatement(bool* ok);
184 Statement ParseIfStatement(bool* ok);
185 Statement ParseContinueStatement(bool* ok);
186 Statement ParseBreakStatement(bool* ok);
187 Statement ParseReturnStatement(bool* ok);
188 Statement ParseWithStatement(bool* ok);
189 Statement ParseSwitchStatement(bool* ok);
190 Statement ParseDoWhileStatement(bool* ok);
191 Statement ParseWhileStatement(bool* ok);
192 Statement ParseForStatement(bool* ok);
193 Statement ParseThrowStatement(bool* ok);
194 Statement ParseTryStatement(bool* ok);
195 Statement ParseDebuggerStatement(bool* ok);
196
197 Expression ParseExpression(bool accept_IN, bool* ok);
198 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
199 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
200 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
201 Expression ParseUnaryExpression(bool* ok);
202 Expression ParsePostfixExpression(bool* ok);
203 Expression ParseLeftHandSideExpression(bool* ok);
204 Expression ParseNewExpression(bool* ok);
205 Expression ParseMemberExpression(bool* ok);
206 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
207 Expression ParsePrimaryExpression(bool* ok);
208 Expression ParseArrayLiteral(bool* ok);
209 Expression ParseObjectLiteral(bool* ok);
210 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
211 Expression ParseV8Intrinsic(bool* ok);
212
213 Arguments ParseArguments(bool* ok);
214 Expression ParseFunctionLiteral(bool* ok);
215
216 Identifier ParseIdentifier(bool* ok);
217 Identifier ParseIdentifierName(bool* ok);
218 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok);
219
Steve Block9fac8402011-05-12 15:51:54 +0100220 // Logs the currently parsed literal as a symbol in the preparser data.
221 void LogSymbol();
222 // Log the currently parsed identifier.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800223 Identifier GetIdentifierSymbol();
Steve Block9fac8402011-05-12 15:51:54 +0100224 // Log the currently parsed string literal.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800225 Expression GetStringSymbol();
226
Ben Murdochb0fe1622011-05-05 13:52:32 +0100227 i::Token::Value peek() {
228 if (stack_overflow_) return i::Token::ILLEGAL;
229 return scanner_->peek();
230 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800231
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800232 i::Token::Value Next() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233 if (stack_overflow_) return i::Token::ILLEGAL;
234 {
235 int marker;
236 if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
237 // Further calls to peek/Next will return illegal token.
238 // The current one will still be returned. It might already
239 // have been seen using peek.
240 stack_overflow_ = true;
241 }
242 }
243 return scanner_->Next();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800244 }
245
Steve Block1e0659c2011-05-24 12:43:12 +0100246 bool peek_any_identifier();
247
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248 void Consume(i::Token::Value token) { Next(); }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800249
250 void Expect(i::Token::Value token, bool* ok) {
251 if (Next() != token) {
252 *ok = false;
253 }
254 }
255
256 bool Check(i::Token::Value token) {
257 i::Token::Value next = peek();
258 if (next == token) {
259 Consume(next);
260 return true;
261 }
262 return false;
263 }
264 void ExpectSemicolon(bool* ok);
265
266 static int Precedence(i::Token::Value tok, bool accept_IN);
267
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800268 i::JavaScriptScanner* scanner_;
269 i::ParserRecorder* log_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800270 Scope* scope_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100271 uintptr_t stack_limit_;
272 bool stack_overflow_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800273 bool allow_lazy_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100274 bool parenthesized_function_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800275};
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800276} } // v8::preparser
277
278#endif // V8_PREPARSER_H