blob: b783d65db32468c6395a76ecd046399cd6d851c6 [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
49enum StatementType {
50 kUnknownStatement
51};
52
53enum ExpressionType {
54 kUnknownExpression,
55 kIdentifierExpression, // Used to detect labels.
56 kThisExpression,
57 kThisPropertyExpression
58};
59
60enum IdentifierType {
61 kUnknownIdentifier
62};
63
64enum SourceElementTypes {
65 kUnknownSourceElements
66};
67
68
69typedef int SourceElements;
70typedef int Expression;
71typedef int Statement;
72typedef int Identifier;
73typedef int Arguments;
74
75
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080076class PreParser {
77 public:
78 PreParser() : scope_(NULL), allow_lazy_(true) { }
79 ~PreParser() { }
80
81 // Pre-parse the program from the character stream; returns true on
82 // success (even if parsing failed, the pre-parse data successfully
83 // captured the syntax error), and false if a stack-overflow happened
84 // during parsing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080085 bool PreParseProgram(i::JavaScriptScanner* scanner,
86 i::ParserRecorder* log,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080087 bool allow_lazy) {
88 allow_lazy_ = allow_lazy;
89 scanner_ = scanner;
90 log_ = log;
91 Scope top_scope(&scope_, kTopLevelScope);
92 bool ok = true;
93 ParseSourceElements(i::Token::EOS, &ok);
94 bool stack_overflow = scanner_->stack_overflow();
95 if (!ok && !stack_overflow) {
96 ReportUnexpectedToken(scanner_->current_token());
97 }
98 return !stack_overflow;
99 }
100
101 private:
102 enum ScopeType {
103 kTopLevelScope,
104 kFunctionScope
105 };
106
107 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
137 // Types that allow us to recognize simple this-property assignments.
138 // A simple this-property assignment is a statement on the form
139 // "this.propertyName = {primitive constant or function parameter name);"
140 // where propertyName isn't "__proto__".
141 // The result is only relevant if the function body contains only
142 // simple this-property assignments.
143
144 // Report syntax error
145 void ReportUnexpectedToken(i::Token::Value token);
146 void ReportMessageAt(int start_pos,
147 int end_pos,
148 const char* type,
149 const char* name_opt) {
150 log_->LogMessage(start_pos, end_pos, type, name_opt);
151 }
152
153 // All ParseXXX functions take as the last argument an *ok parameter
154 // which is set to false if parsing failed; it is unchanged otherwise.
155 // By making the 'exception handling' explicit, we are forced to check
156 // for failure at the call sites.
157 SourceElements ParseSourceElements(int end_token, bool* ok);
158 Statement ParseStatement(bool* ok);
159 Statement ParseFunctionDeclaration(bool* ok);
160 Statement ParseNativeDeclaration(bool* ok);
161 Statement ParseBlock(bool* ok);
162 Statement ParseVariableStatement(bool* ok);
163 Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok);
164 Statement ParseExpressionOrLabelledStatement(bool* ok);
165 Statement ParseIfStatement(bool* ok);
166 Statement ParseContinueStatement(bool* ok);
167 Statement ParseBreakStatement(bool* ok);
168 Statement ParseReturnStatement(bool* ok);
169 Statement ParseWithStatement(bool* ok);
170 Statement ParseSwitchStatement(bool* ok);
171 Statement ParseDoWhileStatement(bool* ok);
172 Statement ParseWhileStatement(bool* ok);
173 Statement ParseForStatement(bool* ok);
174 Statement ParseThrowStatement(bool* ok);
175 Statement ParseTryStatement(bool* ok);
176 Statement ParseDebuggerStatement(bool* ok);
177
178 Expression ParseExpression(bool accept_IN, bool* ok);
179 Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
180 Expression ParseConditionalExpression(bool accept_IN, bool* ok);
181 Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
182 Expression ParseUnaryExpression(bool* ok);
183 Expression ParsePostfixExpression(bool* ok);
184 Expression ParseLeftHandSideExpression(bool* ok);
185 Expression ParseNewExpression(bool* ok);
186 Expression ParseMemberExpression(bool* ok);
187 Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
188 Expression ParsePrimaryExpression(bool* ok);
189 Expression ParseArrayLiteral(bool* ok);
190 Expression ParseObjectLiteral(bool* ok);
191 Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
192 Expression ParseV8Intrinsic(bool* ok);
193
194 Arguments ParseArguments(bool* ok);
195 Expression ParseFunctionLiteral(bool* ok);
196
197 Identifier ParseIdentifier(bool* ok);
198 Identifier ParseIdentifierName(bool* ok);
199 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok);
200
201 Identifier GetIdentifierSymbol();
202 unsigned int HexDigitValue(char digit);
203 Expression GetStringSymbol();
204
205
206 i::Token::Value peek() { return scanner_->peek(); }
207 i::Token::Value Next() {
208 i::Token::Value next = scanner_->Next();
209 return next;
210 }
211
212 void Consume(i::Token::Value token) {
213 Next();
214 }
215
216 void Expect(i::Token::Value token, bool* ok) {
217 if (Next() != token) {
218 *ok = false;
219 }
220 }
221
222 bool Check(i::Token::Value token) {
223 i::Token::Value next = peek();
224 if (next == token) {
225 Consume(next);
226 return true;
227 }
228 return false;
229 }
230 void ExpectSemicolon(bool* ok);
231
232 static int Precedence(i::Token::Value tok, bool accept_IN);
233
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800234 i::JavaScriptScanner* scanner_;
235 i::ParserRecorder* log_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800236 Scope* scope_;
237 bool allow_lazy_;
238};
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800239} } // v8::preparser
240
241#endif // V8_PREPARSER_H