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