File: | platform/mac/avmshell/../../../eval/eval-parse-expr.cpp |
Location: | line 449, column 39 |
Description: | Access to field 'hd' results in a dereference of a null pointer (loaded from variable 'arguments') |
1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ | ||
2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ | ||
3 | /* ***** BEGIN LICENSE BLOCK ***** | ||
4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
5 | * | ||
6 | * The contents of this file are subject to the Mozilla Public License Version | ||
7 | * 1.1 (the "License"); you may not use this file except in compliance with | ||
8 | * the License. You may obtain a copy of the License at | ||
9 | * http://www.mozilla.org/MPL/ | ||
10 | * | ||
11 | * Software distributed under the License is distributed on an "AS IS" basis, | ||
12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
13 | * for the specific language governing rights and limitations under the | ||
14 | * License. | ||
15 | * | ||
16 | * The Original Code is [Open Source Virtual Machine.]. | ||
17 | * | ||
18 | * The Initial Developer of the Original Code is | ||
19 | * Adobe System Incorporated. | ||
20 | * Portions created by the Initial Developer are Copyright (C) 2008 | ||
21 | * the Initial Developer. All Rights Reserved. | ||
22 | * | ||
23 | * Contributor(s): | ||
24 | * Adobe AS3 Team | ||
25 | * | ||
26 | * Alternatively, the contents of this file may be used under the terms of | ||
27 | * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
29 | * in which case the provisions of the GPL or the LGPL are applicable instead | ||
30 | * of those above. If you wish to allow use of your version of this file only | ||
31 | * under the terms of either the GPL or the LGPL, and not to allow others to | ||
32 | * use your version of this file under the terms of the MPL, indicate your | ||
33 | * decision by deleting the provisions above and replace them with the notice | ||
34 | * and other provisions required by the GPL or the LGPL. If you do not delete | ||
35 | * the provisions above, a recipient may use your version of this file under | ||
36 | * the terms of any one of the MPL, the GPL or the LGPL. | ||
37 | * | ||
38 | * ***** END LICENSE BLOCK ***** */ | ||
39 | |||
40 | #include "avmplus.h" | ||
41 | |||
42 | #ifdef VMCFG_EVAL | ||
43 | |||
44 | #include "eval.h" | ||
45 | |||
46 | namespace avmplus | ||
47 | { | ||
48 | namespace RTC | ||
49 | { | ||
50 | NameComponent::~NameComponent() {} | ||
51 | |||
52 | QualifiedName* Parser::typeExpression() | ||
53 | { | ||
54 | if (match(T_Multiply)) | ||
55 | return NULL__null; | ||
56 | QualifiedName* n = nameExpression(falsefalse); | ||
57 | if ((n->qualifier != NULL__null && n->qualifier->tag() != TAG_simpleName) || | ||
58 | n->name->tag() != TAG_simpleName) | ||
59 | compiler->syntaxError(n->pos, SYNTAXERR_ILLEGAL_TYPENAME); | ||
60 | if (hd() == T_LeftDotAngle) | ||
61 | compiler->internalError(position(), "Unimplemented: Cannot parse vector types"); | ||
62 | return n; | ||
63 | } | ||
64 | |||
65 | QualifiedName* Parser::nameExpression(boolbool is_attr) | ||
66 | { | ||
67 | uint32_t pos = position(); | ||
68 | Str* name = NULL__null; | ||
69 | NameComponent* n = NULL__null; | ||
70 | if (match(T_Multiply)) | ||
71 | n = ALLOC(WildcardName, ())::new (allocator->alloc(sizeof(WildcardName))) WildcardName (); | ||
72 | else if (match(T_Public)) { | ||
73 | n = ALLOC(BuiltinNamespace, (T_Public))::new (allocator->alloc(sizeof(BuiltinNamespace))) BuiltinNamespace (T_Public); | ||
74 | } | ||
75 | else if (match(T_Protected)) { | ||
76 | n = ALLOC(BuiltinNamespace, (T_Protected))::new (allocator->alloc(sizeof(BuiltinNamespace))) BuiltinNamespace (T_Protected); | ||
77 | } | ||
78 | else if (match(T_Private)) { | ||
79 | n = ALLOC(BuiltinNamespace, (T_Private))::new (allocator->alloc(sizeof(BuiltinNamespace))) BuiltinNamespace (T_Private); | ||
80 | } | ||
81 | else if (match(T_Internal)) { | ||
82 | n = ALLOC(BuiltinNamespace, (T_Internal))::new (allocator->alloc(sizeof(BuiltinNamespace))) BuiltinNamespace (T_Internal); | ||
83 | } | ||
84 | else { | ||
85 | name = identifier(); | ||
86 | n = ALLOC(SimpleName, (name))::new (allocator->alloc(sizeof(SimpleName))) SimpleName (name ); | ||
87 | } | ||
88 | if (match(T_DoubleColon)) { | ||
89 | if (match(T_Multiply)) | ||
90 | return ALLOC(QualifiedName, (n, ALLOC(WildcardName, ()), is_attr, pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (n, ::new (allocator->alloc(sizeof(WildcardName))) WildcardName (), is_attr, pos); | ||
91 | if (match(T_LeftBracket)) { | ||
92 | Expr* e = commaExpression(0); | ||
93 | eat(T_RightBracket); | ||
94 | return ALLOC(QualifiedName, (n, ALLOC(ComputedName, (e)), is_attr, pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (n, ::new (allocator->alloc(sizeof(ComputedName))) ComputedName (e), is_attr, pos); | ||
95 | } | ||
96 | return ALLOC(QualifiedName, (n, ALLOC(SimpleName, (identifier())), is_attr, pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (n, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName (identifier()), is_attr, pos); | ||
97 | } | ||
98 | else { | ||
99 | if (name == compiler->SYM_arguments) | ||
100 | setUsesArguments(); | ||
101 | return ALLOC(QualifiedName, (NULL, n, is_attr, pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (__null, n, is_attr, pos); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | Expr* Parser::exprListToCommaExpr(Seq<Expr*>* es) { | ||
106 | Expr* expr = es->hd; | ||
107 | for ( es=es->tl ; es != NULL__null ; es = es->tl ) | ||
108 | expr = ALLOC(BinaryExpr, (OPR_comma, expr, es->hd))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_comma , expr, es->hd); | ||
109 | return expr; | ||
110 | } | ||
111 | |||
112 | Expr* Parser::objectInitializer () | ||
113 | { | ||
114 | uint32_t pos = position(); | ||
115 | eat (T_LeftBrace); | ||
116 | Seq<LiteralField*>* fields = fieldList(); | ||
117 | eat (T_RightBrace); | ||
118 | |||
119 | return ALLOC(LiteralObject, (fields, pos))::new (allocator->alloc(sizeof(LiteralObject))) LiteralObject (fields, pos); | ||
120 | } | ||
121 | |||
122 | Seq<LiteralField*>* Parser::fieldList () | ||
123 | { | ||
124 | SeqBuilder<LiteralField*> fields(allocator); | ||
125 | if (hd () != T_RightBrace) { | ||
126 | do { | ||
127 | LiteralField* f = literalField(); | ||
128 | if (f != NULL__null) | ||
129 | fields.addAtEnd(f); | ||
130 | } while (match(T_Comma)); | ||
131 | } | ||
132 | return fields.get(); | ||
133 | } | ||
134 | |||
135 | LiteralField* Parser::literalField() | ||
136 | { | ||
137 | Str* name = NULL__null; | ||
138 | QualifiedName* config = NULL__null; | ||
139 | again: | ||
140 | switch (hd ()) { | ||
141 | case T_StringLiteral: | ||
142 | name = stringValue(); | ||
143 | break; | ||
144 | |||
145 | case T_IntLiteral: | ||
146 | name = doubleToStr(intValue()); | ||
147 | break; | ||
148 | |||
149 | case T_UIntLiteral: | ||
150 | name = doubleToStr(uintValue()); | ||
151 | break; | ||
152 | |||
153 | case T_DoubleLiteral: | ||
154 | name = doubleToStr(doubleValue()); | ||
155 | break; | ||
156 | |||
157 | case T_Identifier: { | ||
158 | if (hd2() != T_DoubleColon) { | ||
159 | name = identValue(); | ||
160 | break; | ||
161 | } | ||
162 | // This must be a program configuration expression | ||
163 | if (config != NULL__null) | ||
164 | compiler->syntaxError(position(), SYNTAXERR_DUPLICATE_CONFIG); | ||
165 | Expr* e = assignmentExpression(0); | ||
166 | if (!isConfigReference(e)) | ||
167 | compiler->syntaxError(position(), SYNTAXERR_CONFIG_REQUIRED); | ||
168 | config = (QualifiedName*)e; | ||
169 | goto again; | ||
170 | } | ||
171 | |||
172 | default: | ||
173 | compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_FIELDNAME); | ||
174 | break; | ||
175 | } | ||
176 | next(); | ||
177 | match(T_Colon); | ||
178 | Expr* expr = assignmentExpression(0); | ||
179 | if (config == NULL__null || evaluateConfigReference(config)) | ||
180 | return ALLOC(LiteralField, (name, expr))::new (allocator->alloc(sizeof(LiteralField))) LiteralField (name, expr); | ||
181 | return NULL__null; | ||
182 | } | ||
183 | |||
184 | Expr* Parser::arrayInitializer () | ||
185 | { | ||
186 | uint32_t pos = position(); | ||
187 | eat (T_LeftBracket); | ||
188 | Seq<Expr*>* elts = elementList(); | ||
189 | eat (T_RightBracket); | ||
190 | return ALLOC(LiteralArray, (elts, pos))::new (allocator->alloc(sizeof(LiteralArray))) LiteralArray (elts, pos); | ||
191 | } | ||
192 | |||
193 | Seq<Expr*>* Parser::elementList() | ||
194 | { | ||
195 | SeqBuilder<Expr*> elts(allocator); | ||
196 | Expr* elt = NULL__null; | ||
197 | |||
198 | for (;;) { | ||
199 | switch (hd()) { | ||
200 | case T_RightBracket: | ||
201 | goto end_loop; | ||
202 | |||
203 | case T_Comma: { | ||
204 | eat(T_Comma); | ||
205 | if (elt == NULL__null) | ||
206 | elt = NULL__null; | ||
207 | elts.addAtEnd(elt); | ||
208 | elt = NULL__null; | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | default: | ||
213 | if (elt != NULL__null) | ||
214 | eat(T_Comma); | ||
215 | elt = assignmentExpression(0); | ||
216 | if (hd() != T_RightBracket && hd() != T_Comma) { | ||
217 | // This must be a program configuration expression | ||
218 | if (!isConfigReference(elt)) | ||
219 | compiler->syntaxError(position(), SYNTAXERR_CONFIG_REQUIRED); | ||
220 | boolbool result = evaluateConfigReference((QualifiedName*)elt); | ||
221 | elt = assignmentExpression(0); | ||
222 | if (!result) | ||
223 | elt = NULL__null; | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | end_loop: | ||
229 | if (elt != NULL__null) | ||
230 | elts.addAtEnd(elt); | ||
231 | |||
232 | return elts.get(); | ||
233 | } | ||
234 | |||
235 | Expr* Parser::functionExpression() | ||
236 | { | ||
237 | Qualifier qual; | ||
238 | return ALLOC(LiteralFunction, (functionGuts(&qual, false, false, true)))::new (allocator->alloc(sizeof(LiteralFunction))) LiteralFunction (functionGuts(&qual, false, false, true)); | ||
239 | } | ||
240 | |||
241 | Expr* Parser::primaryExpression() | ||
242 | { | ||
243 | if (hd() == T_BreakSlash) | ||
244 | regexp(); | ||
245 | |||
246 | uint32_t pos = position(); // Record the source location before consuming the token | ||
247 | switch (hd ()) { | ||
248 | case T_Null: | ||
249 | next(); | ||
250 | return ALLOC(LiteralNull, (pos))::new (allocator->alloc(sizeof(LiteralNull))) LiteralNull ( pos); | ||
251 | |||
252 | case T_True: | ||
253 | case T_False: { | ||
254 | boolbool flag = hd() == T_True; | ||
255 | next(); | ||
256 | return ALLOC(LiteralBoolean, (flag, pos))::new (allocator->alloc(sizeof(LiteralBoolean))) LiteralBoolean (flag, pos); | ||
257 | } | ||
258 | |||
259 | case T_IntLiteral: { | ||
260 | int32_t i = intValue(); | ||
261 | next(); | ||
262 | return ALLOC(LiteralInt, (i, pos))::new (allocator->alloc(sizeof(LiteralInt))) LiteralInt (i , pos); | ||
263 | } | ||
264 | |||
265 | case T_UIntLiteral: { | ||
266 | uint32_t u = uintValue(); | ||
267 | next(); | ||
268 | return ALLOC(LiteralUInt, (u, pos))::new (allocator->alloc(sizeof(LiteralUInt))) LiteralUInt ( u, pos); | ||
269 | } | ||
270 | |||
271 | case T_DoubleLiteral: { | ||
272 | double d = doubleValue(); | ||
273 | next(); | ||
274 | return ALLOC(LiteralDouble, (d, pos))::new (allocator->alloc(sizeof(LiteralDouble))) LiteralDouble (d, pos); | ||
275 | } | ||
276 | |||
277 | case T_StringLiteral: { | ||
278 | Str* s = stringValue(); | ||
279 | next(); | ||
280 | return ALLOC(LiteralString, (s, pos))::new (allocator->alloc(sizeof(LiteralString))) LiteralString (s, pos); | ||
281 | } | ||
282 | |||
283 | case T_RegexpLiteral: { | ||
284 | Str* r = regexValue(); | ||
285 | next(); | ||
286 | return ALLOC(LiteralRegExp, (r, pos))::new (allocator->alloc(sizeof(LiteralRegExp))) LiteralRegExp (r, pos); | ||
287 | } | ||
288 | |||
289 | case T_This: | ||
290 | next(); | ||
291 | return ALLOC(ThisExpr, ())::new (allocator->alloc(sizeof(ThisExpr))) ThisExpr (); | ||
292 | |||
293 | case T_Super: | ||
294 | return superExpression(); | ||
295 | |||
296 | case T_LeftParen: | ||
297 | return parenExpression(); | ||
298 | |||
299 | case T_LeftBracket: | ||
300 | return arrayInitializer (); | ||
301 | |||
302 | case T_LeftBrace: | ||
303 | return objectInitializer (); | ||
304 | |||
305 | case T_Function: | ||
306 | return functionExpression (); | ||
307 | |||
308 | case T_BreakLeftAngle: | ||
309 | return xmlInitializer(); | ||
310 | |||
311 | case T_AtSign: | ||
312 | return attributeIdentifier(); | ||
313 | |||
314 | default: | ||
315 | break; | ||
316 | } | ||
317 | |||
318 | return nameExpression(); | ||
319 | } | ||
320 | |||
321 | QualifiedName* Parser::attributeIdentifier() | ||
322 | { | ||
323 | eat(T_AtSign); | ||
324 | if (hd() == T_LeftBracket) { | ||
325 | eat(T_LeftBracket); | ||
326 | Expr* e = commaExpression(0); | ||
327 | eat(T_RightBracket); | ||
328 | return ALLOC(QualifiedName, (NULL, ALLOC(ComputedName, (e)), true, 0))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (__null, ::new (allocator->alloc(sizeof(ComputedName))) ComputedName (e), true, 0); | ||
329 | } | ||
330 | else | ||
331 | return nameExpression(truetrue); | ||
332 | } | ||
333 | |||
334 | QualifiedName* Parser::propertyIdentifier() | ||
335 | { | ||
336 | switch (hd()) { | ||
337 | case T_Multiply: | ||
338 | case T_AtSign: | ||
339 | case T_Identifier: | ||
340 | return (QualifiedName*)primaryExpression(); | ||
341 | default: | ||
342 | compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_PROPNAME); | ||
343 | /*NOTREACHED*/ | ||
344 | return NULL__null; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | Expr* Parser::propertyOperator(Expr* obj) | ||
349 | { | ||
350 | uint32_t pos = position(); | ||
351 | switch (hd ()) { | ||
352 | case T_Dot: { | ||
353 | eat(T_Dot); | ||
354 | if (hd() == T_LeftParen) | ||
355 | return ALLOC(FilterExpr, (obj, parenExpression(), pos))::new (allocator->alloc(sizeof(FilterExpr))) FilterExpr (obj , parenExpression(), pos); | ||
356 | if (hd() == T_AtSign) | ||
357 | return ALLOC(ObjectRef, (obj, attributeIdentifier(), pos))::new (allocator->alloc(sizeof(ObjectRef))) ObjectRef (obj , attributeIdentifier(), pos); | ||
358 | // Begin keyword hacks | ||
359 | // FIXME | ||
360 | // Allow 'namespace' to be used as a property name | ||
361 | if (hd() == T_Namespace) { | ||
362 | eat(T_Namespace); | ||
363 | return ALLOC(ObjectRef, (obj, ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (compiler->SYM_namespace)), false, pos)), pos))::new (allocator->alloc(sizeof(ObjectRef))) ObjectRef (obj , ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName (compiler->SYM_namespace), false, pos), pos); | ||
364 | } | ||
365 | // End keyword hacks | ||
366 | return ALLOC(ObjectRef, (obj, nameExpression(), pos))::new (allocator->alloc(sizeof(ObjectRef))) ObjectRef (obj , nameExpression(), pos); | ||
367 | } | ||
368 | case T_DoubleDot: { | ||
369 | eat(T_DoubleDot); | ||
370 | return ALLOC(DescendantsExpr, (obj, propertyIdentifier(), pos))::new (allocator->alloc(sizeof(DescendantsExpr))) DescendantsExpr (obj, propertyIdentifier(), pos); | ||
371 | }; | ||
372 | case T_LeftBracket: { | ||
373 | eat(T_LeftBracket); | ||
374 | Expr* expr = commaExpression(0); | ||
375 | eat (T_RightBracket); | ||
376 | return ALLOC(ObjectRef, (obj, ALLOC(QualifiedName, (NULL, ALLOC(ComputedName, (expr)), false, pos)), pos))::new (allocator->alloc(sizeof(ObjectRef))) ObjectRef (obj , ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName (__null, ::new (allocator->alloc(sizeof(ComputedName))) ComputedName (expr), false, pos), pos); | ||
377 | } | ||
378 | case T_LeftDotAngle: | ||
379 | compiler->internalError(position(), "Unimplemented: Cannot parse vector syntax"); | ||
380 | default: | ||
381 | compiler->internalError(position(), "Unexpected token in propertyOperator: %d", (int)hd()); | ||
382 | /*NOTREACHED*/ | ||
383 | return NULL__null; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | Seq<Expr*>* Parser::argumentList () | ||
388 | { | ||
389 | SeqBuilder<Expr*> exprs(allocator); | ||
390 | |||
391 | eat(T_LeftParen); | ||
392 | if (hd() != T_RightParen) { | ||
393 | do { | ||
394 | exprs.addAtEnd(assignmentExpression(0)); | ||
395 | } while (match(T_Comma)); | ||
396 | } | ||
397 | eat(T_RightParen); | ||
398 | return exprs.get(); | ||
399 | } | ||
400 | |||
401 | Expr* Parser::memberExpression () | ||
402 | { | ||
403 | switch (hd ()) { | ||
404 | case T_New: { | ||
405 | next(); | ||
406 | if (hd() == T_BreakLeftAngle) { | ||
407 | // vector initializer | ||
408 | compiler->internalError(position(), "Unimplemented: Cannot parse vector initializer"); | ||
409 | } | ||
410 | Expr* object_expr = memberExpression (); | ||
411 | Seq<Expr*>* argument_exprs = argumentList(); | ||
412 | return memberExpressionPrime (ALLOC(NewExpr, (object_expr, argument_exprs))::new (allocator->alloc(sizeof(NewExpr))) NewExpr (object_expr , argument_exprs)); | ||
413 | } | ||
414 | |||
415 | default: { | ||
416 | Expr* expr = primaryExpression (); | ||
417 | return memberExpressionPrime (expr); | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | Expr* Parser::memberExpressionPrime (Expr* expr) | ||
423 | { | ||
424 | switch (hd ()) { | ||
425 | case T_LeftBracket: | ||
426 | case T_Dot: | ||
427 | case T_DoubleDot: | ||
428 | case T_LeftDotAngle: | ||
429 | return memberExpressionPrime (propertyOperator (expr)); | ||
430 | default: | ||
431 | return expr; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | Expr* Parser::superExpression () | ||
436 | { | ||
437 | eat (T_Super); | ||
438 | uint32_t pos = position(); | ||
439 | Seq<Expr*>* arguments = NULL__null; | ||
440 | boolbool argsPresent = falsefalse; | ||
441 | if (hd() == T_LeftParen) { | ||
| |||
442 | argsPresent = truetrue; | ||
443 | arguments = argumentList(); | ||
444 | } | ||
445 | if (argsPresent && (arguments == NULL__null || arguments->tl != NULL__null)) | ||
| |||
446 | compiler->syntaxError(pos, SYNTAXERR_ONE_ARGUMENT_REQUIRED); | ||
447 | if (hd() != T_Dot && hd() != T_LeftBracket) | ||
| |||
448 | compiler->syntaxError(pos, SYNTAXERR_PROPERTY_OPERATOR_REQUIRED); | ||
449 | Expr* obj = argsPresent ? arguments->hd : ALLOC(ThisExpr, ())::new (allocator->alloc(sizeof(ThisExpr))) ThisExpr (); | ||
| |||
| |||
450 | return propertyOperator(ALLOC(SuperExpr, (obj))::new (allocator->alloc(sizeof(SuperExpr))) SuperExpr (obj )); | ||
451 | } | ||
452 | |||
453 | Expr* Parser::callExpression () | ||
454 | { | ||
455 | uint32_t pos = position(); | ||
456 | Expr* object_expr = memberExpression (); | ||
457 | Seq<Expr*>* argument_exprs = argumentList(); | ||
458 | |||
459 | return callExpressionPrime (ALLOC(CallExpr, (object_expr, argument_exprs, pos))::new (allocator->alloc(sizeof(CallExpr))) CallExpr (object_expr , argument_exprs, pos)); | ||
460 | } | ||
461 | |||
462 | // shared among many | ||
463 | Expr* Parser::callExpressionPrime (Expr* call_expr) | ||
464 | { | ||
465 | switch (hd ()) { | ||
466 | case T_LeftParen: | ||
467 | { | ||
468 | uint32_t pos = position(); | ||
469 | Seq<Expr*>* argument_exprs = argumentList(); | ||
470 | return callExpressionPrime (ALLOC(CallExpr, (call_expr, argument_exprs, pos))::new (allocator->alloc(sizeof(CallExpr))) CallExpr (call_expr , argument_exprs, pos)); | ||
471 | } | ||
472 | case T_LeftBracket: | ||
473 | case T_Dot: | ||
474 | case T_LeftDotAngle: | ||
475 | return callExpressionPrime (propertyOperator (call_expr)); | ||
476 | default: | ||
477 | return call_expr; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | Expr* Parser::newExpression (int new_count) | ||
482 | { | ||
483 | Expr* call_expression; | ||
484 | |||
485 | boolbool is_new = match(T_New); | ||
486 | if (is_new) { | ||
487 | if (hd() == T_LessThan) { | ||
488 | // vector initializer | ||
489 | compiler->internalError(position(), "Unimplemented: Cannot parse vector initializer"); | ||
490 | } | ||
491 | call_expression = newExpression (new_count+1); | ||
492 | } | ||
493 | else | ||
494 | call_expression = memberExpression(); | ||
495 | |||
496 | if (hd() == T_LeftParen) { // No more new exprs so this paren must start a call expr | ||
497 | uint32_t pos = position(); | ||
498 | Seq<Expr*>* argument_exprs = argumentList(); | ||
499 | if (new_count > 0) | ||
500 | return ALLOC(NewExpr, (call_expression, argument_exprs))::new (allocator->alloc(sizeof(NewExpr))) NewExpr (call_expression , argument_exprs); | ||
501 | return callExpressionPrime (ALLOC(CallExpr, (call_expression, argument_exprs, pos))::new (allocator->alloc(sizeof(CallExpr))) CallExpr (call_expression , argument_exprs, pos)); | ||
502 | } | ||
503 | |||
504 | if (new_count > 0) | ||
505 | return ALLOC(NewExpr, (call_expression, NULL))::new (allocator->alloc(sizeof(NewExpr))) NewExpr (call_expression , __null); | ||
506 | |||
507 | if (is_new) | ||
508 | return memberExpressionPrime (call_expression); | ||
509 | |||
510 | return call_expression; | ||
511 | } | ||
512 | |||
513 | Expr* Parser::leftHandSideExpression () | ||
514 | { | ||
515 | Expr* oper = (hd() == T_New) ? newExpression (0) : memberExpression (); | ||
516 | if (hd () == T_LeftParen) { | ||
517 | uint32_t pos = position(); | ||
518 | Seq<Expr*>* args = argumentList(); | ||
519 | return callExpressionPrime(ALLOC(CallExpr, (oper, args, pos))::new (allocator->alloc(sizeof(CallExpr))) CallExpr (oper, args, pos)); | ||
520 | } | ||
521 | return oper; | ||
522 | } | ||
523 | |||
524 | Expr* Parser::postfixExpression () | ||
525 | { | ||
526 | Expr* expr = leftHandSideExpression (); | ||
527 | if (noNewline()) { | ||
528 | if (match(T_PlusPlus)) | ||
529 | return ALLOC(UnaryExpr, (OPR_postIncr, expr))::new (allocator->alloc(sizeof(UnaryExpr))) UnaryExpr (OPR_postIncr , expr); | ||
530 | if (match(T_MinusMinus)) | ||
531 | return ALLOC(UnaryExpr, (OPR_postDecr, expr))::new (allocator->alloc(sizeof(UnaryExpr))) UnaryExpr (OPR_postDecr , expr); | ||
532 | } | ||
533 | return expr; | ||
534 | } | ||
535 | |||
536 | Expr* Parser::unaryExpression() | ||
537 | { | ||
538 | Token t; | ||
539 | |||
540 | switch (t = hd ()) { | ||
541 | case T_Delete: | ||
542 | next(); | ||
543 | return ALLOC(UnaryExpr, (OPR_delete, postfixExpression()))::new (allocator->alloc(sizeof(UnaryExpr))) UnaryExpr (OPR_delete , postfixExpression()); | ||
544 | |||
545 | case T_PlusPlus: | ||
546 | case T_MinusMinus: | ||
547 | next(); | ||
548 | return ALLOC(UnaryExpr, (tokenToUnaryOperator(t), postfixExpression()))::new (allocator->alloc(sizeof(UnaryExpr))) UnaryExpr (tokenToUnaryOperator (t), postfixExpression()); | ||
549 | |||
550 | case T_Void: | ||
551 | case T_TypeOf: | ||
552 | case T_Plus: | ||
553 | case T_Minus: | ||
554 | case T_BitwiseNot: | ||
555 | case T_Not: | ||
556 | next(); | ||
557 | return ALLOC(UnaryExpr, (tokenToUnaryOperator(t), unaryExpression()))::new (allocator->alloc(sizeof(UnaryExpr))) UnaryExpr (tokenToUnaryOperator (t), unaryExpression()); | ||
558 | |||
559 | default: | ||
560 | return postfixExpression(); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | Expr* Parser::multiplicativeExpression() | ||
565 | { | ||
566 | Expr* expr = unaryExpression(); | ||
567 | Token t; | ||
568 | |||
569 | while (isMultiplicative(t = hd()) || t == T_BreakSlash) { | ||
570 | if (t == T_BreakSlash) { | ||
571 | divideOperator(); | ||
572 | if (!isMultiplicative(t = hd())) | ||
573 | break; | ||
574 | } | ||
575 | next(); | ||
576 | expr = ALLOC(BinaryExpr, (tokenToBinaryOperator(t), expr, unaryExpression()))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (tokenToBinaryOperator (t), expr, unaryExpression()); | ||
577 | } | ||
578 | return expr; | ||
579 | } | ||
580 | |||
581 | Expr* Parser::additiveExpression() | ||
582 | { | ||
583 | Expr* expr = multiplicativeExpression(); | ||
584 | Token t; | ||
585 | |||
586 | while (isAdditive(t = hd())) { | ||
587 | next(); | ||
588 | expr = ALLOC(BinaryExpr, (tokenToBinaryOperator(t), expr, multiplicativeExpression()))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (tokenToBinaryOperator (t), expr, multiplicativeExpression()); | ||
589 | } | ||
590 | return expr; | ||
591 | } | ||
592 | |||
593 | Expr* Parser::shiftExpression() | ||
594 | { | ||
595 | Expr* expr = additiveExpression(); | ||
596 | Token t; | ||
597 | |||
598 | while (isShift(t = hd()) || t == T_BreakLeftAngle || t == T_BreakRightAngle) { | ||
599 | if (t == T_BreakLeftAngle) { | ||
600 | leftShiftOrRelationalOperator(); | ||
601 | if (!isShift(t = hd())) | ||
602 | break; | ||
603 | } | ||
604 | else if (t == T_BreakRightAngle) { | ||
605 | rightShiftOrRelationalOperator(); | ||
606 | if (!isShift(t = hd())) | ||
607 | break; | ||
608 | } | ||
609 | next(); | ||
610 | expr = ALLOC(BinaryExpr, (tokenToBinaryOperator(t), expr, additiveExpression()))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (tokenToBinaryOperator (t), expr, additiveExpression()); | ||
611 | } | ||
612 | |||
613 | return expr; | ||
614 | } | ||
615 | |||
616 | Expr* Parser::relationalExpression(int flags) | ||
617 | { | ||
618 | Expr* expr = shiftExpression(); | ||
619 | Token t; | ||
620 | boolbool allowIn = !(flags & EFLAG_NoIn); | ||
621 | |||
622 | for (;;) { | ||
623 | if (!(isRelational(t = hd(), allowIn) || t == T_BreakLeftAngle || t == T_BreakRightAngle)) | ||
624 | break; | ||
625 | if (t == T_BreakLeftAngle) { | ||
626 | leftShiftOrRelationalOperator(); | ||
627 | if (!isRelational(t = hd(), allowIn)) | ||
628 | break; | ||
629 | } | ||
630 | else if (t == T_BreakRightAngle) { | ||
631 | rightShiftOrRelationalOperator(); | ||
632 | if (!isRelational(t = hd(), allowIn)) | ||
633 | break; | ||
634 | } | ||
635 | next(); | ||
636 | expr = ALLOC(BinaryExpr, (tokenToBinaryOperator(t), expr, shiftExpression()))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (tokenToBinaryOperator (t), expr, shiftExpression()); | ||
637 | } | ||
638 | |||
639 | return expr; | ||
640 | } | ||
641 | |||
642 | Expr* Parser::equalityExpression(int flags) | ||
643 | { | ||
644 | Expr* expr = relationalExpression(flags); | ||
645 | Token t; | ||
646 | |||
647 | while (isEquality(t = hd())) { | ||
648 | next(); | ||
649 | expr = ALLOC(BinaryExpr, (tokenToBinaryOperator(t), expr, relationalExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (tokenToBinaryOperator (t), expr, relationalExpression(flags)); | ||
650 | } | ||
651 | return expr; | ||
652 | } | ||
653 | |||
654 | Expr* Parser::bitwiseAndExpression(int flags) | ||
655 | { | ||
656 | Expr* expr = equalityExpression(flags); | ||
657 | while (match(T_BitwiseAnd)) | ||
658 | expr = ALLOC(BinaryExpr, (OPR_bitwiseAnd, expr, equalityExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_bitwiseAnd , expr, equalityExpression(flags)); | ||
659 | return expr; | ||
660 | } | ||
661 | |||
662 | Expr* Parser::bitwiseXorExpression(int flags) | ||
663 | { | ||
664 | Expr* expr = bitwiseAndExpression(flags); | ||
665 | while (match(T_BitwiseXor)) | ||
666 | expr = ALLOC(BinaryExpr, (OPR_bitwiseXor, expr, bitwiseAndExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_bitwiseXor , expr, bitwiseAndExpression(flags)); | ||
667 | return expr; | ||
668 | } | ||
669 | |||
670 | Expr* Parser::bitwiseOrExpression(int flags) | ||
671 | { | ||
672 | Expr* expr = bitwiseXorExpression(flags); | ||
673 | while (match(T_BitwiseOr)) | ||
674 | expr = ALLOC(BinaryExpr, (OPR_bitwiseOr, expr, bitwiseXorExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_bitwiseOr , expr, bitwiseXorExpression(flags)); | ||
675 | return expr; | ||
676 | } | ||
677 | |||
678 | Expr* Parser::logicalAndExpression(int flags) | ||
679 | { | ||
680 | Expr* expr = bitwiseOrExpression(flags); | ||
681 | while (match(T_LogicalAnd)) | ||
682 | expr = ALLOC(BinaryExpr, (OPR_logicalAnd, expr, bitwiseOrExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_logicalAnd , expr, bitwiseOrExpression(flags)); | ||
683 | return expr; | ||
684 | } | ||
685 | |||
686 | Expr* Parser::logicalOrExpression(int flags) | ||
687 | { | ||
688 | Expr* expr = logicalAndExpression(flags); | ||
689 | while (match(T_LogicalOr)) | ||
690 | expr = ALLOC(BinaryExpr, (OPR_logicalOr, expr, logicalAndExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_logicalOr , expr, logicalAndExpression(flags)); | ||
691 | return expr; | ||
692 | } | ||
693 | |||
694 | Expr* Parser::nonAssignmentExpression(int flags) | ||
695 | { | ||
696 | Expr* expr = logicalOrExpression(flags); | ||
697 | if (!match(T_Question)) | ||
698 | return expr; | ||
699 | |||
700 | Expr* consequent = nonAssignmentExpression(flags); | ||
701 | eat (T_Colon); | ||
702 | Expr* alternate = nonAssignmentExpression(flags); | ||
703 | return ALLOC(ConditionalExpr, (expr, consequent, alternate))::new (allocator->alloc(sizeof(ConditionalExpr))) ConditionalExpr (expr, consequent, alternate); | ||
704 | } | ||
705 | |||
706 | Expr* Parser::conditionalExpression(int flags) | ||
707 | { | ||
708 | Expr* expr = logicalOrExpression(flags); | ||
709 | if (!match(T_Question)) | ||
710 | return expr; | ||
711 | |||
712 | Expr* consequent = assignmentExpression(flags); | ||
713 | eat (T_Colon); | ||
714 | Expr* alternate = assignmentExpression(flags); | ||
715 | return ALLOC(ConditionalExpr, (expr, consequent, alternate))::new (allocator->alloc(sizeof(ConditionalExpr))) ConditionalExpr (expr, consequent, alternate); | ||
716 | } | ||
717 | |||
718 | Expr* Parser::assignmentExpression(int flags) | ||
719 | { | ||
720 | Expr* lhs = conditionalExpression(flags); | ||
721 | Token t; | ||
722 | |||
723 | if (!((t = hd()) == T_Assign || isOpAssign(t) || t == T_BreakLeftAngle || t == T_BreakRightAngle)) | ||
724 | return lhs; | ||
725 | |||
726 | if (t == T_BreakLeftAngle) { | ||
727 | leftShiftOrRelationalOperator(); | ||
728 | if (!isOpAssign(t = hd())) | ||
729 | return lhs; | ||
730 | } | ||
731 | else if (t == T_BreakRightAngle) { | ||
732 | rightShiftOrRelationalOperator(); | ||
733 | if (!isOpAssign(t = hd())) | ||
734 | return lhs; | ||
735 | } | ||
736 | |||
737 | eat(t); | ||
738 | Expr* rhs = assignmentExpression (flags); | ||
739 | return ALLOC(AssignExpr, (tokenToBinaryOperator(t), lhs, rhs))::new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (tokenToBinaryOperator (t), lhs, rhs); | ||
740 | } | ||
741 | |||
742 | Expr* Parser::commaExpression(int flags) | ||
743 | { | ||
744 | Expr* expr = assignmentExpression(flags); | ||
745 | while (match(T_Comma)) | ||
746 | expr = ALLOC(BinaryExpr, (OPR_comma, expr, assignmentExpression(flags)))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_comma , expr, assignmentExpression(flags)); | ||
747 | return expr; | ||
748 | } | ||
749 | |||
750 | Expr* Parser::parenExpression() | ||
751 | { | ||
752 | eat (T_LeftParen); | ||
753 | Expr* expr = commaExpression(0); | ||
754 | eat (T_RightParen); | ||
755 | |||
756 | return expr; | ||
757 | } | ||
758 | } | ||
759 | } | ||
760 | |||
761 | #endif // VMCFG_EVAL |