]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2010 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 | * THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef ASTBuilder_h | |
27 | #define ASTBuilder_h | |
28 | ||
29 | #include "NodeConstructors.h" | |
30 | #include "SyntaxChecker.h" | |
31 | #include <utility> | |
32 | ||
33 | namespace JSC { | |
34 | ||
35 | class ASTBuilder { | |
36 | struct BinaryOpInfo { | |
37 | BinaryOpInfo() {} | |
38 | BinaryOpInfo(int s, int d, int e, bool r) | |
39 | : start(s) | |
40 | , divot(d) | |
41 | , end(e) | |
42 | , hasAssignment(r) | |
43 | { | |
44 | } | |
45 | BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs) | |
46 | : start(lhs.start) | |
47 | , divot(rhs.start) | |
48 | , end(rhs.end) | |
49 | , hasAssignment(lhs.hasAssignment || rhs.hasAssignment) | |
50 | { | |
51 | } | |
52 | int start; | |
53 | int divot; | |
54 | int end; | |
55 | bool hasAssignment; | |
56 | }; | |
57 | ||
58 | ||
59 | struct AssignmentInfo { | |
60 | AssignmentInfo() {} | |
61 | AssignmentInfo(ExpressionNode* node, int start, int divot, int initAssignments, Operator op) | |
62 | : m_node(node) | |
63 | , m_start(start) | |
64 | , m_divot(divot) | |
65 | , m_initAssignments(initAssignments) | |
66 | , m_op(op) | |
67 | { | |
68 | } | |
69 | ExpressionNode* m_node; | |
70 | int m_start; | |
71 | int m_divot; | |
72 | int m_initAssignments; | |
73 | Operator m_op; | |
74 | }; | |
75 | public: | |
76 | ASTBuilder(JSGlobalData* globalData, Lexer* lexer) | |
77 | : m_globalData(globalData) | |
78 | , m_lexer(lexer) | |
79 | , m_scope(globalData) | |
80 | , m_evalCount(0) | |
81 | { | |
82 | } | |
83 | ||
84 | struct BinaryExprContext { | |
85 | BinaryExprContext(ASTBuilder&) {} | |
86 | }; | |
87 | struct UnaryExprContext { | |
88 | UnaryExprContext(ASTBuilder&) {} | |
89 | }; | |
90 | ||
91 | typedef SyntaxChecker FunctionBodyBuilder; | |
92 | ||
93 | typedef ExpressionNode* Expression; | |
94 | typedef JSC::SourceElements* SourceElements; | |
95 | typedef ArgumentsNode* Arguments; | |
96 | typedef CommaNode* Comma; | |
97 | typedef PropertyNode* Property; | |
98 | typedef PropertyListNode* PropertyList; | |
99 | typedef ElementNode* ElementList; | |
100 | typedef ArgumentListNode* ArgumentsList; | |
101 | typedef ParameterNode* FormalParameterList; | |
102 | typedef FunctionBodyNode* FunctionBody; | |
103 | typedef StatementNode* Statement; | |
104 | typedef ClauseListNode* ClauseList; | |
105 | typedef CaseClauseNode* Clause; | |
106 | typedef ConstDeclNode* ConstDeclList; | |
107 | typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand; | |
108 | ||
109 | static const bool CreatesAST = true; | |
110 | static const bool NeedsFreeVariableInfo = true; | |
111 | static const bool CanUseFunctionCache = true; | |
112 | static const int DontBuildKeywords = 0; | |
113 | static const int DontBuildStrings = 0; | |
114 | ||
115 | ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); | |
116 | ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end); | |
117 | ||
118 | JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(m_globalData); } | |
119 | ||
120 | ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; } | |
121 | ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; } | |
122 | int features() const { return m_scope.m_features; } | |
123 | int numConstants() const { return m_scope.m_numConstants; } | |
124 | ||
125 | void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } | |
126 | ||
127 | CommaNode* createCommaExpr(ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(m_globalData, lhs, rhs); } | |
128 | ||
129 | ExpressionNode* makeAssignNode(ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end); | |
130 | ExpressionNode* makePrefixNode(ExpressionNode*, Operator, int start, int divot, int end); | |
131 | ExpressionNode* makePostfixNode(ExpressionNode*, Operator, int start, int divot, int end); | |
132 | ExpressionNode* makeTypeOfNode(ExpressionNode*); | |
133 | ExpressionNode* makeDeleteNode(ExpressionNode*, int start, int divot, int end); | |
134 | ExpressionNode* makeNegateNode(ExpressionNode*); | |
135 | ExpressionNode* makeBitwiseNotNode(ExpressionNode*); | |
136 | ExpressionNode* makeMultNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
137 | ExpressionNode* makeDivNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
138 | ExpressionNode* makeModNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
139 | ExpressionNode* makeAddNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
140 | ExpressionNode* makeSubNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
141 | ExpressionNode* makeBitXOrNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
142 | ExpressionNode* makeBitAndNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
143 | ExpressionNode* makeBitOrNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
144 | ExpressionNode* makeLeftShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
145 | ExpressionNode* makeRightShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
146 | ExpressionNode* makeURightShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); | |
147 | ||
148 | ExpressionNode* createLogicalNot(ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(m_globalData, expr); } | |
149 | ExpressionNode* createUnaryPlus(ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(m_globalData, expr); } | |
150 | ExpressionNode* createVoid(ExpressionNode* expr) | |
151 | { | |
152 | incConstants(); | |
153 | return new (m_globalData) VoidNode(m_globalData, expr); | |
154 | } | |
155 | ExpressionNode* thisExpr() | |
156 | { | |
157 | usesThis(); | |
158 | return new (m_globalData) ThisNode(m_globalData); | |
159 | } | |
160 | ExpressionNode* createResolve(const Identifier* ident, int start) | |
161 | { | |
162 | if (m_globalData->propertyNames->arguments == *ident) | |
163 | usesArguments(); | |
164 | return new (m_globalData) ResolveNode(m_globalData, *ident, start); | |
165 | } | |
166 | ExpressionNode* createObjectLiteral() { return new (m_globalData) ObjectLiteralNode(m_globalData); } | |
167 | ExpressionNode* createObjectLiteral(PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(m_globalData, properties); } | |
168 | ||
169 | ExpressionNode* createArray(int elisions) | |
170 | { | |
171 | if (elisions) | |
172 | incConstants(); | |
173 | return new (m_globalData) ArrayNode(m_globalData, elisions); | |
174 | } | |
175 | ||
176 | ExpressionNode* createArray(ElementNode* elems) { return new (m_globalData) ArrayNode(m_globalData, elems); } | |
177 | ExpressionNode* createArray(int elisions, ElementNode* elems) | |
178 | { | |
179 | if (elisions) | |
180 | incConstants(); | |
181 | return new (m_globalData) ArrayNode(m_globalData, elisions, elems); | |
182 | } | |
183 | ExpressionNode* createNumberExpr(double d) | |
184 | { | |
185 | incConstants(); | |
186 | return new (m_globalData) NumberNode(m_globalData, d); | |
187 | } | |
188 | ||
189 | ExpressionNode* createString(const Identifier* string) | |
190 | { | |
191 | incConstants(); | |
192 | return new (m_globalData) StringNode(m_globalData, *string); | |
193 | } | |
194 | ||
195 | ExpressionNode* createBoolean(bool b) | |
196 | { | |
197 | incConstants(); | |
198 | return new (m_globalData) BooleanNode(m_globalData, b); | |
199 | } | |
200 | ||
201 | ExpressionNode* createNull() | |
202 | { | |
203 | incConstants(); | |
204 | return new (m_globalData) NullNode(m_globalData); | |
205 | } | |
206 | ||
207 | ExpressionNode* createBracketAccess(ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end) | |
208 | { | |
209 | BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(m_globalData, base, property, propertyHasAssignments); | |
210 | setExceptionLocation(node, start, divot, end); | |
211 | return node; | |
212 | } | |
213 | ||
214 | ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier* property, int start, int divot, int end) | |
215 | { | |
216 | DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, *property); | |
217 | setExceptionLocation(node, start, divot, end); | |
218 | return node; | |
219 | } | |
220 | ||
221 | ExpressionNode* createRegExp(const Identifier& pattern, const Identifier& flags, int start) | |
222 | { | |
223 | if (Yarr::checkSyntax(pattern.ustring())) | |
224 | return 0; | |
225 | RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags); | |
226 | int size = pattern.length() + 2; // + 2 for the two /'s | |
227 | setExceptionLocation(node, start, start + size, start + size); | |
228 | return node; | |
229 | } | |
230 | ||
231 | ExpressionNode* createNewExpr(ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end) | |
232 | { | |
233 | NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr, arguments); | |
234 | setExceptionLocation(node, start, divot, end); | |
235 | return node; | |
236 | } | |
237 | ||
238 | ExpressionNode* createNewExpr(ExpressionNode* expr, int start, int end) | |
239 | { | |
240 | NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr); | |
241 | setExceptionLocation(node, start, end, end); | |
242 | return node; | |
243 | } | |
244 | ||
245 | ExpressionNode* createConditionalExpr(ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) | |
246 | { | |
247 | return new (m_globalData) ConditionalNode(m_globalData, condition, lhs, rhs); | |
248 | } | |
249 | ||
250 | ExpressionNode* createAssignResolve(const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end) | |
251 | { | |
252 | AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, ident, rhs, rhsHasAssignment); | |
253 | setExceptionLocation(node, start, divot, end); | |
254 | return node; | |
255 | } | |
256 | ||
257 | ExpressionNode* createFunctionExpr(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) | |
258 | { | |
259 | FuncExprNode* result = new (m_globalData) FuncExprNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters); | |
260 | body->setLoc(bodyStartLine, bodyEndLine); | |
261 | return result; | |
262 | } | |
263 | ||
264 | FunctionBodyNode* createFunctionBody(bool inStrictContext) | |
265 | { | |
266 | usesClosures(); | |
267 | return FunctionBodyNode::create(m_globalData, inStrictContext); | |
268 | } | |
269 | ||
270 | template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) | |
271 | { | |
272 | ASSERT(name); | |
273 | body->setLoc(bodyStartLine, bodyEndLine); | |
274 | return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(m_globalData, m_globalData->propertyNames->nullIdentifier, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), params), type); | |
275 | } | |
276 | ||
277 | ||
278 | ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(m_globalData); } | |
279 | ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(m_globalData, args); } | |
280 | ArgumentListNode* createArgumentsList(ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, arg); } | |
281 | ArgumentListNode* createArgumentsList(ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, args, arg); } | |
282 | ||
283 | template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); } | |
284 | template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); } | |
285 | PropertyListNode* createPropertyList(PropertyNode* property) { return new (m_globalData) PropertyListNode(m_globalData, property); } | |
286 | PropertyListNode* createPropertyList(PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(m_globalData, property, tail); } | |
287 | ||
288 | ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elisions, expr); } | |
289 | ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elems, elisions, expr); } | |
290 | ||
291 | ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, ident); } | |
292 | ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, list, ident); } | |
293 | ||
294 | CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_globalData) CaseClauseNode(m_globalData, expr, statements); } | |
295 | ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, clause); } | |
296 | ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, tail, clause); } | |
297 | ||
298 | void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); } | |
299 | ||
300 | StatementNode* createFuncDeclStatement(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) | |
301 | { | |
302 | FuncDeclNode* decl = new (m_globalData) FuncDeclNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters); | |
303 | if (*name == m_globalData->propertyNames->arguments) | |
304 | usesArguments(); | |
305 | m_scope.m_funcDeclarations->data.append(decl->body()); | |
306 | body->setLoc(bodyStartLine, bodyEndLine); | |
307 | return decl; | |
308 | } | |
309 | ||
310 | StatementNode* createBlockStatement(JSC::SourceElements* elements, int startLine, int endLine) | |
311 | { | |
312 | BlockNode* block = new (m_globalData) BlockNode(m_globalData, elements); | |
313 | block->setLoc(startLine, endLine); | |
314 | return block; | |
315 | } | |
316 | ||
317 | StatementNode* createExprStatement(ExpressionNode* expr, int start, int end) | |
318 | { | |
319 | ExprStatementNode* result = new (m_globalData) ExprStatementNode(m_globalData, expr); | |
320 | result->setLoc(start, end); | |
321 | return result; | |
322 | } | |
323 | ||
324 | StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, int start, int end) | |
325 | { | |
326 | IfNode* result = new (m_globalData) IfNode(m_globalData, condition, trueBlock); | |
327 | result->setLoc(start, end); | |
328 | return result; | |
329 | } | |
330 | ||
331 | StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) | |
332 | { | |
333 | IfNode* result = new (m_globalData) IfElseNode(m_globalData, condition, trueBlock, falseBlock); | |
334 | result->setLoc(start, end); | |
335 | return result; | |
336 | } | |
337 | ||
338 | StatementNode* createForLoop(ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, bool b, int start, int end) | |
339 | { | |
340 | ForNode* result = new (m_globalData) ForNode(m_globalData, initializer, condition, iter, statements, b); | |
341 | result->setLoc(start, end); | |
342 | return result; | |
343 | } | |
344 | ||
345 | StatementNode* createForInLoop(const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine) | |
346 | { | |
347 | ForInNode* result = new (m_globalData) ForInNode(m_globalData, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart); | |
348 | result->setLoc(startLine, endLine); | |
349 | setExceptionLocation(result, start, divot + 1, end); | |
350 | return result; | |
351 | } | |
352 | ||
353 | StatementNode* createForInLoop(ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end) | |
354 | { | |
355 | ForInNode* result = new (m_globalData) ForInNode(m_globalData, lhs, iter, statements); | |
356 | result->setLoc(start, end); | |
357 | setExceptionLocation(result, eStart, eDivot, eEnd); | |
358 | return result; | |
359 | } | |
360 | ||
361 | StatementNode* createEmptyStatement() { return new (m_globalData) EmptyStatementNode(m_globalData); } | |
362 | ||
363 | StatementNode* createVarStatement(ExpressionNode* expr, int start, int end) | |
364 | { | |
365 | StatementNode* result; | |
366 | if (!expr) | |
367 | result = new (m_globalData) EmptyStatementNode(m_globalData); | |
368 | else | |
369 | result = new (m_globalData) VarStatementNode(m_globalData, expr); | |
370 | result->setLoc(start, end); | |
371 | return result; | |
372 | } | |
373 | ||
374 | StatementNode* createReturnStatement(ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine) | |
375 | { | |
376 | ReturnNode* result = new (m_globalData) ReturnNode(m_globalData, expression); | |
377 | setExceptionLocation(result, eStart, eEnd, eEnd); | |
378 | result->setLoc(startLine, endLine); | |
379 | return result; | |
380 | } | |
381 | ||
382 | StatementNode* createBreakStatement(int eStart, int eEnd, int startLine, int endLine) | |
383 | { | |
384 | BreakNode* result = new (m_globalData) BreakNode(m_globalData); | |
385 | setExceptionLocation(result, eStart, eEnd, eEnd); | |
386 | result->setLoc(startLine, endLine); | |
387 | return result; | |
388 | } | |
389 | ||
390 | StatementNode* createBreakStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) | |
391 | { | |
392 | BreakNode* result = new (m_globalData) BreakNode(m_globalData, *ident); | |
393 | setExceptionLocation(result, eStart, eEnd, eEnd); | |
394 | result->setLoc(startLine, endLine); | |
395 | return result; | |
396 | } | |
397 | ||
398 | StatementNode* createContinueStatement(int eStart, int eEnd, int startLine, int endLine) | |
399 | { | |
400 | ContinueNode* result = new (m_globalData) ContinueNode(m_globalData); | |
401 | setExceptionLocation(result, eStart, eEnd, eEnd); | |
402 | result->setLoc(startLine, endLine); | |
403 | return result; | |
404 | } | |
405 | ||
406 | StatementNode* createContinueStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) | |
407 | { | |
408 | ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, *ident); | |
409 | setExceptionLocation(result, eStart, eEnd, eEnd); | |
410 | result->setLoc(startLine, endLine); | |
411 | return result; | |
412 | } | |
413 | ||
414 | StatementNode* createTryStatement(StatementNode* tryBlock, const Identifier* ident, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) | |
415 | { | |
416 | TryNode* result = new (m_globalData) TryNode(m_globalData, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock); | |
417 | if (catchBlock) | |
418 | usesCatch(); | |
419 | result->setLoc(startLine, endLine); | |
420 | return result; | |
421 | } | |
422 | ||
423 | StatementNode* createSwitchStatement(ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine) | |
424 | { | |
425 | CaseBlockNode* cases = new (m_globalData) CaseBlockNode(m_globalData, firstClauses, defaultClause, secondClauses); | |
426 | SwitchNode* result = new (m_globalData) SwitchNode(m_globalData, expr, cases); | |
427 | result->setLoc(startLine, endLine); | |
428 | return result; | |
429 | } | |
430 | ||
431 | StatementNode* createWhileStatement(ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) | |
432 | { | |
433 | WhileNode* result = new (m_globalData) WhileNode(m_globalData, expr, statement); | |
434 | result->setLoc(startLine, endLine); | |
435 | return result; | |
436 | } | |
437 | ||
438 | StatementNode* createDoWhileStatement(StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) | |
439 | { | |
440 | DoWhileNode* result = new (m_globalData) DoWhileNode(m_globalData, statement, expr); | |
441 | result->setLoc(startLine, endLine); | |
442 | return result; | |
443 | } | |
444 | ||
445 | StatementNode* createLabelStatement(const Identifier* ident, StatementNode* statement, int start, int end) | |
446 | { | |
447 | LabelNode* result = new (m_globalData) LabelNode(m_globalData, *ident, statement); | |
448 | setExceptionLocation(result, start, end, end); | |
449 | return result; | |
450 | } | |
451 | ||
452 | StatementNode* createWithStatement(ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) | |
453 | { | |
454 | usesWith(); | |
455 | WithNode* result = new (m_globalData) WithNode(m_globalData, expr, statement, end, end - start); | |
456 | result->setLoc(startLine, endLine); | |
457 | return result; | |
458 | } | |
459 | ||
460 | StatementNode* createThrowStatement(ExpressionNode* expr, int start, int end, int startLine, int endLine) | |
461 | { | |
462 | ThrowNode* result = new (m_globalData) ThrowNode(m_globalData, expr); | |
463 | result->setLoc(startLine, endLine); | |
464 | setExceptionLocation(result, start, end, end); | |
465 | return result; | |
466 | } | |
467 | ||
468 | StatementNode* createDebugger(int startLine, int endLine) | |
469 | { | |
470 | DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(m_globalData); | |
471 | result->setLoc(startLine, endLine); | |
472 | return result; | |
473 | } | |
474 | ||
475 | StatementNode* createConstStatement(ConstDeclNode* decls, int startLine, int endLine) | |
476 | { | |
477 | ConstStatementNode* result = new (m_globalData) ConstStatementNode(m_globalData, decls); | |
478 | result->setLoc(startLine, endLine); | |
479 | return result; | |
480 | } | |
481 | ||
482 | ConstDeclNode* appendConstDecl(ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) | |
483 | { | |
484 | ConstDeclNode* result = new (m_globalData) ConstDeclNode(m_globalData, *name, initializer); | |
485 | if (tail) | |
486 | tail->m_next = result; | |
487 | return result; | |
488 | } | |
489 | ||
490 | void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement) | |
491 | { | |
492 | elements->append(statement); | |
493 | } | |
494 | ||
495 | void addVar(const Identifier* ident, int attrs) | |
496 | { | |
497 | if (m_globalData->propertyNames->arguments == *ident) | |
498 | usesArguments(); | |
499 | m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs)); | |
500 | } | |
501 | ||
502 | ExpressionNode* combineCommaNodes(ExpressionNode* list, ExpressionNode* init) | |
503 | { | |
504 | if (!list) | |
505 | return init; | |
506 | if (list->isCommaNode()) { | |
507 | static_cast<CommaNode*>(list)->append(init); | |
508 | return list; | |
509 | } | |
510 | return new (m_globalData) CommaNode(m_globalData, list, init); | |
511 | } | |
512 | ||
513 | int evalCount() const { return m_evalCount; } | |
514 | ||
515 | void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments) | |
516 | { | |
517 | operandStackDepth++; | |
518 | m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments))); | |
519 | } | |
520 | ||
521 | // Logic to handle datastructures used during parsing of binary expressions | |
522 | void operatorStackPop(int& operatorStackDepth) | |
523 | { | |
524 | operatorStackDepth--; | |
525 | m_binaryOperatorStack.removeLast(); | |
526 | } | |
527 | bool operatorStackHasHigherPrecedence(int&, int precedence) | |
528 | { | |
529 | return precedence <= m_binaryOperatorStack.last().second; | |
530 | } | |
531 | const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; } | |
532 | void shrinkOperandStackBy(int& operandStackDepth, int amount) | |
533 | { | |
534 | operandStackDepth -= amount; | |
535 | ASSERT(operandStackDepth >= 0); | |
536 | m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount); | |
537 | } | |
538 | void appendBinaryOperation(int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs) | |
539 | { | |
540 | operandStackDepth++; | |
541 | m_binaryOperandStack.append(std::make_pair(makeBinaryNode(m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second))); | |
542 | } | |
543 | void operatorStackAppend(int& operatorStackDepth, int op, int precedence) | |
544 | { | |
545 | operatorStackDepth++; | |
546 | m_binaryOperatorStack.append(std::make_pair(op, precedence)); | |
547 | } | |
548 | ExpressionNode* popOperandStack(int&) | |
549 | { | |
550 | ExpressionNode* result = m_binaryOperandStack.last().first; | |
551 | m_binaryOperandStack.removeLast(); | |
552 | return result; | |
553 | } | |
554 | ||
555 | void appendUnaryToken(int& tokenStackDepth, int type, int start) | |
556 | { | |
557 | tokenStackDepth++; | |
558 | m_unaryTokenStack.append(std::make_pair(type, start)); | |
559 | } | |
560 | ||
561 | int unaryTokenStackLastType(int&) | |
562 | { | |
563 | return m_unaryTokenStack.last().first; | |
564 | } | |
565 | ||
566 | int unaryTokenStackLastStart(int&) | |
567 | { | |
568 | return m_unaryTokenStack.last().second; | |
569 | } | |
570 | ||
571 | void unaryTokenStackRemoveLast(int& tokenStackDepth) | |
572 | { | |
573 | tokenStackDepth--; | |
574 | m_unaryTokenStack.removeLast(); | |
575 | } | |
576 | ||
577 | void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, int start, int divot, int assignmentCount, Operator op) | |
578 | { | |
579 | assignmentStackDepth++; | |
580 | m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op)); | |
581 | } | |
582 | ||
583 | ExpressionNode* createAssignment(int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd) | |
584 | { | |
585 | ExpressionNode* result = makeAssignNode(m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd); | |
586 | m_assignmentInfoStack.removeLast(); | |
587 | assignmentStackDepth--; | |
588 | return result; | |
589 | } | |
590 | ||
591 | const Identifier& getName(Property property) const { return property->name(); } | |
592 | PropertyNode::Type getType(Property property) const { return property->type(); } | |
593 | ||
594 | bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); } | |
595 | ||
596 | private: | |
597 | struct Scope { | |
598 | Scope(JSGlobalData* globalData) | |
599 | : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>) | |
600 | , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>) | |
601 | , m_features(0) | |
602 | , m_numConstants(0) | |
603 | { | |
604 | } | |
605 | ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; | |
606 | ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; | |
607 | int m_features; | |
608 | int m_numConstants; | |
609 | }; | |
610 | ||
611 | static void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end) | |
612 | { | |
613 | node->setExceptionSourceCode(divot, divot - start, end - divot); | |
614 | } | |
615 | ||
616 | void incConstants() { m_scope.m_numConstants++; } | |
617 | void usesThis() { m_scope.m_features |= ThisFeature; } | |
618 | void usesCatch() { m_scope.m_features |= CatchFeature; } | |
619 | void usesClosures() { m_scope.m_features |= ClosureFeature; } | |
620 | void usesArguments() { m_scope.m_features |= ArgumentsFeature; } | |
621 | void usesAssignment() { m_scope.m_features |= AssignFeature; } | |
622 | void usesWith() { m_scope.m_features |= WithFeature; } | |
623 | void usesEval() | |
624 | { | |
625 | m_evalCount++; | |
626 | m_scope.m_features |= EvalFeature; | |
627 | } | |
628 | ExpressionNode* createNumber(double d) | |
629 | { | |
630 | return new (m_globalData) NumberNode(m_globalData, d); | |
631 | } | |
632 | ||
633 | JSGlobalData* m_globalData; | |
634 | Lexer* m_lexer; | |
635 | Scope m_scope; | |
636 | Vector<BinaryOperand, 10> m_binaryOperandStack; | |
637 | Vector<AssignmentInfo, 10> m_assignmentInfoStack; | |
638 | Vector<pair<int, int>, 10> m_binaryOperatorStack; | |
639 | Vector<pair<int, int>, 10> m_unaryTokenStack; | |
640 | int m_evalCount; | |
641 | }; | |
642 | ||
643 | ExpressionNode* ASTBuilder::makeTypeOfNode(ExpressionNode* expr) | |
644 | { | |
645 | if (expr->isResolveNode()) { | |
646 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); | |
647 | return new (m_globalData) TypeOfResolveNode(m_globalData, resolve->identifier()); | |
648 | } | |
649 | return new (m_globalData) TypeOfValueNode(m_globalData, expr); | |
650 | } | |
651 | ||
652 | ExpressionNode* ASTBuilder::makeDeleteNode(ExpressionNode* expr, int start, int divot, int end) | |
653 | { | |
654 | if (!expr->isLocation()) | |
655 | return new (m_globalData) DeleteValueNode(m_globalData, expr); | |
656 | if (expr->isResolveNode()) { | |
657 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); | |
658 | return new (m_globalData) DeleteResolveNode(m_globalData, resolve->identifier(), divot, divot - start, end - divot); | |
659 | } | |
660 | if (expr->isBracketAccessorNode()) { | |
661 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); | |
662 | return new (m_globalData) DeleteBracketNode(m_globalData, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); | |
663 | } | |
664 | ASSERT(expr->isDotAccessorNode()); | |
665 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); | |
666 | return new (m_globalData) DeleteDotNode(m_globalData, dot->base(), dot->identifier(), divot, divot - start, end - divot); | |
667 | } | |
668 | ||
669 | ExpressionNode* ASTBuilder::makeNegateNode(ExpressionNode* n) | |
670 | { | |
671 | if (n->isNumber()) { | |
672 | NumberNode* numberNode = static_cast<NumberNode*>(n); | |
673 | numberNode->setValue(-numberNode->value()); | |
674 | return numberNode; | |
675 | } | |
676 | ||
677 | return new (m_globalData) NegateNode(m_globalData, n); | |
678 | } | |
679 | ||
680 | ExpressionNode* ASTBuilder::makeBitwiseNotNode(ExpressionNode* expr) | |
681 | { | |
682 | if (expr->isNumber()) | |
683 | return createNumber(~toInt32(static_cast<NumberNode*>(expr)->value())); | |
684 | return new (m_globalData) BitwiseNotNode(m_globalData, expr); | |
685 | } | |
686 | ||
687 | ExpressionNode* ASTBuilder::makeMultNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
688 | { | |
689 | expr1 = expr1->stripUnaryPlus(); | |
690 | expr2 = expr2->stripUnaryPlus(); | |
691 | ||
692 | if (expr1->isNumber() && expr2->isNumber()) | |
693 | return createNumber(static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); | |
694 | ||
695 | if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) | |
696 | return new (m_globalData) UnaryPlusNode(m_globalData, expr2); | |
697 | ||
698 | if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) | |
699 | return new (m_globalData) UnaryPlusNode(m_globalData, expr1); | |
700 | ||
701 | return new (m_globalData) MultNode(m_globalData, expr1, expr2, rightHasAssignments); | |
702 | } | |
703 | ||
704 | ExpressionNode* ASTBuilder::makeDivNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
705 | { | |
706 | expr1 = expr1->stripUnaryPlus(); | |
707 | expr2 = expr2->stripUnaryPlus(); | |
708 | ||
709 | if (expr1->isNumber() && expr2->isNumber()) | |
710 | return createNumber(static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); | |
711 | return new (m_globalData) DivNode(m_globalData, expr1, expr2, rightHasAssignments); | |
712 | } | |
713 | ||
714 | ExpressionNode* ASTBuilder::makeModNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
715 | { | |
716 | expr1 = expr1->stripUnaryPlus(); | |
717 | expr2 = expr2->stripUnaryPlus(); | |
718 | ||
719 | if (expr1->isNumber() && expr2->isNumber()) | |
720 | return createNumber(fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value())); | |
721 | return new (m_globalData) ModNode(m_globalData, expr1, expr2, rightHasAssignments); | |
722 | } | |
723 | ||
724 | ExpressionNode* ASTBuilder::makeAddNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
725 | { | |
726 | if (expr1->isNumber() && expr2->isNumber()) | |
727 | return createNumber(static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); | |
728 | return new (m_globalData) AddNode(m_globalData, expr1, expr2, rightHasAssignments); | |
729 | } | |
730 | ||
731 | ExpressionNode* ASTBuilder::makeSubNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
732 | { | |
733 | expr1 = expr1->stripUnaryPlus(); | |
734 | expr2 = expr2->stripUnaryPlus(); | |
735 | ||
736 | if (expr1->isNumber() && expr2->isNumber()) | |
737 | return createNumber(static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); | |
738 | return new (m_globalData) SubNode(m_globalData, expr1, expr2, rightHasAssignments); | |
739 | } | |
740 | ||
741 | ExpressionNode* ASTBuilder::makeLeftShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
742 | { | |
743 | if (expr1->isNumber() && expr2->isNumber()) | |
744 | return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); | |
745 | return new (m_globalData) LeftShiftNode(m_globalData, expr1, expr2, rightHasAssignments); | |
746 | } | |
747 | ||
748 | ExpressionNode* ASTBuilder::makeRightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
749 | { | |
750 | if (expr1->isNumber() && expr2->isNumber()) | |
751 | return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); | |
752 | return new (m_globalData) RightShiftNode(m_globalData, expr1, expr2, rightHasAssignments); | |
753 | } | |
754 | ||
755 | ExpressionNode* ASTBuilder::makeURightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
756 | { | |
757 | if (expr1->isNumber() && expr2->isNumber()) | |
758 | return createNumber(toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); | |
759 | return new (m_globalData) UnsignedRightShiftNode(m_globalData, expr1, expr2, rightHasAssignments); | |
760 | } | |
761 | ||
762 | ExpressionNode* ASTBuilder::makeBitOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
763 | { | |
764 | if (expr1->isNumber() && expr2->isNumber()) | |
765 | return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value())); | |
766 | return new (m_globalData) BitOrNode(m_globalData, expr1, expr2, rightHasAssignments); | |
767 | } | |
768 | ||
769 | ExpressionNode* ASTBuilder::makeBitAndNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
770 | { | |
771 | if (expr1->isNumber() && expr2->isNumber()) | |
772 | return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value())); | |
773 | return new (m_globalData) BitAndNode(m_globalData, expr1, expr2, rightHasAssignments); | |
774 | } | |
775 | ||
776 | ExpressionNode* ASTBuilder::makeBitXOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) | |
777 | { | |
778 | if (expr1->isNumber() && expr2->isNumber()) | |
779 | return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value())); | |
780 | return new (m_globalData) BitXOrNode(m_globalData, expr1, expr2, rightHasAssignments); | |
781 | } | |
782 | ||
783 | ExpressionNode* ASTBuilder::makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end) | |
784 | { | |
785 | if (!func->isLocation()) | |
786 | return new (m_globalData) FunctionCallValueNode(m_globalData, func, args, divot, divot - start, end - divot); | |
787 | if (func->isResolveNode()) { | |
788 | ResolveNode* resolve = static_cast<ResolveNode*>(func); | |
789 | const Identifier& identifier = resolve->identifier(); | |
790 | if (identifier == m_globalData->propertyNames->eval) { | |
791 | usesEval(); | |
792 | return new (m_globalData) EvalFunctionCallNode(m_globalData, args, divot, divot - start, end - divot); | |
793 | } | |
794 | return new (m_globalData) FunctionCallResolveNode(m_globalData, identifier, args, divot, divot - start, end - divot); | |
795 | } | |
796 | if (func->isBracketAccessorNode()) { | |
797 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func); | |
798 | FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(m_globalData, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot); | |
799 | node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); | |
800 | return node; | |
801 | } | |
802 | ASSERT(func->isDotAccessorNode()); | |
803 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(func); | |
804 | FunctionCallDotNode* node; | |
805 | if (dot->identifier() == m_globalData->propertyNames->call) | |
806 | node = new (m_globalData) CallFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); | |
807 | else if (dot->identifier() == m_globalData->propertyNames->apply) | |
808 | node = new (m_globalData) ApplyFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); | |
809 | else | |
810 | node = new (m_globalData) FunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); | |
811 | node->setSubexpressionInfo(dot->divot(), dot->endOffset()); | |
812 | return node; | |
813 | } | |
814 | ||
815 | ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs) | |
816 | { | |
817 | switch (token) { | |
818 | case OR: | |
819 | return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalOr); | |
820 | ||
821 | case AND: | |
822 | return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd); | |
823 | ||
824 | case BITOR: | |
825 | return makeBitOrNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
826 | ||
827 | case BITXOR: | |
828 | return makeBitXOrNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
829 | ||
830 | case BITAND: | |
831 | return makeBitAndNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
832 | ||
833 | case EQEQ: | |
834 | return new (m_globalData) EqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
835 | ||
836 | case NE: | |
837 | return new (m_globalData) NotEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
838 | ||
839 | case STREQ: | |
840 | return new (m_globalData) StrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
841 | ||
842 | case STRNEQ: | |
843 | return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
844 | ||
845 | case LT: | |
846 | return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
847 | ||
848 | case GT: | |
849 | return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
850 | ||
851 | case LE: | |
852 | return new (m_globalData) LessEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
853 | ||
854 | case GE: | |
855 | return new (m_globalData) GreaterEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
856 | ||
857 | case INSTANCEOF: { | |
858 | InstanceOfNode* node = new (m_globalData) InstanceOfNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
859 | setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); | |
860 | return node; | |
861 | } | |
862 | ||
863 | case INTOKEN: { | |
864 | InNode* node = new (m_globalData) InNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment); | |
865 | setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); | |
866 | return node; | |
867 | } | |
868 | ||
869 | case LSHIFT: | |
870 | return makeLeftShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
871 | ||
872 | case RSHIFT: | |
873 | return makeRightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
874 | ||
875 | case URSHIFT: | |
876 | return makeURightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
877 | ||
878 | case PLUS: | |
879 | return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
880 | ||
881 | case MINUS: | |
882 | return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
883 | ||
884 | case TIMES: | |
885 | return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
886 | ||
887 | case DIVIDE: | |
888 | return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
889 | ||
890 | case MOD: | |
891 | return makeModNode(lhs.first, rhs.first, rhs.second.hasAssignment); | |
892 | } | |
893 | CRASH(); | |
894 | return 0; | |
895 | } | |
896 | ||
897 | ExpressionNode* ASTBuilder::makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) | |
898 | { | |
899 | usesAssignment(); | |
900 | if (!loc->isLocation()) | |
901 | return new (m_globalData) AssignErrorNode(m_globalData, loc, op, expr, divot, divot - start, end - divot); | |
902 | ||
903 | if (loc->isResolveNode()) { | |
904 | ResolveNode* resolve = static_cast<ResolveNode*>(loc); | |
905 | if (op == OpEqual) { | |
906 | AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, resolve->identifier(), expr, exprHasAssignments); | |
907 | setExceptionLocation(node, start, divot, end); | |
908 | return node; | |
909 | } | |
910 | return new (m_globalData) ReadModifyResolveNode(m_globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); | |
911 | } | |
912 | if (loc->isBracketAccessorNode()) { | |
913 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); | |
914 | if (op == OpEqual) | |
915 | return new (m_globalData) AssignBracketNode(m_globalData, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); | |
916 | ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); | |
917 | node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); | |
918 | return node; | |
919 | } | |
920 | ASSERT(loc->isDotAccessorNode()); | |
921 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc); | |
922 | if (op == OpEqual) | |
923 | return new (m_globalData) AssignDotNode(m_globalData, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); | |
924 | ||
925 | ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(m_globalData, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); | |
926 | node->setSubexpressionInfo(dot->divot(), dot->endOffset()); | |
927 | return node; | |
928 | } | |
929 | ||
930 | ExpressionNode* ASTBuilder::makePrefixNode(ExpressionNode* expr, Operator op, int start, int divot, int end) | |
931 | { | |
932 | usesAssignment(); | |
933 | if (!expr->isLocation()) | |
934 | return new (m_globalData) PrefixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot); | |
935 | ||
936 | if (expr->isResolveNode()) { | |
937 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); | |
938 | return new (m_globalData) PrefixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot); | |
939 | } | |
940 | if (expr->isBracketAccessorNode()) { | |
941 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); | |
942 | PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); | |
943 | node->setSubexpressionInfo(bracket->divot(), bracket->startOffset()); | |
944 | return node; | |
945 | } | |
946 | ASSERT(expr->isDotAccessorNode()); | |
947 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); | |
948 | PrefixDotNode* node = new (m_globalData) PrefixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); | |
949 | node->setSubexpressionInfo(dot->divot(), dot->startOffset()); | |
950 | return node; | |
951 | } | |
952 | ||
953 | ExpressionNode* ASTBuilder::makePostfixNode(ExpressionNode* expr, Operator op, int start, int divot, int end) | |
954 | { | |
955 | usesAssignment(); | |
956 | if (!expr->isLocation()) | |
957 | return new (m_globalData) PostfixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot); | |
958 | ||
959 | if (expr->isResolveNode()) { | |
960 | ResolveNode* resolve = static_cast<ResolveNode*>(expr); | |
961 | return new (m_globalData) PostfixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot); | |
962 | } | |
963 | if (expr->isBracketAccessorNode()) { | |
964 | BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); | |
965 | PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); | |
966 | node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); | |
967 | return node; | |
968 | ||
969 | } | |
970 | ASSERT(expr->isDotAccessorNode()); | |
971 | DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); | |
972 | PostfixDotNode* node = new (m_globalData) PostfixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); | |
973 | node->setSubexpressionInfo(dot->divot(), dot->endOffset()); | |
974 | return node; | |
975 | } | |
976 | ||
977 | } | |
978 | ||
979 | #endif |