001: package org.python.parser;
002:
003: import org.python.parser.ast.*;
004: import org.python.core.PyObject;
005:
006: public class TreeBuilder implements PythonGrammarTreeConstants {
007: private JJTPythonGrammarState stack;
008: CtxVisitor ctx;
009:
010: public TreeBuilder(JJTPythonGrammarState stack) {
011: this .stack = stack;
012: ctx = new CtxVisitor();
013: }
014:
015: private stmtType[] makeStmts(int l) {
016: stmtType[] stmts = new stmtType[l];
017: for (int i = l - 1; i >= 0; i--) {
018: stmts[i] = (stmtType) stack.popNode();
019: }
020: return stmts;
021: }
022:
023: private stmtType[] popSuite() {
024: return ((Suite) popNode()).body;
025: }
026:
027: private exprType[] makeExprs() {
028: if (stack.nodeArity() > 0 && peekNode().getId() == JJTCOMMA)
029: popNode();
030: return makeExprs(stack.nodeArity());
031: }
032:
033: private exprType[] makeExprs(int l) {
034: exprType[] exprs = new exprType[l];
035: for (int i = l - 1; i >= 0; i--) {
036: exprs[i] = makeExpr();
037: }
038: return exprs;
039: }
040:
041: private exprType makeExpr(SimpleNode node) {
042: return (exprType) node;
043: }
044:
045: private exprType makeExpr() {
046: return makeExpr((SimpleNode) stack.popNode());
047: }
048:
049: private String makeIdentifier() {
050: return ((Name) stack.popNode()).id;
051: }
052:
053: private String[] makeIdentifiers() {
054: int l = stack.nodeArity();
055: String[] ids = new String[l];
056: for (int i = l - 1; i >= 0; i--) {
057: ids[i] = makeIdentifier();
058: }
059: return ids;
060: }
061:
062: private aliasType[] makeAliases() {
063: return makeAliases(stack.nodeArity());
064: }
065:
066: private aliasType[] makeAliases(int l) {
067: aliasType[] aliases = new aliasType[l];
068: for (int i = l - 1; i >= 0; i--) {
069: aliases[i] = (aliasType) stack.popNode();
070: }
071: return aliases;
072: }
073:
074: private static SimpleNode[] nodes = new SimpleNode[PythonGrammarTreeConstants.jjtNodeName.length];
075:
076: public SimpleNode openNode(int id) {
077: if (nodes[id] == null) {
078: if (id == JJTNAME || id == JJTSTRING || id == JJTNUM) {
079: // Names, strings and numbers are stored in the image field of
080: // their Node, so don't statically share nodes of those types.
081: return new IdentityNode(id);
082: }
083: nodes[id] = new IdentityNode(id);
084: }
085: return nodes[id];
086: }
087:
088: /**
089: * @return the image of the SimpleNode as a String, not throwing a NullPointerException when image is null
090: * @param n The SimpleNode
091: */
092: public static String getImageAsString(SimpleNode n) {
093: String imageAsString;
094: Object image = n.getImage();
095: if (image == null) {
096: imageAsString = "Incomplete node";
097: } else {
098: imageAsString = image.toString();
099: }
100: return imageAsString;
101: }
102:
103: public SimpleNode closeNode(SimpleNode n, int arity)
104: throws Exception {
105: exprType value;
106: exprType[] exprs;
107:
108: switch (n.getId()) {
109: case -1:
110: System.out.println("Illegal node");
111: case JJTSINGLE_INPUT:
112: return new Interactive(makeStmts(arity));
113: case JJTFILE_INPUT:
114: return new Module(makeStmts(arity));
115: case JJTEVAL_INPUT:
116: return new Expression(makeExpr());
117:
118: case JJTNAME:
119: return new Name(getImageAsString(n), Name.Load);
120: case JJTNUM:
121: return new Num((PyObject) n.getImage());
122: case JJTSTRING:
123: return new Str(getImageAsString(n));
124: case JJTUNICODE:
125: return new Unicode(getImageAsString(n));
126:
127: case JJTSUITE:
128: stmtType[] stmts = new stmtType[arity];
129: for (int i = arity - 1; i >= 0; i--) {
130: stmts[i] = (stmtType) popNode();
131: }
132: return new Suite(stmts);
133: case JJTEXPR_STMT:
134: value = makeExpr();
135: if (arity > 1) {
136: exprs = makeExprs(arity - 1);
137: ctx.setStore(exprs);
138: return new Assign(exprs, value);
139: } else {
140: return new Expr(value);
141: }
142: case JJTINDEX_OP:
143: sliceType slice = (sliceType) stack.popNode();
144: value = makeExpr();
145: return new Subscript(value, slice, Subscript.Load);
146: case JJTDOT_OP:
147: String attr = makeIdentifier();
148: value = makeExpr();
149: return new Attribute(value, attr, Attribute.Load);
150: case JJTDEL_STMT:
151: exprs = makeExprs(arity);
152: ctx.setDelete(exprs);
153: return new Delete(exprs);
154: case JJTPRINT_STMT:
155: boolean nl = true;
156: if (stack.nodeArity() == 0)
157: return new Print(null, null, true);
158: if (peekNode().getId() == JJTCOMMA) {
159: popNode();
160: nl = false;
161: }
162: return new Print(null, makeExprs(), nl);
163: case JJTPRINTEXT_STMT:
164: nl = true;
165: if (peekNode().getId() == JJTCOMMA) {
166: popNode();
167: nl = false;
168: }
169: exprs = makeExprs(stack.nodeArity() - 1);
170: return new Print(makeExpr(), exprs, nl);
171: case JJTFOR_STMT:
172: stmtType[] orelse = null;
173: if (stack.nodeArity() == 4)
174: orelse = popSuite();
175: stmtType[] body = popSuite();
176: exprType iter = makeExpr();
177: exprType target = makeExpr();
178: ctx.setStore(target);
179: return new For(target, iter, body, orelse);
180: case JJTWHILE_STMT:
181: orelse = null;
182: if (stack.nodeArity() == 3)
183: orelse = popSuite();
184: body = popSuite();
185: exprType test = makeExpr();
186: return new While(test, body, orelse);
187: case JJTIF_STMT:
188: orelse = null;
189: if (arity % 2 == 1)
190: orelse = popSuite();
191: body = popSuite();
192: test = makeExpr();
193: If last = new If(test, body, orelse);
194: for (int i = 0; i < (arity / 2) - 1; i++) {
195: body = popSuite();
196: test = makeExpr();
197: last = new If(test, body, new stmtType[] { last });
198: }
199: return last;
200: case JJTPASS_STMT:
201: return new Pass();
202: case JJTBREAK_STMT:
203: return new Break();
204: case JJTCONTINUE_STMT:
205: return new Continue();
206: case JJTFUNCDEF:
207: body = popSuite();
208: argumentsType arguments = makeArguments(arity - 2);
209: String name = makeIdentifier();
210: return new FunctionDef(name, arguments, body);
211: case JJTDEFAULTARG:
212: value = (arity == 1) ? null : makeExpr();
213: return new DefaultArg(makeExpr(), value);
214: case JJTEXTRAARGLIST:
215: return new ExtraArg(makeIdentifier(), JJTEXTRAARGLIST);
216: case JJTEXTRAKEYWORDLIST:
217: return new ExtraArg(makeIdentifier(), JJTEXTRAKEYWORDLIST);
218: /*
219: case JJTFPLIST:
220: fpdefType[] list = new fpdefType[arity];
221: for (int i = arity-1; i >= 0; i--) {
222: list[i] = popFpdef();
223: }
224: return new FpList(list);
225: */
226: case JJTCLASSDEF:
227: body = popSuite();
228: exprType[] bases = makeExprs(stack.nodeArity() - 1);
229: name = makeIdentifier();
230: return new ClassDef(name, bases, body);
231: case JJTRETURN_STMT:
232: value = arity == 1 ? makeExpr() : null;
233: return new Return(value);
234: case JJTYIELD_STMT:
235: return new Yield(makeExpr());
236: case JJTRAISE_STMT:
237: exprType tback = arity >= 3 ? makeExpr() : null;
238: exprType inst = arity >= 2 ? makeExpr() : null;
239: exprType type = arity >= 1 ? makeExpr() : null;
240: return new Raise(type, inst, tback);
241: case JJTGLOBAL_STMT:
242: return new Global(makeIdentifiers());
243: case JJTEXEC_STMT:
244: exprType globals = arity >= 3 ? makeExpr() : null;
245: exprType locals = arity >= 2 ? makeExpr() : null;
246: value = makeExpr();
247: return new Exec(value, locals, globals);
248: case JJTASSERT_STMT:
249: exprType msg = arity == 2 ? makeExpr() : null;
250: test = makeExpr();
251: return new Assert(test, msg);
252: case JJTTRYFINALLY_STMT:
253: orelse = popSuite();
254: return new TryFinally(popSuite(), orelse);
255: case JJTTRY_STMT:
256: orelse = null;
257: if (peekNode() instanceof Suite) {
258: arity--;
259: orelse = popSuite();
260: }
261: int l = arity - 1;
262: excepthandlerType[] handlers = new excepthandlerType[l];
263: for (int i = l - 1; i >= 0; i--) {
264: handlers[i] = (excepthandlerType) popNode();
265: }
266: return new TryExcept(popSuite(), handlers, orelse);
267: case JJTEXCEPT_CLAUSE:
268: body = popSuite();
269: exprType excname = arity == 3 ? makeExpr() : null;
270: if (excname != null)
271: ctx.setStore(excname);
272: type = arity >= 2 ? makeExpr() : null;
273: return new excepthandlerType(type, excname, body);
274: case JJTOR_BOOLEAN:
275: return new BoolOp(BoolOp.Or, makeExprs());
276: case JJTAND_BOOLEAN:
277: return new BoolOp(BoolOp.And, makeExprs());
278: case JJTCOMPARISION:
279: l = arity / 2;
280: exprType[] comparators = new exprType[l];
281: int[] ops = new int[l];
282: for (int i = l - 1; i >= 0; i--) {
283: comparators[i] = makeExpr();
284: SimpleNode op = (SimpleNode) stack.popNode();
285: switch (op.getId()) {
286: case JJTLESS_CMP:
287: ops[i] = Compare.Lt;
288: break;
289: case JJTGREATER_CMP:
290: ops[i] = Compare.Gt;
291: break;
292: case JJTEQUAL_CMP:
293: ops[i] = Compare.Eq;
294: break;
295: case JJTGREATER_EQUAL_CMP:
296: ops[i] = Compare.GtE;
297: break;
298: case JJTLESS_EQUAL_CMP:
299: ops[i] = Compare.LtE;
300: break;
301: case JJTNOTEQUAL_CMP:
302: ops[i] = Compare.NotEq;
303: break;
304: case JJTIN_CMP:
305: ops[i] = Compare.In;
306: break;
307: case JJTNOT_IN_CMP:
308: ops[i] = Compare.NotIn;
309: break;
310: case JJTIS_NOT_CMP:
311: ops[i] = Compare.IsNot;
312: break;
313: case JJTIS_CMP:
314: ops[i] = Compare.Is;
315: break;
316: default:
317: throw new RuntimeException("Unknown cmp op:"
318: + op.getId());
319: }
320: }
321: return new Compare(makeExpr(), ops, comparators);
322: case JJTLESS_CMP:
323: case JJTGREATER_CMP:
324: case JJTEQUAL_CMP:
325: case JJTGREATER_EQUAL_CMP:
326: case JJTLESS_EQUAL_CMP:
327: case JJTNOTEQUAL_CMP:
328: case JJTIN_CMP:
329: case JJTNOT_IN_CMP:
330: case JJTIS_NOT_CMP:
331: case JJTIS_CMP:
332: return n;
333: case JJTOR_2OP:
334: return makeBinOp(BinOp.BitOr);
335: case JJTXOR_2OP:
336: return makeBinOp(BinOp.BitXor);
337: case JJTAND_2OP:
338: return makeBinOp(BinOp.BitAnd);
339: case JJTLSHIFT_2OP:
340: return makeBinOp(BinOp.LShift);
341: case JJTRSHIFT_2OP:
342: return makeBinOp(BinOp.RShift);
343: case JJTADD_2OP:
344: return makeBinOp(BinOp.Add);
345: case JJTSUB_2OP:
346: return makeBinOp(BinOp.Sub);
347: case JJTMUL_2OP:
348: return makeBinOp(BinOp.Mult);
349: case JJTDIV_2OP:
350: return makeBinOp(BinOp.Div);
351: case JJTMOD_2OP:
352: return makeBinOp(BinOp.Mod);
353: case JJTPOW_2OP:
354: return makeBinOp(BinOp.Pow);
355: case JJTFLOORDIV_2OP:
356: return makeBinOp(BinOp.FloorDiv);
357: case JJTPOS_1OP:
358: return new UnaryOp(UnaryOp.UAdd, makeExpr());
359: case JJTNEG_1OP:
360: return new UnaryOp(UnaryOp.USub, makeExpr());
361: case JJTINVERT_1OP:
362: return new UnaryOp(UnaryOp.Invert, makeExpr());
363: case JJTNOT_1OP:
364: return new UnaryOp(UnaryOp.Not, makeExpr());
365: case JJTCALL_OP:
366: //if (arity == 1)
367: // return new Call(makeExpr(), null, null, null, null);
368: exprType starargs = null;
369: exprType kwargs = null;
370:
371: l = arity - 1;
372: if (l > 0 && peekNode().getId() == JJTEXTRAKEYWORDVALUELIST) {
373: kwargs = ((ExtraArgValue) popNode()).value;
374: l--;
375: }
376: if (l > 0 && peekNode().getId() == JJTEXTRAARGVALUELIST) {
377: starargs = ((ExtraArgValue) popNode()).value;
378: l--;
379: }
380:
381: int nargs = l;
382:
383: SimpleNode[] tmparr = new SimpleNode[l];
384: for (int i = l - 1; i >= 0; i--) {
385: tmparr[i] = popNode();
386: if (tmparr[i] instanceof keywordType) {
387: nargs = i;
388: }
389: }
390:
391: exprType[] args = new exprType[nargs];
392: for (int i = 0; i < nargs; i++) {
393: args[i] = makeExpr(tmparr[i]);
394: }
395:
396: keywordType[] keywords = new keywordType[l - nargs];
397: for (int i = nargs; i < l; i++) {
398: if (!(tmparr[i] instanceof keywordType))
399: throw new ParseException(
400: "non-keyword argument following keyword",
401: tmparr[i]);
402: keywords[i - nargs] = (keywordType) tmparr[i];
403: }
404: exprType func = makeExpr();
405: return new Call(func, args, keywords, starargs, kwargs);
406: case JJTEXTRAKEYWORDVALUELIST:
407: return new ExtraArgValue(makeExpr(),
408: JJTEXTRAKEYWORDVALUELIST);
409: case JJTEXTRAARGVALUELIST:
410: return new ExtraArgValue(makeExpr(), JJTEXTRAARGVALUELIST);
411: case JJTKEYWORD:
412: value = makeExpr();
413: name = makeIdentifier();
414: return new keywordType(name, value);
415: case JJTTUPLE:
416: return new Tuple(makeExprs(), Tuple.Load);
417: case JJTLIST:
418: if (stack.nodeArity() > 0
419: && peekNode() instanceof listcompType) {
420: listcompType[] generators = new listcompType[arity - 1];
421: for (int i = arity - 2; i >= 0; i--) {
422: generators[i] = (listcompType) popNode();
423: }
424: return new ListComp(makeExpr(), generators);
425: }
426: return new List(makeExprs(), List.Load);
427: case JJTDICTIONARY:
428: l = arity / 2;
429: exprType[] keys = new exprType[l];
430: exprType[] vals = new exprType[l];
431: for (int i = l - 1; i >= 0; i--) {
432: vals[i] = makeExpr();
433: keys[i] = makeExpr();
434: }
435: return new Dict(keys, vals);
436: case JJTSTR_1OP:
437: return new Repr(makeExpr());
438: case JJTSTRJOIN:
439: String str2 = ((Str) popNode()).s;
440: String str1 = ((Str) popNode()).s;
441: return new Str(str1 + str2);
442: case JJTLAMBDEF:
443: test = makeExpr();
444: arguments = makeArguments(arity - 1);
445: return new Lambda(arguments, test);
446: case JJTELLIPSES:
447: return new Ellipsis();
448: case JJTSLICE:
449: SimpleNode[] arr = new SimpleNode[arity];
450: for (int i = arity - 1; i >= 0; i--) {
451: arr[i] = popNode();
452: }
453:
454: exprType[] values = new exprType[3];
455: int k = 0;
456: for (int j = 0; j < arity; j++) {
457: if (arr[j].getId() == JJTCOLON)
458: k++;
459: else
460: values[k] = makeExpr(arr[j]);
461: }
462: if (k == 0) {
463: return new Index(values[0]);
464: } else {
465: return new Slice(values[0], values[1], values[2]);
466: }
467: case JJTSUBSCRIPTLIST:
468: if (arity > 0 && peekNode().getId() == JJTCOMMA) {
469: arity--;
470: popNode();
471: }
472: sliceType[] dims = new sliceType[arity];
473: for (int i = arity - 1; i >= 0; i--) {
474: dims[i] = (sliceType) popNode();
475: }
476: return new ExtSlice(dims);
477: case JJTAUG_PLUS:
478: return makeAugAssign(AugAssign.Add);
479: case JJTAUG_MINUS:
480: return makeAugAssign(AugAssign.Sub);
481: case JJTAUG_MULTIPLY:
482: return makeAugAssign(AugAssign.Mult);
483: case JJTAUG_DIVIDE:
484: return makeAugAssign(AugAssign.Div);
485: case JJTAUG_MODULO:
486: return makeAugAssign(AugAssign.Mod);
487: case JJTAUG_AND:
488: return makeAugAssign(AugAssign.BitAnd);
489: case JJTAUG_OR:
490: return makeAugAssign(AugAssign.BitOr);
491: case JJTAUG_XOR:
492: return makeAugAssign(AugAssign.BitXor);
493: case JJTAUG_LSHIFT:
494: return makeAugAssign(AugAssign.LShift);
495: case JJTAUG_RSHIFT:
496: return makeAugAssign(AugAssign.RShift);
497: case JJTAUG_POWER:
498: return makeAugAssign(AugAssign.Pow);
499: case JJTAUG_FLOORDIVIDE:
500: return makeAugAssign(AugAssign.FloorDiv);
501: case JJTLIST_FOR:
502: exprType[] ifs = new exprType[arity - 2];
503: for (int i = arity - 3; i >= 0; i--) {
504: ifs[i] = makeExpr();
505: }
506: iter = makeExpr();
507: target = makeExpr();
508: ctx.setStore(target);
509: return new listcompType(target, iter, ifs);
510: case JJTIMPORTFROM:
511: aliasType[] aliases = makeAliases(arity - 1);
512: String module = makeIdentifier();
513: return new ImportFrom(module, aliases);
514: case JJTIMPORT:
515: return new Import(makeAliases());
516:
517: case JJTDOTTED_NAME:
518: StringBuffer sb = new StringBuffer();
519: for (int i = 0; i < arity; i++) {
520: if (i > 0)
521: sb.insert(0, '.');
522: sb.insert(0, makeIdentifier());
523: }
524: return new Name(sb.toString(), Name.Load);
525:
526: case JJTDOTTED_AS_NAME:
527: String asname = null;
528: if (arity > 1)
529: asname = makeIdentifier();
530: return new aliasType(makeIdentifier(), asname);
531:
532: case JJTIMPORT_AS_NAME:
533: asname = null;
534: if (arity > 1)
535: asname = makeIdentifier();
536: return new aliasType(makeIdentifier(), asname);
537: case JJTCOMMA:
538: case JJTCOLON:
539: return n;
540: default:
541: return null;
542: }
543: }
544:
545: private stmtType makeAugAssign(int op) throws Exception {
546: exprType value = makeExpr();
547: exprType target = makeExpr();
548: ctx.setAugStore(target);
549: return new AugAssign(target, op, value);
550: }
551:
552: private void dumpStack() {
553: int n = stack.nodeArity();
554: System.out.println("nodeArity:" + n);
555: if (n > 0) {
556: System.out.println("peek:" + stack.peekNode());
557: }
558: }
559:
560: SimpleNode peekNode() {
561: return (SimpleNode) stack.peekNode();
562: }
563:
564: SimpleNode popNode() {
565: return (SimpleNode) stack.popNode();
566: }
567:
568: BinOp makeBinOp(int op) {
569: exprType right = makeExpr();
570: exprType left = makeExpr();
571: return new BinOp(left, op, right);
572: }
573:
574: argumentsType makeArguments(int l) throws Exception {
575: String kwarg = null;
576: String stararg = null;
577: if (l > 0 && peekNode().getId() == JJTEXTRAKEYWORDLIST) {
578: kwarg = ((ExtraArg) popNode()).name;
579: l--;
580: }
581: if (l > 0 && peekNode().getId() == JJTEXTRAARGLIST) {
582: stararg = ((ExtraArg) popNode()).name;
583: l--;
584: }
585: int startofdefaults = l;
586: exprType fpargs[] = new exprType[l];
587: exprType defaults[] = new exprType[l];
588: for (int i = l - 1; i >= 0; i--) {
589: DefaultArg node = (DefaultArg) popNode();
590: fpargs[i] = node.parameter;
591: ctx.setStore(fpargs[i]);
592: defaults[i] = node.value;
593: if (node.value != null)
594: startofdefaults = i;
595: }
596: //System.out.println("start "+ startofdefaults + " " + l);
597: exprType[] newdefs = new exprType[l - startofdefaults];
598: System.arraycopy(defaults, startofdefaults, newdefs, 0,
599: newdefs.length);
600:
601: return new argumentsType(fpargs, stararg, kwarg, newdefs);
602: }
603: }
604:
605: class DefaultArg extends SimpleNode {
606: public exprType parameter;
607: public exprType value;
608:
609: DefaultArg(exprType parameter, exprType value) {
610: this .parameter = parameter;
611: this .value = value;
612: }
613: }
614:
615: class ExtraArg extends SimpleNode {
616: public String name;
617: public int id;
618:
619: ExtraArg(String name, int id) {
620: this .name = name;
621: this .id = id;
622: }
623:
624: public int getId() {
625: return id;
626: }
627: }
628:
629: class ExtraArgValue extends SimpleNode {
630: public exprType value;
631: public int id;
632:
633: ExtraArgValue(exprType value, int id) {
634: this .value = value;
635: this .id = id;
636: }
637:
638: public int getId() {
639: return id;
640: }
641: }
642:
643: class IdentityNode extends SimpleNode {
644: public int id;
645: public Object image;
646:
647: IdentityNode(int id) {
648: this .id = id;
649: }
650:
651: public int getId() {
652: return id;
653: }
654:
655: public void setImage(Object image) {
656: this .image = image;
657: }
658:
659: public Object getImage() {
660: return image;
661: }
662:
663: public String toString() {
664: return "IdNode[" + PythonGrammarTreeConstants.jjtNodeName[id]
665: + ", " + image + "]";
666: }
667: }
668:
669: class CtxVisitor extends Visitor {
670: private int ctx;
671:
672: public CtxVisitor() {
673: }
674:
675: public void setStore(SimpleNode node) throws Exception {
676: this .ctx = expr_contextType.Store;
677: visit(node);
678: }
679:
680: public void setStore(SimpleNode[] nodes) throws Exception {
681: for (int i = 0; i < nodes.length; i++)
682: setStore(nodes[i]);
683: }
684:
685: public void setDelete(SimpleNode node) throws Exception {
686: this .ctx = expr_contextType.Del;
687: visit(node);
688: }
689:
690: public void setDelete(SimpleNode[] nodes) throws Exception {
691: for (int i = 0; i < nodes.length; i++)
692: setDelete(nodes[i]);
693: }
694:
695: public void setAugStore(SimpleNode node) throws Exception {
696: this .ctx = expr_contextType.AugStore;
697: visit(node);
698: }
699:
700: public Object visitName(Name node) throws Exception {
701: node.ctx = ctx;
702: return null;
703: }
704:
705: public Object visitAttribute(Attribute node) throws Exception {
706: node.ctx = ctx;
707: return null;
708: }
709:
710: public Object visitSubscript(Subscript node) throws Exception {
711: node.ctx = ctx;
712: return null;
713: }
714:
715: public Object visitList(List node) throws Exception {
716: if (ctx == expr_contextType.AugStore) {
717: throw new ParseException(
718: "augmented assign to list not possible", node);
719: }
720: node.ctx = ctx;
721: traverse(node);
722: return null;
723: }
724:
725: public Object visitTuple(Tuple node) throws Exception {
726: if (ctx == expr_contextType.AugStore) {
727: throw new ParseException(
728: "augmented assign to tuple not possible", node);
729: }
730: node.ctx = ctx;
731: traverse(node);
732: return null;
733: }
734:
735: public Object visitCall(Call node) throws Exception {
736: throw new ParseException("can't assign to function call", node);
737: }
738:
739: public Object visitListComp(Call node) throws Exception {
740: throw new ParseException(
741: "can't assign to list comprehension call", node);
742: }
743:
744: public Object unhandled_node(SimpleNode node) throws Exception {
745: throw new ParseException("can't assign to operator", node);
746: }
747: }
|