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