View Javadoc

1   /***
2    *
3    * Copyright 2004 James Strachan
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  package org.codehaus.groovy.antlr;
19  
20  import antlr.RecognitionException;
21  import antlr.TokenStreamException;
22  import antlr.NoViableAltException;
23  import antlr.collections.AST;
24  import com.thoughtworks.xstream.XStream;
25  import org.codehaus.groovy.antlr.parser.GroovyLexer;
26  import org.codehaus.groovy.antlr.parser.GroovyRecognizer;
27  import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
28  import org.codehaus.groovy.ast.*;
29  import org.codehaus.groovy.ast.expr.*;
30  import org.codehaus.groovy.ast.stmt.*;
31  import org.codehaus.groovy.control.CompilationFailedException;
32  import org.codehaus.groovy.control.ParserPlugin;
33  import org.codehaus.groovy.control.SourceUnit;
34  import org.codehaus.groovy.syntax.Numbers;
35  import org.codehaus.groovy.syntax.Reduction;
36  import org.codehaus.groovy.syntax.Token;
37  import org.codehaus.groovy.syntax.Types;
38  import org.codehaus.groovy.syntax.parser.ASTHelper;
39  import org.codehaus.groovy.syntax.parser.ParserException;
40  import org.objectweb.asm.Constants;
41  
42  import java.io.FileWriter;
43  import java.io.Reader;
44  import java.util.ArrayList;
45  import java.util.Iterator;
46  import java.util.List;
47  
48  /***
49   * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime
50   *
51   * @author <a href="mailto:jstrachan@protique.com">James Strachan</a>
52   * @version $Revision: 1.24 $
53   */
54  public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
55      private static final Type OBJECT_TYPE = new Type("java.lang.Object", true);
56  
57      private AST ast;
58      private ClassNode classNode;
59      private String[] tokenNames;
60  
61  
62      public Reduction parseCST(SourceUnit sourceUnit, Reader reader) throws CompilationFailedException {
63          ast = null;
64  
65          setController(sourceUnit);
66  
67          UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(reader);
68          GroovyLexer lexer = new GroovyLexer(unicodeReader);
69          unicodeReader.setLexer(lexer);
70          GroovyRecognizer parser = GroovyRecognizer.make(lexer);
71          tokenNames = parser.getTokenNames();
72          parser.setFilename(sourceUnit.getName());
73  
74          // start parsing at the compilationUnit rule
75          try {
76              parser.compilationUnit();
77          }
78          catch (RecognitionException e) {
79              sourceUnit.addException(e);
80          }
81          catch (TokenStreamException e) {
82              sourceUnit.addException(e);
83          }
84  
85          ast = parser.getAST();
86  
87          if ("xml".equals(System.getProperty("antlr.ast"))) {
88              saveAsXML(sourceUnit.getName(), ast);
89          }
90  
91          return null; //new Reduction(Tpken.EOF);
92      }
93  
94      private void saveAsXML(String name, AST ast) {
95          XStream xstream = new XStream();
96          try {
97              xstream.toXML(ast, new FileWriter(name + ".antlr.xml"));
98              System.out.println("Written AST to " + name + ".antlr.xml");
99          }
100         catch (Exception e) {
101             System.out.println("Couldn't write to " + name + ".antlr.xml");
102             e.printStackTrace();
103         }
104     }
105 
106     public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException {
107         setClassLoader(classLoader);
108         makeModule();
109         try {
110             convertGroovy(ast);
111         }
112         catch (ASTRuntimeException e) {
113             throw new ASTParserException(e.getMessage() + ". File: " + sourceUnit.getName(), e);
114         }
115         return output;
116     }
117 
118     /***
119      * Converts the Antlr AST to the Groovy AST
120      */
121     protected void convertGroovy(AST node) {
122         while (node != null) {
123             int type = node.getType();
124             switch (type) {
125                 case PACKAGE_DEF:
126                     packageDef(node);
127                     break;
128 
129                 case IMPORT:
130                     importDef(node);
131                     break;
132 
133                 case CLASS_DEF:
134                     classDef(node);
135                     break;
136 
137                 case METHOD_DEF:
138                     methodDef(node);
139                     break;
140 
141                 default:
142                     {
143                         Statement statement = statement(node);
144                         output.addStatement(statement);
145                     }
146             }
147             node = node.getNextSibling();
148         }
149     }
150 
151     // Top level control structures
152     //-------------------------------------------------------------------------
153 
154     protectedong> void packageDef(AST packageDef) {
155         AST node = packageDef.getFirstChild();
156         if (isType(ANNOTATIONS, node)) {
157             node = node.getNextSibling();
158         }
159         String name = qualifiedName(node);
160         setPackageName(name);
161     }
162 
163     protected void importDef(AST importNode) {
164         AST node = importNode.getFirstChild();
165         if (isType(LITERAL_as, node)) {
166             AST dotNode = node.getFirstChild();
167             AST packageNode = dotNode.getFirstChild();
168             AST classNode = packageNode.getNextSibling();
169             String packageName = qualifiedName(packageNode);
170             String name = qualifiedName(classNode);
171             String alias = identifier(dotNode.getNextSibling());
172             importClass(packageName, name, alias);
173         }
174         else {
175             AST packageNode = node.getFirstChild();
176             String packageName = qualifiedName(packageNode);
177             AST nameNode = packageNode.getNextSibling();
178             if (isType(STAR, nameNode)) {
179                 importPackageWithStar(packageName);
180             }
181             else {
182                 String name = qualifiedName(nameNode);
183                 importClass(packageName, name, name);
184             }
185         }
186     }
187 
188     protected void classDef(AST classDef) {
189         List annotations = new ArrayList();
190         AST node = classDef.getFirstChild();
191         int modifiers = Constants.ACC_PUBLIC;
192         if (isType(MODIFIERS, node)) {
193             modifiers = modifiers(node, annotations, modifiers);
194             node = node.getNextSibling();
195         }
196 
197         String name = identifier(node);
198         node = node.getNextSibling();
199 
200         String superClass = null;
201         if (isType(EXTENDS_CLAUSE, node)) {
202             superClass = typeName(node);
203             node = node.getNextSibling();
204         }
205         if (superClass == null) {
206             superClass = "java.lang.Object";
207         }
208 
209         String[] interfaces = {};
210         if (isType(IMPLEMENTS_CLAUSE, node)) {
211             interfaces = interfaces(node);
212             node = node.getNextSibling();
213         }
214 
215         // TODO read mixins
216         MixinNode[] mixins = {};
217 
218         addNewClassName(name);
219         String fullClassName = dot(getPackageName(), name);
220         classNode = new ClassNode(fullClassName, modifiers, superClass, interfaces, mixins);
221         classNode.addAnnotations(annotations);
222         configureAST(classNode, classDef);
223 
224         assertNodeType(OBJBLOCK, node);
225         objectBlock(node);
226         output.addClass(classNode);
227         classNode = null;
228     }
229 
230     protected void objectBlock(AST objectBlock) {
231         for (AST node = objectBlock.getFirstChild(); node != null; node = node.getNextSibling()) {
232             int type = node.getType();
233             switch (type) {
234                 case OBJBLOCK:
235                     objectBlock(node);
236                     break;
237 
238                 case METHOD_DEF:
239                     methodDef(node);
240                     break;
241 
242                 case CTOR_IDENT:
243                     constructorDef(node);
244                     break;
245 
246                 case VARIABLE_DEF:
247                     fieldDef(node);
248                     break;
249 
250                 default:
251                     unknownAST(node);
252             }
253         }
254     }
255 
256     protected void methodDef(AST methodDef) {
257         List annotations = new ArrayList();
258         AST node = methodDef.getFirstChild();
259         int modifiers = Constants.ACC_PUBLIC;
260         if (isType(MODIFIERS, node)) {
261             modifiers = modifiers(node, annotations, modifiers);
262             node = node.getNextSibling();
263         }
264 
265         String returnType = null;
266 
267         if (isType(TYPE, node)) {
268             returnType = typeName(node);
269             node = node.getNextSibling();
270         }
271 
272         String name = identifier(node);
273         if (classNode != null) {
274             if (classNode.getNameWithoutPackage().equals(name)) {
275                 throw new ASTRuntimeException(methodDef, "Invalid constructor format. Try remove the 'def' expression?");
276             }
277         }
278         node = node.getNextSibling();
279 
280         assertNodeType(PARAMETERS, node);
281         Parameter[] parameters = parameters(node);
282         node = node.getNextSibling();
283 
284         assertNodeType(SLIST, node);
285         Statement code = statementList(node);
286 
287         MethodNode methodNode = new MethodNode(name, modifiers, returnType, parameters, code);
288         methodNode.addAnnotations(annotations);
289         configureAST(methodNode, methodDef);
290         if (classNode != null) {
291             classNode.addMethod(methodNode);
292         }
293         else {
294             output.addMethod(methodNode);
295         }
296     }
297 
298     protected void constructorDef(AST constructorDef) {
299         List annotations = new ArrayList();
300         AST node = constructorDef.getFirstChild();
301         int modifiers = Constants.ACC_PUBLIC;
302         if (isType(MODIFIERS, node)) {
303             modifiers = modifiers(node, annotations, modifiers);
304             node = node.getNextSibling();
305         }
306 
307         assertNodeType(PARAMETERS, node);
308         Parameter[] parameters = parameters(node);
309         node = node.getNextSibling();
310 
311         assertNodeType(SLIST, node);
312         Statement code = statementList(node);
313 
314         ConstructorNode constructorNode = classNode.addConstructor(modifiers, parameters, code);
315         constructorNode.addAnnotations(annotations);
316         configureAST(constructorNode, constructorDef);
317     }
318 
319     protected void fieldDef(AST fieldDef) {
320         List annotations = new ArrayList();
321         AST node = fieldDef.getFirstChild();
322 
323         int modifiers = 0;
324         if (isType(MODIFIERS, node)) {
325             modifiers = modifiers(node, annotations, modifiers);
326             node = node.getNextSibling();
327         }
328 
329         String type = null;
330         if (isType(TYPE, node)) {
331             type = typeName(node);
332             node = node.getNextSibling();
333         }
334 
335         String name = identifier(node);
336         node = node.getNextSibling();
337 
338         Expression initialValue = null;
339         if (node != null) {
340             assertNodeType(ASSIGN, node);
341             initialValue = expression(node);
342         }
343 
344 
345         FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
346         fieldNode.addAnnotations(annotations);
347         configureAST(fieldNode, fieldDef);
348 
349         // lets check for a property annotation first
350         if (fieldNode.getAnnotations("Property") != null) {
351             // lets set the modifiers on the field
352             int fieldModifiers = 0;
353             int flags = Constants.ACC_STATIC | Constants.ACC_TRANSIENT | Constants.ACC_VOLATILE | Constants.ACC_FINAL;
354 
355             // lets pass along any other modifiers we need
356             fieldModifiers |= (modifiers & flags);
357             fieldNode.setModifiers(fieldModifiers);
358 
359             if (!hasVisibility(modifiers)) {
360                 modifiers |= Constants.ACC_PUBLIC;
361             }
362             PropertyNode propertyNode = new PropertyNode(fieldNode, modifiers, null, null);
363             configureAST(propertyNode, fieldDef);
364             classNode.addProperty(propertyNode);
365         }
366         else {
367             /*
368             if (!hasVisibility(modifiers)) {
369                 modifiers |= Constants.ACC_PRIVATE;
370                 fieldNode.setModifiers(modifiers);
371             }
372             */
373             fieldNode.setModifiers(modifiers);
374 
375             classNode.addField(fieldNode);
376         }
377     }
378 
379     protected String[] interfaces(AST node) {
380         List interfaceList = new ArrayList();
381         for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode.getNextSibling()) {
382             interfaceList.add(resolveTypeName(qualifiedName(implementNode)));
383         }
384         String[] interfaces = {};
385         if (!interfaceList.isEmpty()) {
386             interfaces = new String[interfaceList.size()];
387             interfaceList.toArray(interfaces);
388 
389         }
390         return interfaces;
391     }
392 
393     protected Parameter[] parameters(AST parametersNode) {
394         AST node = parametersNode.getFirstChild();
395         if (node == null) {
396             return Parameter.EMPTY_ARRAY;
397         }
398         else {
399             List parameters = new ArrayList();
400             do {
401                 parameters.add(parameter(node));
402                 node = node.getNextSibling();
403             }
404             while (node != null);
405             Parameter[] answer = new Parameter[parameters.size()];
406             parameters.toArray(answer);
407             return answer;
408         }
409     }
410 
411     protected Parameter parameter(AST paramNode) {
412         List annotations = new ArrayList();
413         AST node = paramNode.getFirstChild();
414 
415         int modifiers = 0;
416         if (isType(MODIFIERS, node)) {
417             modifiers = modifiers(node, annotations, modifiers);
418             node = node.getNextSibling();
419         }
420         assertNodeType(TYPE, node);
421         String type = typeName(node);
422 
423         node = node.getNextSibling();
424 
425         String name = identifier(node);
426 
427         Expression defaultValue = null;
428         node = node.getNextSibling();
429         if (node != null) {
430             defaultValue = expression(node);
431         }
432         Parameter parameter = new Parameter(type, name, defaultValue);
433         // TODO
434         //configureAST(parameter,paramNode);
435         //parameter.addAnnotations(annotations);
436         return parameter;
437     }
438 
439     protected int modifiers(AST modifierNode, List annotations, int defaultModifiers) {
440         assertNodeType(MODIFIERS, modifierNode);
441 
442         boolean access = false;
443         int answer = 0;
444 
445         for (AST node = modifierNode.getFirstChild(); node != null; node = node.getNextSibling()) {
446             int type = node.getType();
447             switch (type) {
448                 // annotations
449                 case ANNOTATION:
450                     annotations.add(annotation(node));
451                     break;
452 
453 
454                     // core access scope modifiers
455                 case LITERAL_private:
456                     answer = setModifierBit(node, answer, Constants.ACC_PRIVATE);
457                     access = setAccessTrue(node, access);
458                     break;
459 
460                 case LITERAL_protected:
461                     answer = setModifierBit(node, answer, Constants.ACC_PROTECTED);
462                     access = setAccessTrue(node, access);
463                     break;
464 
465                 case LITERAL_public:
466                     answer = setModifierBit(node, answer, Constants.ACC_PUBLIC);
467                     access = setAccessTrue(node, access);
468                     break;
469 
470                     // other modifiers
471                 case ABSTRACT:
472                     answer = setModifierBit(node, answer, Constants.ACC_ABSTRACT);
473                     break;
474 
475                 case FINAL:
476                     answer = setModifierBit(node, answer, Constants.ACC_FINAL);
477                     break;
478 
479                 case LITERAL_native:
480                     answer = setModifierBit(node, answer, Constants.ACC_NATIVE);
481                     break;
482 
483                 case LITERAL_static:
484                     answer = setModifierBit(node, answer, Constants.ACC_STATIC);
485                     break;
486 
487                 case STRICTFP:
488                     answer = setModifierBit(node, answer, Constants.ACC_STRICT);
489                     break;
490 
491                 case LITERAL_synchronized:
492                     answer = setModifierBit(node, answer, Constants.ACC_SYNCHRONIZED);
493                     break;
494 
495                 case LITERAL_transient:
496                     answer = setModifierBit(node, answer, Constants.ACC_TRANSIENT);
497                     break;
498 
499                 case LITERAL_volatile:
500                     answer = setModifierBit(node, answer, Constants.ACC_VOLATILE);
501                     break;
502 
503                 default:
504                     unknownAST(node);
505             }
506         }
507         if (!access) {
508             answer |= defaultModifiers;
509         }
510         return answer;
511     }
512 
513     protected boolean setAccessTrue(AST node, boolean access) {
514         if (!access) {
515             return true;
516         }
517         else {
518             throw new ASTRuntimeException(node, "Cannot specify modifier: " + node.getText() + " when access scope has already been defined");
519         }
520     }
521 
522     protected int setModifierBit(AST node, int answer, int bit) {
523         if ((answer & bit) != 0) {
524             throw new ASTRuntimeException(node, "Cannot repeat modifier: " + node.getText());
525         }
526         return answer | bit;
527     }
528 
529     protected AnnotationNode annotation(AST annotationNode) {
530         AST node = annotationNode.getFirstChild();
531         String name = identifier(node);
532         AnnotationNode annotatedNode = new AnnotationNode(name);
533         configureAST(annotatedNode, node);
534         while (true) {
535             node = node.getNextSibling();
536             if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) {
537                 AST memberNode = node.getFirstChild();
538                 String param = identifier(memberNode);
539                 Expression expression = expression(memberNode.getNextSibling());
540                 annotatedNode.addMember(param, expression);
541             }
542             else {
543                 break;
544             }
545         }
546         return annotatedNode;
547     }
548 
549 
550 
551     // Statements
552     //-------------------------------------------------------------------------
553 
554     protected Statement statement(AST node) {
555         Statement statement = null;
556         int type = node.getType();
557         switch (type) {
558             case SLIST:
559             case LITERAL_finally:
560                 statement = statementList(node);
561                 break;
562 
563             case METHOD_CALL:
564                 statement = methodCall(node);
565                 break;
566 
567             case VARIABLE_DEF:
568                 statement = variableDef(node);
569                 break;
570 
571 
572             case LABELED_STAT:
573                 statement = labelledStatement(node);
574                 break;
575 
576             case LITERAL_assert:
577                 statement = assertStatement(node);
578                 break;
579 
580             case LITERAL_break:
581                 statement = breakStatement(node);
582                 break;
583 
584             case LITERAL_continue:
585                 statement = continueStatement(node);
586                 break;
587 
588             case LITERAL_if:
589                 statement = ifStatement(node);
590                 break;
591 
592             case LITERAL_for:
593                 statement = forStatement(node);
594                 break;
595 
596             case LITERAL_return:
597                 statement = returnStatement(node);
598                 break;
599 
600             case LITERAL_synchronized:
601                 statement = synchronizedStatement(node);
602                 break;
603 
604             case LITERAL_switch:
605                 statement = switchStatement(node);
606                 break;
607 
608             case LITERAL_with:
609                 statement = withStatement(node);
610                 break;
611 
612             case LITERAL_try:
613                 statement = tryStatement(node);
614                 break;
615 
616             case LITERAL_throw:
617                 statement = throwStatement(node);
618                 break;
619 
620             case LITERAL_while:
621                 statement = whileStatement(node);
622                 break;
623 
624             default:
625                 statement = new ExpressionStatement(expression(node));
626         }
627         if (statement != null) {
628             configureAST(statement, node);
629         }
630         return statement;
631     }
632 
633     protected Statement statementList(AST code) {
634         return statementListNoChild(code.getFirstChild());
635     }
636 
637     protected Statement statementListNoChild(AST node) {
638         BlockStatement block = new BlockStatement();
639         // no need to configureAST(block,node); as node is probably null
640         for (; node != null; node = node.getNextSibling()) {
641             block.addStatement(statement(node));
642         }
643         return block;
644     }
645 
646     protected Statement assertStatement(AST assertNode) {
647         AST node = assertNode.getFirstChild();
648         BooleanExpression booleanExpression = booleanExpression(node);
649         Expression messageExpression = null;
650 
651         node = node.getNextSibling();
652         if (node != null) {
653             messageExpression = expression(node);
654         }
655         else {
656             messageExpression = ConstantExpression.NULL;
657         }
658         AssertStatement assertStatement = new AssertStatement(booleanExpression, messageExpression);
659         configureAST(assertStatement, assertNode);
660         return assertStatement;
661     }
662 
663     protected Statement breakStatement(AST node) {
664         BreakStatement breakStatement = new BreakStatement(label(node));
665         configureAST(breakStatement, node);
666         return breakStatement;
667     }
668 
669     protected Statement continueStatement(AST node) {
670         ContinueStatement continueStatement = new ContinueStatement(label(node));
671         configureAST(continueStatement, node);
672         return continueStatement;
673     }
674 
675     protected Statement forStatement(AST forNode) {
676         AST inNode = forNode.getFirstChild();
677         AST variableNode = inNode.getFirstChild();
678         AST collectionNode = variableNode.getNextSibling();
679 
680         Type type = OBJECT_TYPE;
681         if (isType(VARIABLE_DEF, variableNode)) {
682             AST typeNode = variableNode.getFirstChild();
683             assertNodeType(TYPE, typeNode);
684 
685             type = type(typeNode);
686             variableNode = typeNode.getNextSibling();
687         }
688         String variable = identifier(variableNode);
689 
690         Expression collectionExpression = expression(collectionNode);
691         Statement block = statement(inNode.getNextSibling());
692 
693         ForStatement forStatement = new ForStatement(variable, type, collectionExpression, block);
694         configureAST(forStatement, forNode);
695         return forStatement;
696     }
697 
698     protected Statement ifStatement(AST ifNode) {
699         AST node = ifNode.getFirstChild();
700         assertNodeType(EXPR, node);
701         BooleanExpression booleanExpression = booleanExpression(node);
702 
703         node = node.getNextSibling();
704         // this node could be a BREAK node
705         //assertNodeType(SLIST, node);
706         Statement ifBlock = statement(node);
707 
708         Statement elseBlock = EmptyStatement.INSTANCE;
709         node = node.getNextSibling();
710         if (node != null) {
711             elseBlock = statement(node);
712         }
713         IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
714         configureAST(ifStatement, ifNode);
715         return ifStatement;
716     }
717 
718     protected Statement labelledStatement(AST labelNode) {
719         AST node = labelNode.getFirstChild();
720         String label = identifier(node);
721         Statement statement = statement(node.getNextSibling());
722         statement.setStatementLabel(label);
723         return statement;
724     }
725 
726     protected Statement methodCall(AST code) {
727         Expression expression = methodCallExpression(code);
728         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
729         configureAST(expressionStatement, code);
730         return expressionStatement;
731     }
732 
733     protected Statement variableDef(AST variableDef) {
734         AST node = variableDef.getFirstChild();
735         String type = null;
736         if (isType(MODIFIERS, node)) {
737             node = node.getNextSibling();
738         }
739         if (isType(TYPE, node)) {
740             type = typeName(node);
741             node = node.getNextSibling();
742         }
743 
744         String name = identifier(node);
745         node = node.getNextSibling();
746 
747         Expression leftExpression = new VariableExpression(name, type);
748         configureAST(leftExpression, variableDef);
749 
750         Expression rightExpression = ConstantExpression.NULL;
751         if (node != null) {
752             assertNodeType(ASSIGN, node);
753 
754             rightExpression = expression(node.getFirstChild());
755         }
756         Token token = makeToken(Types.ASSIGN, variableDef);
757 
758         // TODO should we have a variable declaration statement?
759         BinaryExpression expression = new BinaryExpression(leftExpression, token, rightExpression);
760         configureAST(expression, variableDef);
761         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
762         configureAST(expressionStatement, variableDef);
763         return expressionStatement;
764     }
765 
766     protected Statement returnStatement(AST node) {
767         AST exprNode = node.getFirstChild();
768         
769         // This will pick up incorrect sibling node if 'node' is a plain 'return'
770 		//
771 		//if (exprNode == null) {
772         //    exprNode = node.getNextSibling();
773         //}
774         if (exprNode != null) {
775             Expression expression = expression(exprNode);
776             if (expression instanceof ConstantExpression) {
777                 ConstantExpression constantExpr = (ConstantExpression) expression;
778                 if (constantExpr.getValue() == null) {
779                     return ReturnStatement.RETURN_NULL_OR_VOID;
780                 }
781             }
782             ReturnStatement returnStatement = new ReturnStatement(expression);
783             configureAST(returnStatement, node);
784             return returnStatement;
785         }
786         else {
787             return ReturnStatement.RETURN_NULL_OR_VOID;
788         }
789     }
790 
791     protected Statement switchStatement(AST switchNode) {
792         AST node = switchNode.getFirstChild();
793         Expression expression = expression(node);
794         Statement defaultStatement = EmptyStatement.INSTANCE;
795 
796         List list = new ArrayList();
797         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
798             AST child = node.getFirstChild();
799             if (isType(LITERAL_case, child)) {
800                 list.add(caseStatement(child));
801             }
802             else {
803                 defaultStatement = statement(child.getNextSibling());
804             }
805         }
806         if (node != null) {
807             unknownAST(node);
808         }
809         SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
810         configureAST(switchStatement, switchNode);
811         return switchStatement;
812     }
813 
814     protected CaseStatement caseStatement(AST node) {
815         Expression expression = expression(node.getFirstChild());
816         AST nextSibling = node.getNextSibling();
817         Statement statement = EmptyStatement.INSTANCE;
818         if (!isType(LITERAL_default, nextSibling)) {
819              statement = statement(nextSibling);
820         }
821         CaseStatement answer = new CaseStatement(expression, statement);
822         configureAST(answer, node);
823         return answer;
824     }
825 
826     protected Statement synchronizedStatement(AST syncNode) {
827         AST node = syncNode.getFirstChild();
828         Expression expression = expression(node);
829         Statement code = statement(node.getNextSibling());
830         SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
831         configureAST(synchronizedStatement, syncNode);
832         return synchronizedStatement;
833     }
834 
835     protected Statement throwStatement(AST node) {
836         AST expressionNode = node.getFirstChild();
837         if (expressionNode == null) {
838             expressionNode = node.getNextSibling();
839         }
840         if (expressionNode == null) {
841             throw new ASTRuntimeException(node, "No expression available");
842         }
843         ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
844         configureAST(throwStatement, node);
845         return throwStatement;
846     }
847 
848     protected Statement tryStatement(AST tryStatementNode) {
849         AST tryNode = tryStatementNode.getFirstChild();
850         Statement tryStatement = statement(tryNode);
851         Statement finallyStatement = EmptyStatement.INSTANCE;
852         AST node = tryNode.getNextSibling();
853 
854         // lets do the catch nodes
855         List catches = new ArrayList();
856         for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
857             catches.add(catchStatement(node));
858         }
859 
860         if (isType(LITERAL_finally, node)) {
861             finallyStatement = statement(node);
862             node = node.getNextSibling();
863         }
864 
865         TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
866         configureAST(tryCatchStatement, tryStatementNode);
867         for (Iterator iter = catches.iterator(); iter.hasNext();) {
868             CatchStatement statement = (CatchStatement) iter.next();
869             tryCatchStatement.addCatch(statement);
870         }
871         return tryCatchStatement;
872     }
873 
874     protected CatchStatement catchStatement(AST catchNode) {
875         AST node = catchNode.getFirstChild();
876         Parameter parameter = parameter(node);
877         String exceptionType = parameter.getType();
878         String variable = parameter.getName();
879         node = node.getNextSibling();
880         Statement code = statement(node);
881         CatchStatement answer = new CatchStatement(exceptionType, variable, code);
882         configureAST(answer, catchNode);
883         return answer;
884     }
885 
886     protected Statement whileStatement(AST whileNode) {
887         AST node = whileNode.getFirstChild();
888         assertNodeType(EXPR, node);
889         BooleanExpression booleanExpression = booleanExpression(node);
890 
891         node = node.getNextSibling();
892         assertNodeType(SLIST, node);
893         Statement block = statement(node);
894         WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
895         configureAST(whileStatement, whileNode);
896         return whileStatement;
897     }
898 
899     protected Statement withStatement(AST node) {
900         notImplementedYet(node);
901         return null; /*** TODO */
902     }
903 
904 
905 
906     // Expressions
907     //-------------------------------------------------------------------------
908 
909     protected Expression expression(AST node) {
910         Expression expression = expressionSwitch(node);
911         configureAST(expression, node);
912         return expression;
913     }
914 
915     protected Expression expressionSwitch(AST node) {
916         int type = node.getType();
917         switch (type) {
918             case EXPR:
919                 return expression(node.getFirstChild());
920 
921             case ELIST:
922                 return expressionList(node);
923 
924             case SLIST:
925                 return blockExpression(node);
926 
927             case CLOSED_BLOCK:
928                 return closureExpression(node);
929 
930             case SUPER_CTOR_CALL:
931                 return superMethodCallExpression(node);
932 
933             case METHOD_CALL:
934                 return methodCallExpression(node);
935 
936             case LITERAL_new:
937                 return constructorCallExpression(node.getFirstChild());
938 
939             case CTOR_CALL:
940                 return constructorCallExpression(node);
941 
942             case QUESTION:
943                 return ternaryExpression(node);
944 
945             case OPTIONAL_DOT:
946             case SPREAD_DOT:
947             case DOT:
948                 return dotExpression(node);
949 
950             case IDENT:
951             case LITERAL_boolean:
952             case LITERAL_byte:
953             case LITERAL_char:
954             case LITERAL_double:
955             case LITERAL_float:
956             case LITERAL_int:
957             case LITERAL_long:
958             case LITERAL_short:
959                 return variableExpression(node);
960 
961             case LIST_CONSTRUCTOR:
962                 return listExpression(node);
963 
964             case MAP_CONSTRUCTOR:
965                 return mapExpression(node);
966 
967             case LABELED_ARG:
968                 return mapEntryExpression(node);
969 
970             case SPREAD_ARG:
971                 return spreadExpression(node);
972 
973             case MEMBER_POINTER:
974                 return methodPointerExpression(node);
975 
976             case INDEX_OP:
977                 return indexExpression(node);
978 
979             case LITERAL_instanceof:
980                 return instanceofExpression(node);
981 
982             case LITERAL_as:
983                 return asExpression(node);
984 
985             case TYPECAST:
986                 return castExpression(node);
987 
988                 // literals
989 
990             case LITERAL_true:
991                 return ConstantExpression.TRUE;
992 
993             case LITERAL_false:
994                 return ConstantExpression.FALSE;
995 
996             case LITERAL_null:
997                 return ConstantExpression.NULL;
998 
999             case STRING_LITERAL:
1000                 ConstantExpression constantExpression = new ConstantExpression(node.getText());
1001                 configureAST(constantExpression, node);
1002                 return constantExpression;
1003 
1004             case STRING_CONSTRUCTOR:
1005                 return gstring(node);
1006 
1007             case NUM_DOUBLE:
1008             case NUM_FLOAT:
1009             case NUM_BIG_DECIMAL:
1010                 return decimalExpression(node);
1011 
1012             case NUM_BIG_INT:
1013             case NUM_INT:
1014             case NUM_LONG:
1015                 return integerExpression(node);
1016 
1017             case LITERAL_this:
1018                 return VariableExpression.THIS_EXPRESSION;
1019 
1020             case LITERAL_super:
1021                 return VariableExpression.SUPER_EXPRESSION;
1022 
1023 
1024                 // Unary expressions
1025             case LNOT:
1026                 NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
1027                 configureAST(notExpression, node);
1028                 return notExpression;
1029 
1030             case UNARY_MINUS:
1031                 return negateExpression(node);
1032 
1033             case BNOT:
1034                 BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(expression(node.getFirstChild()));
1035                 configureAST(bitwiseNegExpression, node);
1036                 return bitwiseNegExpression;
1037 
1038             case UNARY_PLUS:
1039                 return expression(node.getFirstChild());
1040 
1041 
1042                 // Prefix expressions
1043             case INC:
1044                 return prefixExpression(node, Types.PLUS_PLUS);
1045 
1046             case DEC:
1047                 return prefixExpression(node, Types.MINUS_MINUS);
1048 
1049                 // Postfix expressions
1050             case POST_INC:
1051                 return postfixExpression(node, Types.PLUS_PLUS);
1052 
1053             case POST_DEC:
1054                 return postfixExpression(node, Types.MINUS_MINUS);
1055 
1056                 
1057                 // Binary expressions
1058 
1059             case ASSIGN:
1060                 return binaryExpression(Types.ASSIGN, node);
1061 
1062             case EQUAL:
1063                 return binaryExpression(Types.COMPARE_EQUAL, node);
1064 
1065             case NOT_EQUAL:
1066                 return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1067 
1068             case COMPARE_TO:
1069                 return binaryExpression(Types.COMPARE_TO, node);
1070 
1071             case LE:
1072                 return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1073 
1074             case LT:
1075                 return binaryExpression(Types.COMPARE_LESS_THAN, node);
1076 
1077             case GT:
1078                 return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1079 
1080             case GE:
1081                 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
1082 
1083                 /***
1084                  * TODO treble equal?
1085                  return binaryExpression(Types.COMPARE_IDENTICAL, node);
1086 
1087                  case ???:
1088                  return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
1089 
1090                  case ???:
1091                  return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
1092 
1093                  */
1094 
1095             case LAND:
1096                 return binaryExpression(Types.LOGICAL_AND, node);
1097 
1098             case LOR:
1099                 return binaryExpression(Types.LOGICAL_OR, node);
1100 
1101             case BAND:
1102                 return binaryExpression(Types.BITWISE_AND, node);
1103 
1104             case BAND_ASSIGN:
1105                 return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1106 
1107             case BOR:
1108                 return binaryExpression(Types.BITWISE_OR, node);
1109 
1110             case BOR_ASSIGN:
1111                 return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1112 
1113             case BXOR:
1114                 return binaryExpression(Types.BITWISE_XOR, node);
1115 
1116             case BXOR_ASSIGN:
1117                 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1118 
1119 
1120             case PLUS:
1121                 return binaryExpression(Types.PLUS, node);
1122 
1123             case PLUS_ASSIGN:
1124                 return binaryExpression(Types.PLUS_EQUAL, node);
1125 
1126 
1127             case MINUS:
1128                 return binaryExpression(Types.MINUS, node);
1129 
1130             case MINUS_ASSIGN:
1131                 return binaryExpression(Types.MINUS_EQUAL, node);
1132 
1133 
1134             case STAR:
1135                 return binaryExpression(Types.MULTIPLY, node);
1136 
1137             case STAR_ASSIGN:
1138                 return binaryExpression(Types.MULTIPLY_EQUAL, node);
1139 
1140 
1141             case STAR_STAR:
1142                 return binaryExpression(Types.POWER, node);
1143 
1144             case STAR_STAR_ASSIGN:
1145                 return binaryExpression(Types.POWER_EQUAL, node);
1146 
1147 
1148             case DIV:
1149                 return binaryExpression(Types.DIVIDE, node);
1150 
1151             case DIV_ASSIGN:
1152                 return binaryExpression(Types.DIVIDE_EQUAL, node);
1153 
1154 
1155             case MOD:
1156                 return binaryExpression(Types.MOD, node);
1157 
1158             case MOD_ASSIGN:
1159                 return binaryExpression(Types.MOD_EQUAL, node);
1160 
1161             case SL:
1162                 return binaryExpression(Types.LEFT_SHIFT, node);
1163 
1164             case SL_ASSIGN:
1165                 return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1166 
1167             case SR:
1168                 return binaryExpression(Types.RIGHT_SHIFT, node);
1169 
1170             case SR_ASSIGN:
1171                 return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1172 
1173             case BSR:
1174                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1175 
1176             case BSR_ASSIGN:
1177                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
1178 
1179                 // Regex
1180             case REGEX_FIND:
1181                 return binaryExpression(Types.FIND_REGEX, node);
1182 
1183             case REGEX_MATCH:
1184                 return binaryExpression(Types.MATCH_REGEX, node);
1185 
1186 
1187                 // Ranges
1188             case RANGE_INCLUSIVE:
1189                 return rangeExpression(node, true);
1190 
1191             case RANGE_EXCLUSIVE:
1192                 return rangeExpression(node, false);
1193 
1194             default:
1195                 unknownAST(node);
1196         }
1197         return null;
1198     }
1199 
1200     protected Expression ternaryExpression(AST ternaryNode) {
1201         AST node = ternaryNode.getFirstChild();
1202         BooleanExpression booleanExpression = booleanExpression(node);
1203         node = node.getNextSibling();
1204         Expression left = expression(node);
1205         Expression right = expression(node.getNextSibling());
1206         TernaryExpression ternaryExpression = new TernaryExpression(booleanExpression, left, right);
1207         configureAST(ternaryExpression, ternaryNode);
1208         return ternaryExpression;
1209     }
1210 
1211     protected Expression variableExpression(AST node) {
1212         String text = node.getText();
1213 
1214         // TODO we might wanna only try to resolve the name if we are
1215         // on the left hand side of an expression or before a dot?
1216         String newText = resolveTypeName(text, false);
1217         if (newText == null) {
1218             VariableExpression variableExpression = new VariableExpression(text);
1219             configureAST(variableExpression, node);
1220             return variableExpression;
1221         }
1222         else {
1223             ClassExpression classExpression = new ClassExpression(newText);
1224             configureAST(classExpression, node);
1225             return classExpression;
1226         }
1227     }
1228 
1229     protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
1230         AST node = rangeNode.getFirstChild();
1231         Expression left = expression(node);
1232         Expression right = expression(node.getNextSibling());
1233         RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
1234         configureAST(rangeExpression, rangeNode);
1235         return rangeExpression;
1236     }
1237 
1238     protected Expression spreadExpression(AST node) {
1239         AST exprNode = node.getFirstChild();
1240         AST listNode = exprNode.getFirstChild();
1241         Expression right = expression(listNode);
1242         SpreadExpression spreadExpression = new SpreadExpression(right);
1243         configureAST(spreadExpression, node);
1244         return spreadExpression;
1245     }
1246 
1247     protected Expression methodPointerExpression(AST node) {
1248         AST exprNode = node.getFirstChild();
1249         String methodName = identifier(exprNode.getNextSibling());
1250         Expression expression = expression(exprNode);
1251         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(expression, methodName);
1252         configureAST(methodPointerExpression, node);
1253         return methodPointerExpression;
1254     }
1255 
1256 
1257     protected Expression listExpression(AST listNode) {
1258         List expressions = new ArrayList();
1259         AST elist = listNode.getFirstChild();
1260         assertNodeType(ELIST, elist);
1261 
1262         for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1263             // check for stray labeled arguments:
1264             switch (node.getType()) {
1265             case LABELED_ARG:       assertNodeType(COMMA, node);       break;  // helpful error?
1266             case SPREAD_MAP_ARG:    assertNodeType(SPREAD_ARG, node);  break;  // helpful error
1267             }
1268             expressions.add(expression(node));
1269         }
1270         ListExpression listExpression = new ListExpression(expressions);
1271         configureAST(listExpression, listNode);
1272         return listExpression;
1273     }
1274 
1275     /***
1276      * Typically only used for map constructors I think?
1277      */
1278     protected Expression mapExpression(AST mapNode) {
1279         List expressions = new ArrayList();
1280         AST elist = mapNode.getFirstChild();
1281         if (elist != null) {  // totally empty in the case of [:]
1282             assertNodeType(ELIST, elist);
1283             for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1284                 switch (node.getType()) {
1285                 case LABELED_ARG:
1286                 case SPREAD_MAP_ARG:
1287                     break;  // legal cases
1288                 case SPREAD_ARG:
1289                     assertNodeType(SPREAD_MAP_ARG, node);  break;  // helpful error
1290                 default:
1291                     assertNodeType(LABELED_ARG, node);  break;  // helpful error
1292                 }
1293                 expressions.add(mapEntryExpression(node));
1294             }
1295         }
1296         MapExpression mapExpression = new MapExpression(expressions);
1297         configureAST(mapExpression, mapNode);
1298         return mapExpression;
1299     }
1300 
1301     protected MapEntryExpression mapEntryExpression(AST node) {
1302         AST keyNode = node.getFirstChild();
1303         Expression keyExpression = expression(keyNode);
1304         AST valueNode = keyNode.getNextSibling();
1305         Expression valueExpression = expression(valueNode);
1306         MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
1307         configureAST(mapEntryExpression, node);
1308         return mapEntryExpression;
1309     }
1310 
1311 
1312     protected Expression instanceofExpression(AST node) {
1313         AST leftNode = node.getFirstChild();
1314         Expression leftExpression = expression(leftNode);
1315 
1316         AST rightNode = leftNode.getNextSibling();
1317         String typeName = resolvedName(rightNode);
1318         assertTypeNotNull(typeName, rightNode);
1319 
1320         Expression rightExpression = new ClassExpression(typeName);
1321         configureAST(rightExpression, rightNode);
1322         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
1323         configureAST(binaryExpression, node);
1324         return binaryExpression;
1325     }
1326 
1327     protected void assertTypeNotNull(String typeName, AST rightNode) {
1328         if (typeName == null) {
1329             throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
1330         }
1331     }
1332 
1333     protected Expression asExpression(AST node) {
1334         AST leftNode = node.getFirstChild();
1335         Expression leftExpression = expression(leftNode);
1336 
1337         AST rightNode = leftNode.getNextSibling();
1338         String typeName = resolvedName(rightNode);
1339 
1340         return CastExpression.asExpression(typeName, leftExpression);
1341     }
1342 
1343     protected Expression castExpression(AST castNode) {
1344         AST node = castNode.getFirstChild();
1345         String typeName = resolvedName(node);
1346         assertTypeNotNull(typeName, node);
1347 
1348         AST expressionNode = node.getNextSibling();
1349         Expression expression = expression(expressionNode);
1350 
1351         CastExpression castExpression = new CastExpression(typeName, expression);
1352         configureAST(castExpression, castNode);
1353         return castExpression;
1354     }
1355 
1356 
1357     protected Expression indexExpression(AST indexNode) {
1358         AST leftNode = indexNode.getFirstChild();
1359         Expression leftExpression = expression(leftNode);
1360 
1361         AST rightNode = leftNode.getNextSibling();
1362         Expression rightExpression = expression(rightNode);
1363 
1364         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, indexNode), rightExpression);
1365         configureAST(binaryExpression, indexNode);
1366         return binaryExpression;
1367     }
1368 
1369     protected Expression binaryExpression(int type, AST node) {
1370         Token token = makeToken(type, node);
1371 
1372         AST leftNode = node.getFirstChild();
1373         Expression leftExpression = expression(leftNode);
1374         AST rightNode = leftNode.getNextSibling();
1375         if (rightNode == null) {
1376             //rightNode = leftNode.getFirstChild();
1377             return leftExpression;
1378         }
1379         /*if (rightNode == null) {
1380             throw new NullPointerException("No rightNode associated with binary expression");
1381         }*/
1382         Expression rightExpression = expression(rightNode);
1383         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
1384         configureAST(binaryExpression, node);
1385         return binaryExpression;
1386     }
1387 
1388     protected Expression prefixExpression(AST node, int token) {
1389         Expression expression = expression(node.getFirstChild());
1390         PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
1391         configureAST(prefixExpression, node);
1392         return prefixExpression;
1393     }
1394 
1395     protected Expression postfixExpression(AST node, int token) {
1396         Expression expression = expression(node.getFirstChild());
1397         PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
1398         configureAST(postfixExpression, node);
1399         return postfixExpression;
1400     }
1401 
1402     protected BooleanExpression booleanExpression(AST node) {
1403         BooleanExpression booleanExpression = new BooleanExpression(expression(node));
1404         configureAST(booleanExpression, node);
1405         return booleanExpression;
1406     }
1407 
1408     protected Expression dotExpression(AST node) {
1409         // lets decide if this is a propery invocation or a method call
1410         AST leftNode = node.getFirstChild();
1411         if (leftNode != null) {
1412             AST identifierNode = leftNode.getNextSibling();
1413             if (identifierNode != null) {
1414                 Expression leftExpression = expression(leftNode);
1415                 if (isType(SELECT_SLOT, identifierNode)) {
1416                     String field = identifier(identifierNode.getFirstChild());
1417                     AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field);
1418                     configureAST(attributeExpression, node);
1419                     return attributeExpression;
1420                 }
1421                 String property = identifier(identifierNode);
1422                 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
1423                 configureAST(propertyExpression, node);
1424                 return propertyExpression;
1425             }
1426         }
1427         return methodCallExpression(node);
1428     }
1429 
1430     protected Expression superMethodCallExpression(AST methodCallNode) {
1431         AST node = methodCallNode.getFirstChild();
1432 
1433         String name = "super";
1434         Expression objectExpression = VariableExpression.SUPER_EXPRESSION;
1435 
1436         Expression arguments = arguments(node);
1437         MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1438         configureAST(expression, methodCallNode);
1439         return expression;
1440     }
1441 
1442 
1443     protected Expression methodCallExpression(AST methodCallNode) {
1444         AST node = methodCallNode.getFirstChild();
1445         if (isType(METHOD_CALL, node)) {
1446             // sometimes method calls get wrapped in method calls for some wierd reason
1447             return methodCallExpression(node);
1448         }
1449 
1450         Expression objectExpression = VariableExpression.THIS_EXPRESSION;
1451         AST elist = null;
1452         boolean safe = isType(OPTIONAL_DOT, node);
1453         if (isType(DOT, node) || safe) {
1454             AST objectNode = node.getFirstChild();
1455             elist = node.getNextSibling();
1456 
1457             objectExpression = expression(objectNode);
1458 
1459             node = objectNode.getNextSibling();
1460         }
1461 
1462         String name = null;
1463         if (isType(LITERAL_super, node)) {
1464             name = "super";
1465             if (objectExpression == VariableExpression.THIS_EXPRESSION) {
1466                 objectExpression = VariableExpression.SUPER_EXPRESSION;
1467             }
1468         }
1469         else if (isType(LITERAL_new, node)) {
1470             // TODO for some reason the parser wraps this in a method call if
1471             // there is an appended closure
1472             return constructorCallExpression(node);
1473         }
1474         else if (isPrimitiveTypeLiteral(node)) {
1475             throw new ASTRuntimeException(node, "Primitive type literal: " + node.getText()
1476                     + " cannot be used as a method name; maybe you need to use a double || with a closure expression? {|int x| ..} rather than {int x|...}");
1477         }
1478         else {
1479             name = identifier(node);
1480         }
1481 
1482         if (elist == null) {
1483             elist = node.getNextSibling();
1484         }
1485 
1486         Expression arguments = arguments(elist);
1487         MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1488         boolean implicitThis = (objectExpression == VariableExpression.THIS_EXPRESSION);
1489         implicitThis = implicitThis || (objectExpression == VariableExpression.SUPER_EXPRESSION);
1490         expression.setSafe(safe);
1491         expression.setImplicitThis(implicitThis);
1492         configureAST(expression, methodCallNode);
1493         return expression;
1494     }
1495 
1496     protected Expression constructorCallExpression(AST node) {
1497         if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
1498             node = node.getFirstChild();
1499         }
1500         AST constructorCallNode = node;
1501 
1502         String name = resolvedName(node);
1503         AST elist = node.getNextSibling();
1504 
1505         if (isType(ARRAY_DECLARATOR, elist)) {
1506             AST expressionNode = elist.getFirstChild();
1507             if (expressionNode == null) {
1508                 throw new ASTRuntimeException(elist, "No expression for the arrary constructor call");
1509             }
1510             Expression size = expression(expressionNode);
1511             ArrayExpression arrayExpression = new ArrayExpression(name, size);
1512             configureAST(arrayExpression, node);
1513             return arrayExpression;
1514         }
1515         Expression arguments = arguments(elist);
1516         ConstructorCallExpression expression = new ConstructorCallExpression(name, arguments);
1517         configureAST(expression, constructorCallNode);
1518         return expression;
1519     }
1520 
1521     protected Expression arguments(AST elist) {
1522         List expressionList = new ArrayList();
1523         // FIXME: all labeled arguments should follow any unlabeled arguments
1524         boolean namedArguments = false;
1525         for (AST node = elist; node != null; node = node.getNextSibling()) {
1526             if (isType(ELIST, node)) {
1527                 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1528                     namedArguments |= addArgumentExpression(child, expressionList);
1529                 }
1530             }
1531             else {
1532                 namedArguments |= addArgumentExpression(node, expressionList);
1533             }
1534         }
1535         if (namedArguments) {
1536             if (!expressionList.isEmpty()) {
1537                 // lets remove any non-MapEntryExpression instances
1538                 // such as if the last expression is a ClosureExpression
1539                 // so lets wrap the named method calls in a Map expression
1540                 List argumentList = new ArrayList();
1541                 for (Iterator iter = expressionList.iterator(); iter.hasNext();) {
1542                     Expression expression = (Expression) iter.next();
1543                     if (!(expression instanceof MapEntryExpression)) {
1544                         argumentList.add(expression);
1545                     }
1546                 }
1547                 if (!argumentList.isEmpty()) {
1548                     expressionList.removeAll(argumentList);
1549                     MapExpression mapExpression = new MapExpression(expressionList);
1550                     configureAST(mapExpression, elist);
1551                     argumentList.add(0, mapExpression);
1552                     ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
1553                     configureAST(argumentListExpression, elist);
1554                     return argumentListExpression;
1555                 }
1556             }
1557             NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
1558             configureAST(namedArgumentListExpression, elist);
1559             return namedArgumentListExpression;
1560         }
1561         else {
1562             ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
1563             configureAST(argumentListExpression, elist);
1564             return argumentListExpression;
1565         }
1566     }
1567 
1568     protected boolean addArgumentExpression(AST node, List expressionList) {
1569         Expression expression = expression(node);
1570         expressionList.add(expression);
1571         return expression instanceof MapEntryExpression;
1572     }
1573 
1574     protected Expression expressionList(AST node) {
1575         List expressionList = new ArrayList();
1576         for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1577             expressionList.add(expression(child));
1578         }
1579         if (expressionList.size() == 1) {
1580             return (Expression) expressionList.get(0);
1581         }
1582         else {
1583             ListExpression listExpression = new ListExpression(expressionList);
1584             configureAST(listExpression, node);
1585             return listExpression;
1586         }
1587     }
1588 
1589     protected ClosureExpression closureExpression(AST node) {
1590         AST paramNode = node.getFirstChild();
1591         Parameter[] parameters = Parameter.EMPTY_ARRAY;
1592         AST codeNode = paramNode;
1593         if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
1594             parameters = parameters(paramNode);
1595             codeNode = paramNode.getNextSibling();
1596         }
1597         Statement code = statementListNoChild(codeNode);
1598         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1599         configureAST(closureExpression, node);
1600         return closureExpression;
1601     }
1602 
1603     protected Expression blockExpression(AST node) {
1604         AST codeNode = node.getFirstChild();
1605         if (codeNode == null)  return ConstantExpression.NULL;
1606         if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
1607             // Simplify common case of {expr} to expr.
1608             return expression(codeNode);
1609         }
1610         Parameter[] parameters = Parameter.EMPTY_ARRAY;
1611         Statement code = statementListNoChild(codeNode);
1612         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1613         configureAST(closureExpression, node);
1614         // Call it immediately.
1615         String callName = "call";
1616         Expression noArguments = new ArgumentListExpression();
1617         MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
1618         configureAST(call, node);
1619         return call;
1620     }
1621 
1622     protected Expression negateExpression(AST negateExpr) {
1623         AST node = negateExpr.getFirstChild();
1624 
1625         // if we are a number literal then lets just parse it
1626         // as the negation operator on MIN_INT causes rounding to a long
1627         String text = node.getText();
1628         switch (node.getType()) {
1629             case NUM_DOUBLE:
1630             case NUM_FLOAT:
1631             case NUM_BIG_DECIMAL:
1632                 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
1633                 configureAST(constantExpression, negateExpr);
1634                 return constantExpression;
1635 
1636             case NUM_BIG_INT:
1637             case NUM_INT:
1638             case NUM_LONG:
1639                 ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
1640                 configureAST(constantLongExpression, negateExpr);
1641                 return constantLongExpression;
1642 
1643             default:
1644                 NegationExpression negationExpression = new NegationExpression(expression(node));
1645                 configureAST(negationExpression, negateExpr);
1646                 return negationExpression;
1647         }
1648     }
1649 
1650     protected ConstantExpression decimalExpression(AST node) {
1651         String text = node.getText();
1652         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
1653         configureAST(constantExpression, node);
1654         return constantExpression;
1655     }
1656 
1657     protected ConstantExpression integerExpression(AST node) {
1658         String text = node.getText();
1659         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseInteger(text));
1660         configureAST(constantExpression, node);
1661         return constantExpression;
1662     }
1663 
1664     protected Expression gstring(AST gstringNode) {
1665         List strings = new ArrayList();
1666         List values = new ArrayList();
1667 
1668         StringBuffer buffer = new StringBuffer();
1669         
1670         boolean isPrevString = false;
1671 
1672         for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
1673             int type = node.getType();
1674             String text = null;
1675             switch (type) {
1676 
1677                 case STRING_LITERAL:
1678                     if (isPrevString)  assertNodeType(IDENT, node);  // parser bug
1679                     isPrevString = true;
1680                     text = node.getText();
1681                     ConstantExpression constantExpression = new ConstantExpression(text);
1682                     configureAST(constantExpression, node);
1683                     strings.add(constantExpression);
1684                     buffer.append(text);
1685                     break;
1686 
1687                 default:
1688                     {
1689                         if (!isPrevString)  assertNodeType(IDENT, node);  // parser bug
1690                         isPrevString = false;
1691                         Expression expression = expression(node);
1692                         values.add(expression);
1693                         buffer.append("$");
1694                         buffer.append(expression.getText());
1695                     }
1696                     break;
1697             }
1698         }
1699         GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
1700         configureAST(gStringExpression, gstringNode);
1701         return gStringExpression;
1702     }
1703 
1704     protected Type type(AST typeNode) {
1705         // TODO intern types?
1706         // TODO configureAST(...)
1707         return new Type(resolvedName(typeNode.getFirstChild()));
1708     }
1709 
1710     protected String qualifiedName(AST qualifiedNameNode) {
1711         if (isType(IDENT, qualifiedNameNode)) {
1712             return qualifiedNameNode.getText();
1713         }
1714         if (isType(DOT, qualifiedNameNode)) {
1715             AST node = qualifiedNameNode.getFirstChild();
1716             StringBuffer buffer = new StringBuffer();
1717             boolean first = true;
1718 
1719             for (; node != null; node = node.getNextSibling()) {
1720                 if (first) {
1721                     first = false;
1722                 }
1723                 else {
1724                     buffer.append(".");
1725                 }
1726                 buffer.append(qualifiedName(node));
1727             }
1728             return buffer.toString();
1729         }
1730         else {
1731             return qualifiedNameNode.getText();
1732         }
1733     }
1734 
1735     protected String typeName(AST typeNode) {
1736         String answer = null;
1737         AST node = typeNode.getFirstChild();
1738         if (node != null) {
1739             if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1740                 return resolveTypeName(qualifiedName(node.getFirstChild())) + "[]";
1741             }
1742             answer = resolveTypeName(qualifiedName(node));
1743             node = node.getNextSibling();
1744             if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1745                 return answer + "[]";
1746             }
1747         }
1748         return answer;
1749     }
1750 
1751     /***
1752      * Performs a name resolution to see if the given name is a type from imports,
1753      * aliases or newly created classes
1754      */
1755     protected String resolveTypeName(String name, boolean safe) {
1756         if (name == null) {
1757             return null;
1758         }
1759         return resolveNewClassOrName(name, safe);
1760     }
1761 
1762     /***
1763      * Performs a name resolution to see if the given name is a type from imports,
1764      * aliases or newly created classes
1765      */
1766     protected String resolveTypeName(String name) {
1767         return resolveTypeName(name, true);
1768     }
1769 
1770     /***
1771      * Extracts an identifier from the Antlr AST and then performs a name resolution
1772      * to see if the given name is a type from imports, aliases or newly created classes
1773      */
1774     protected String resolvedName(AST node) {
1775         if (isType(TYPE, node)) {
1776             node = node.getFirstChild();
1777         }
1778         String answer = null;
1779         if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
1780             answer = qualifiedName(node);
1781         }
1782         else if (isPrimitiveTypeLiteral(node)) {
1783             answer = node.getText();
1784         }
1785         else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1786             AST child = node.getFirstChild();
1787             String text = resolvedName(child);
1788             // TODO sometimes we have ARRAY_DECLARATOR->typeName
1789             // and sometimes we have typeName->ARRAY_DECLARATOR
1790             // so here's a little fudge while we be more consistent in the Antlr
1791             if (text.endsWith("[]")) {
1792                 return text;
1793             }
1794             return text + "[]";
1795         }
1796         else {
1797             String identifier = node.getText();
1798             answer = resolveTypeName(identifier);
1799 
1800         }
1801         AST nextSibling = node.getNextSibling();
1802         if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
1803             return answer + "[]";
1804         }
1805         else {
1806             return answer;
1807         }
1808     }
1809 
1810     protected boolean isPrimitiveTypeLiteral(AST node) {
1811         int type = node.getType();
1812         switch (type) {
1813             case LITERAL_boolean:
1814             case LITERAL_byte:
1815             case LITERAL_char:
1816             case LITERAL_double:
1817             case LITERAL_float:
1818             case LITERAL_int:
1819             case LITERAL_long:
1820             case LITERAL_short:
1821                 return true;
1822 
1823             default:
1824                 return false;
1825         }
1826     }
1827 
1828     /***
1829      * Extracts an identifier from the Antlr AST
1830      */
1831     protected String identifier(AST node) {
1832         assertNodeType(IDENT, node);
1833         return node.getText();
1834     }
1835 
1836     protected String label(AST labelNode) {
1837         AST node = labelNode.getFirstChild();
1838         if (node == null) {
1839             return null;
1840         }
1841         return identifier(node);
1842     }
1843 
1844 
1845 
1846     // Helper methods
1847     //-------------------------------------------------------------------------
1848 
1849 
1850     /***
1851      * Returns true if the modifiers flags contain a visibility modifier
1852      */
1853     protected boolean hasVisibility(int modifiers) {
1854         return (modifiers & (Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_PUBLIC)) != 0;
1855     }
1856 
1857     protected void configureAST(ASTNode node, AST ast) {
1858         if (ast==null) throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure "+node.getClass().getName()+" with null Node");
1859         node.setColumnNumber(ast.getColumn());
1860         node.setLineNumber(ast.getLine());
1861 
1862         // TODO we could one day store the Antlr AST on the Groovy AST
1863         // node.setCSTNode(ast);
1864     }
1865 
1866     protected static Token makeToken(int typeCode, AST node) {
1867         return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
1868     }
1869 
1870     protected String getFirstChildText(AST node) {
1871         AST child = node.getFirstChild();
1872         return child != null ? child.getText() : null;
1873     }
1874 
1875 
1876     protected boolean isType(int typeCode, AST node) {
1877         return node != null && node.getType() == typeCode;
1878     }
1879 
1880     private String getTokenName(int token) {
1881         if (tokenNames==null) return ""+token;
1882         return tokenNames[token];
1883     }
1884     
1885     private String getTokenName(AST node) {
1886         if (node==null) return "null";
1887         return getTokenName(node.getType());
1888     }
1889 
1890     protected void assertNodeType(int type, AST node) {
1891         if (node == null) {
1892             throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
1893         }
1894         if (node.getType() != type) {            
1895             throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
1896         }
1897     }
1898 
1899     protected void notImplementedYet(AST node) {
1900         throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
1901     }
1902 
1903     protected void unknownAST(AST node) {
1904         throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
1905     }
1906 
1907     protected void dumpTree(AST ast) {
1908         for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
1909             dump(node);
1910         }
1911     }
1912 
1913     protected void dump(AST node) {
1914         System.out.println("Type: " + getTokenName(node) + " text: " + node.getText());
1915     }
1916 }