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: 4526 $
    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     protectedong> 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 caught 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         assertNotLegacyFor(forNode);
    887         AST inNode = forNode.getFirstChild();
    888         AST variableNode = inNode.getFirstChild();
    889         AST collectionNode = variableNode.getNextSibling();
    890
    891         ClassNode type = ClassHelper.OBJECT_TYPE;
    892         if (isType(VARIABLE_DEF, variableNode)) {
    893             AST typeNode = variableNode.getFirstChild();
    894             assertNodeType(TYPE, typeNode);
    895
    896             type = type(typeNode);
    897             variableNode = typeNode.getNextSibling();
    898         }
    899         String variable = identifier(variableNode);
    900
    901         Expression collectionExpression = expression(collectionNode);
    902         Statement block = statement(inNode.getNextSibling());
    903         Parameter forParameter = new Parameter(type,variable);
    904
    905         ForStatement forStatement = new ForStatement(forParameter, collectionExpression, block);
    906         configureAST(forStatement, forNode);
    907         return forStatement;
    908     }
    909
    910     private void assertNotLegacyFor(AST forNode) {
    911         AST childNode = forNode.getFirstChild();
    912         boolean legacy = false;
    913         while (childNode != null) {
    914             int type = childNode.getType();
    915             if (type == FOR_INIT || type == FOR_CONDITION || type == FOR_ITERATOR) {
    916                 legacy = true;
    917                 break;
    918             }
    919             childNode = childNode.getNextSibling();
    920         }
    921         if (legacy) {
    922             throw new ASTRuntimeException(forNode, "For statement contains unexpected tokens. Possible attempt to use unsupported Java-style for loop.");
    923         }
    924     }
    925
    926     protected Statement ifStatement(AST ifNode) {
    927         AST node = ifNode.getFirstChild();
    928         assertNodeType(EXPR, node);
    929         BooleanExpression booleanExpression = booleanExpression(node);
    930
    931         node = node.getNextSibling();
    932         Statement ifBlock = statement(node);
    933
    934         Statement elseBlock = EmptyStatement.INSTANCE;
    935         node = node.getNextSibling();
    936         if (node != null) {
    937             elseBlock = statement(node);
    938         }
    939         IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
    940         configureAST(ifStatement, ifNode);
    941         return ifStatement;
    942     }
    943
    944     protected Statement labelledStatement(AST labelNode) {
    945         AST node = labelNode.getFirstChild();
    946         String label = identifier(node);
    947         Statement statement = statement(node.getNextSibling());
    948         statement.setStatementLabel(label);
    949         return statement;
    950     }
    951
    952     protected Statement methodCall(AST code) {
    953         Expression expression = methodCallExpression(code);
    954         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
    955         configureAST(expressionStatement, code);
    956         return expressionStatement;
    957     }
    958
    959     protected Statement variableDef(AST variableDef) {
    960         AST node = variableDef.getFirstChild();
    961         ClassNode type = null;
    962         if (isType(MODIFIERS, node)) {
    963             node = node.getNextSibling();
    964         }
    965         if (isType(TYPE, node)) {
    966             type = makeType(node);
    967             node = node.getNextSibling();
    968         }
    969
    970         String name = identifier(node);
    971         node = node.getNextSibling();
    972
    973         VariableExpression leftExpression = new VariableExpression(name, type);
    974         configureAST(leftExpression, variableDef);
    975
    976         Expression rightExpression = ConstantExpression.NULL;
    977         if (node != null) {
    978             assertNodeType(ASSIGN, node);
    979
    980             rightExpression = expression(node.getFirstChild());
    981         }
    982         Token token = makeToken(Types.ASSIGN, variableDef);
    983
    984         // TODO should we have a variable declaration statement?
    985         DeclarationExpression expression = new DeclarationExpression(leftExpression, token, rightExpression);
    986         configureAST(expression, variableDef);
    987         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
    988         configureAST(expressionStatement, variableDef);
    989         return expressionStatement;
    990     }
    991
    992     protected Statement returnStatement(AST node) {
    993         AST exprNode = node.getFirstChild();
    994
    995         // This will pick up incorrect sibling node if 'node' is a plain 'return'
    996 		//
    997 		//if (exprNode == null) {
    998         //    exprNode = node.getNextSibling();
    999         //}
    1000         if (exprNode != null) {
    1001             Expression expression = expression(exprNode);
    1002             if (expression instanceof ConstantExpression) {
    1003                 ConstantExpression constantExpr = (ConstantExpression) expression;
    1004                 if (constantExpr.getValue() == null) {
    1005                     return ReturnStatement.RETURN_NULL_OR_VOID;
    1006                 }
    1007             }
    1008             ReturnStatement returnStatement = new ReturnStatement(expression);
    1009             configureAST(returnStatement, node);
    1010             return returnStatement;
    1011         }
    1012         else {
    1013             return ReturnStatement.RETURN_NULL_OR_VOID;
    1014         }
    1015     }
    1016
    1017     protected Statement switchStatement(AST switchNode) {
    1018         AST node = switchNode.getFirstChild();
    1019         Expression expression = expression(node);
    1020         Statement defaultStatement = EmptyStatement.INSTANCE;
    1021
    1022         List list = new ArrayList();
    1023         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
    1024             AST child = node.getFirstChild();
    1025             if (isType(LITERAL_case, child)) {
    1026                 list.add(caseStatement(child));
    1027             } else {
    1028                 defaultStatement = statement(child.getNextSibling());
    1029             }
    1030         }
    1031         if (node != null) {
    1032             unknownAST(node);
    1033         }
    1034         SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
    1035         configureAST(switchStatement, switchNode);
    1036         return switchStatement;
    1037     }
    1038
    1039     protected CaseStatement caseStatement(AST node) {
    1040         List expressions = new ArrayList();
    1041         Statement statement = EmptyStatement.INSTANCE;
    1042         AST nextSibling = node;
    1043         do {
    1044             Expression expression = expression(nextSibling.getFirstChild());
    1045             expressions.add(expression);
    1046             nextSibling = nextSibling.getNextSibling();
    1047         } while (isType(LITERAL_case, nextSibling));
    1048         if (!isType(LITERAL_default, nextSibling) && nextSibling != null) {
    1049              statement = statement(nextSibling);
    1050         }
    1051         CaseStatement answer;
    1052         if (expressions.size() == 1) {
    1053             // single case uses original code for effiiency
    1054             answer = new CaseStatement((Expression) expressions.get(0), statement);
    1055         } else {
    1056             // multiple cases in casegroup are grouped as an expression
    1057             // doesn't seem to mix well with certain case expressions, e.g. regex
    1058             ListExpression listExpression = new ListExpression(expressions);
    1059             answer = new CaseStatement(listExpression, statement);
    1060         }
    1061         configureAST(answer, node);
    1062         return answer;
    1063     }
    1064
    1065     protected Statement synchronizedStatement(AST syncNode) {
    1066         AST node = syncNode.getFirstChild();
    1067         Expression expression = expression(node);
    1068         Statement code = statement(node.getNextSibling());
    1069         SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
    1070         configureAST(synchronizedStatement, syncNode);
    1071         return synchronizedStatement;
    1072     }
    1073
    1074     protected Statement throwStatement(AST node) {
    1075         AST expressionNode = node.getFirstChild();
    1076         if (expressionNode == null) {
    1077             expressionNode = node.getNextSibling();
    1078         }
    1079         if (expressionNode == null) {
    1080             throw new ASTRuntimeException(node, "No expression available");
    1081         }
    1082         ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
    1083         configureAST(throwStatement, node);
    1084         return throwStatement;
    1085     }
    1086
    1087     protected Statement tryStatement(AST tryStatementNode) {
    1088         AST tryNode = tryStatementNode.getFirstChild();
    1089         Statement tryStatement = statement(tryNode);
    1090         Statement finallyStatement = EmptyStatement.INSTANCE;
    1091         AST node = tryNode.getNextSibling();
    1092
    1093         // lets do the catch nodes
    1094         List catches = new ArrayList();
    1095         for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
    1096             catches.add(catchStatement(node));
    1097         }
    1098
    1099         if (isType(LITERAL_finally, node)) {
    1100             finallyStatement = statement(node);
    1101             node = node.getNextSibling();
    1102         }
    1103
    1104         TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
    1105         configureAST(tryCatchStatement, tryStatementNode);
    1106         for (Iterator iter = catches.iterator(); iter.hasNext();) {
    1107             CatchStatement statement = (CatchStatement) iter.next();
    1108             tryCatchStatement.addCatch(statement);
    1109         }
    1110         return tryCatchStatement;
    1111     }
    1112
    1113     protected CatchStatement catchStatement(AST catchNode) {
    1114         AST node = catchNode.getFirstChild();
    1115         Parameter parameter = parameter(node);
    1116         ClassNode exceptionType = parameter.getType();
    1117         String variable = parameter.getName();
    1118         node = node.getNextSibling();
    1119         Statement code = statement(node);
    1120         Parameter catchParameter = new Parameter(exceptionType,variable);
    1121         CatchStatement answer = new CatchStatement(catchParameter, code);
    1122         configureAST(answer, catchNode);
    1123         return answer;
    1124     }
    1125
    1126     protected Statement whileStatement(AST whileNode) {
    1127         AST node = whileNode.getFirstChild();
    1128         assertNodeType(EXPR, node);
    1129         BooleanExpression booleanExpression = booleanExpression(node);
    1130
    1131         node = node.getNextSibling();
    1132         Statement block = statement(node);
    1133         WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
    1134         configureAST(whileStatement, whileNode);
    1135         return whileStatement;
    1136     }
    1137
    1138     protected Statement withStatement(AST node) {
    1139         notImplementedYet(node);
    1140         return null; /*** TODO */
    1141     }
    1142
    1143
    1144
    1145     // Expressions
    1146     //-------------------------------------------------------------------------
    1147
    1148     protected Expression expression(AST node) {
    1149         return expression(node,false);
    1150     }
    1151
    1152     protected Expression expression(AST node, boolean convertToConstant) {
    1153         Expression expression = expressionSwitch(node);
    1154         if (convertToConstant) {
    1155             // a method name can never be a VariableExprssion, so it must converted
    1156             // to a ConstantExpression then. This is needed as the expression
    1157             // method doesn't know we want a ConstantExpression instead of a
    1158             // VariableExpression
    1159             if ( expression != VariableExpression.THIS_EXPRESSION &&
    1160                  expression != VariableExpression.SUPER_EXPRESSION &&
    1161                  expression instanceof VariableExpression)
    1162             {
    1163                 VariableExpression ve = (VariableExpression) expression;
    1164                 expression = new ConstantExpression(ve.getName());
    1165             }
    1166         }
    1167         configureAST(expression, node);
    1168         return expression;
    1169     }
    1170
    1171     protected Expression expressionSwitch(AST node) {
    1172         int type = node.getType();
    1173         switch (type) {
    1174             case EXPR:
    1175                 return expression(node.getFirstChild());
    1176
    1177             case ELIST:
    1178                 return expressionList(node);
    1179
    1180             case SLIST:
    1181                 return blockExpression(node);
    1182
    1183             case CLOSABLE_BLOCK:
    1184                 return closureExpression(node);
    1185
    1186             case SUPER_CTOR_CALL:
    1187                 return specialConstructorCallExpression(node,ClassNode.SUPER);
    1188
    1189             case METHOD_CALL:
    1190                 return methodCallExpression(node);
    1191
    1192             case LITERAL_new:
    1193                 return constructorCallExpression(node.getFirstChild());
    1194
    1195             case CTOR_CALL:
    1196                 return specialConstructorCallExpression(node,ClassNode.THIS);
    1197
    1198             case QUESTION:
    1199                 return ternaryExpression(node);
    1200
    1201             case OPTIONAL_DOT:
    1202             case SPREAD_DOT:
    1203             case DOT:
    1204                 return dotExpression(node);
    1205
    1206             case IDENT:
    1207             case LITERAL_boolean:
    1208             case LITERAL_byte:
    1209             case LITERAL_char:
    1210             case LITERAL_double:
    1211             case LITERAL_float:
    1212             case LITERAL_int:
    1213             case LITERAL_long:
    1214             case LITERAL_short:
    1215             case LITERAL_void:
    1216                 return variableExpression(node);
    1217
    1218             case LIST_CONSTRUCTOR:
    1219                 return listExpression(node);
    1220
    1221             case MAP_CONSTRUCTOR:
    1222                 return mapExpression(node);
    1223
    1224             case LABELED_ARG:
    1225                 return mapEntryExpression(node);
    1226
    1227             case SPREAD_ARG:
    1228                 return spreadExpression(node);
    1229
    1230             case SPREAD_MAP_ARG:
    1231                 return spreadMapExpression(node);
    1232
    1233             // commented out of groovy.g due to non determinisms
    1234             //case MEMBER_POINTER_DEFAULT:
    1235             //    return defaultMethodPointerExpression(node);
    1236
    1237             case MEMBER_POINTER:
    1238                 return methodPointerExpression(node);
    1239
    1240             case INDEX_OP:
    1241                 return indexExpression(node);
    1242
    1243             case LITERAL_instanceof:
    1244                 return instanceofExpression(node);
    1245
    1246             case LITERAL_as:
    1247                 return asExpression(node);
    1248
    1249             case TYPECAST:
    1250                 return castExpression(node);
    1251
    1252                 // literals
    1253
    1254             case LITERAL_true:
    1255                 return ConstantExpression.TRUE;
    1256
    1257             case LITERAL_false:
    1258                 return ConstantExpression.FALSE;
    1259
    1260             case LITERAL_null:
    1261                 return ConstantExpression.NULL;
    1262
    1263             case STRING_LITERAL:
    1264                 ConstantExpression constantExpression = new ConstantExpression(node.getText());
    1265                 configureAST(constantExpression, node);
    1266                 return constantExpression;
    1267
    1268             case STRING_CONSTRUCTOR:
    1269                 return gstring(node);
    1270
    1271             case NUM_DOUBLE:
    1272             case NUM_FLOAT:
    1273             case NUM_BIG_DECIMAL:
    1274                 return decimalExpression(node);
    1275
    1276             case NUM_BIG_INT:
    1277             case NUM_INT:
    1278             case NUM_LONG:
    1279                 return integerExpression(node);
    1280
    1281             case LITERAL_this:
    1282                 return VariableExpression.THIS_EXPRESSION;
    1283
    1284             case LITERAL_super:
    1285                 return VariableExpression.SUPER_EXPRESSION;
    1286
    1287
    1288                 // Unary expressions
    1289             case LNOT:
    1290                 NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
    1291                 configureAST(notExpression, node);
    1292                 return notExpression;
    1293
    1294             case UNARY_MINUS:
    1295                 return negateExpression(node);
    1296
    1297             case BNOT:
    1298                 BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(expression(node.getFirstChild()));
    1299                 configureAST(bitwiseNegExpression, node);
    1300                 return bitwiseNegExpression;
    1301
    1302             case UNARY_PLUS:
    1303                 return expression(node.getFirstChild());
    1304
    1305
    1306                 // Prefix expressions
    1307             case INC:
    1308                 return prefixExpression(node, Types.PLUS_PLUS);
    1309
    1310             case DEC:
    1311                 return prefixExpression(node, Types.MINUS_MINUS);
    1312
    1313                 // Postfix expressions
    1314             case POST_INC:
    1315                 return postfixExpression(node, Types.PLUS_PLUS);
    1316
    1317             case POST_DEC:
    1318                 return postfixExpression(node, Types.MINUS_MINUS);
    1319
    1320
    1321                 // Binary expressions
    1322
    1323             case ASSIGN:
    1324                 return binaryExpression(Types.ASSIGN, node);
    1325
    1326             case EQUAL:
    1327                 return binaryExpression(Types.COMPARE_EQUAL, node);
    1328
    1329             case NOT_EQUAL:
    1330                 return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
    1331
    1332             case COMPARE_TO:
    1333                 return binaryExpression(Types.COMPARE_TO, node);
    1334
    1335             case LE:
    1336                 return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
    1337
    1338             case LT:
    1339                 return binaryExpression(Types.COMPARE_LESS_THAN, node);
    1340
    1341             case GT:
    1342                 return binaryExpression(Types.COMPARE_GREATER_THAN, node);
    1343
    1344             case GE:
    1345                 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
    1346
    1347                 /***
    1348                  * TODO treble equal?
    1349                  return binaryExpression(Types.COMPARE_IDENTICAL, node);
    1350
    1351                  case ???:
    1352                  return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
    1353
    1354                  case ???:
    1355                  return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
    1356
    1357                  */
    1358
    1359             case LAND:
    1360                 return binaryExpression(Types.LOGICAL_AND, node);
    1361
    1362             case LOR:
    1363                 return binaryExpression(Types.LOGICAL_OR, node);
    1364
    1365             case BAND:
    1366                 return binaryExpression(Types.BITWISE_AND, node);
    1367
    1368             case BAND_ASSIGN:
    1369                 return binaryExpression(Types.BITWISE_AND_EQUAL, node);
    1370
    1371             case BOR:
    1372                 return binaryExpression(Types.BITWISE_OR, node);
    1373
    1374             case BOR_ASSIGN:
    1375                 return binaryExpression(Types.BITWISE_OR_EQUAL, node);
    1376
    1377             case BXOR:
    1378                 return binaryExpression(Types.BITWISE_XOR, node);
    1379
    1380             case BXOR_ASSIGN:
    1381                 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
    1382
    1383
    1384             case PLUS:
    1385                 return binaryExpression(Types.PLUS, node);
    1386
    1387             case PLUS_ASSIGN:
    1388                 return binaryExpression(Types.PLUS_EQUAL, node);
    1389
    1390
    1391             case MINUS:
    1392                 return binaryExpression(Types.MINUS, node);
    1393
    1394             case MINUS_ASSIGN:
    1395                 return binaryExpression(Types.MINUS_EQUAL, node);
    1396
    1397
    1398             case STAR:
    1399                 return binaryExpression(Types.MULTIPLY, node);
    1400
    1401             case STAR_ASSIGN:
    1402                 return binaryExpression(Types.MULTIPLY_EQUAL, node);
    1403
    1404
    1405             case STAR_STAR:
    1406                 return binaryExpression(Types.POWER, node);
    1407
    1408             case STAR_STAR_ASSIGN:
    1409                 return binaryExpression(Types.POWER_EQUAL, node);
    1410
    1411
    1412             case DIV:
    1413                 return binaryExpression(Types.DIVIDE, node);
    1414
    1415             case DIV_ASSIGN:
    1416                 return binaryExpression(Types.DIVIDE_EQUAL, node);
    1417
    1418
    1419             case MOD:
    1420                 return binaryExpression(Types.MOD, node);
    1421
    1422             case MOD_ASSIGN:
    1423                 return binaryExpression(Types.MOD_EQUAL, node);
    1424
    1425             case SL:
    1426                 return binaryExpression(Types.LEFT_SHIFT, node);
    1427
    1428             case SL_ASSIGN:
    1429                 return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
    1430
    1431             case SR:
    1432                 return binaryExpression(Types.RIGHT_SHIFT, node);
    1433
    1434             case SR_ASSIGN:
    1435                 return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
    1436
    1437             case BSR:
    1438                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
    1439
    1440             case BSR_ASSIGN:
    1441                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
    1442
    1443                 // Regex
    1444             case REGEX_FIND:
    1445                 return binaryExpression(Types.FIND_REGEX, node);
    1446
    1447             case REGEX_MATCH:
    1448                 return binaryExpression(Types.MATCH_REGEX, node);
    1449
    1450
    1451                 // Ranges
    1452             case RANGE_INCLUSIVE:
    1453                 return rangeExpression(node, true);
    1454
    1455             case RANGE_EXCLUSIVE:
    1456                 return rangeExpression(node, false);
    1457
    1458             case DYNAMIC_MEMBER:
    1459                 return dynamicMemberExpression(node);
    1460
    1461             case LITERAL_in:
    1462                 return binaryExpression(Types.KEYWORD_IN,node);
    1463
    1464             default:
    1465                 unknownAST(node);
    1466         }
    1467         return null;
    1468     }
    1469
    1470     protected Expression dynamicMemberExpression(AST dynamicMemberNode) {
    1471         AST node = dynamicMemberNode.getFirstChild();
    1472         return expression(node);
    1473     }
    1474
    1475     protected Expression ternaryExpression(AST ternaryNode) {
    1476         AST node = ternaryNode.getFirstChild();
    1477         BooleanExpression booleanExpression = booleanExpression(node);
    1478         node = node.getNextSibling();
    1479         Expression left = expression(node);
    1480         Expression right = expression(node.getNextSibling());
    1481         TernaryExpression ternaryExpression = new TernaryExpression(booleanExpression, left, right);
    1482         configureAST(ternaryExpression, ternaryNode);
    1483         return ternaryExpression;
    1484     }
    1485
    1486     protected Expression variableExpression(AST node) {
    1487         String text = node.getText();
    1488
    1489         // TODO we might wanna only try to resolve the name if we are
    1490         // on the left hand side of an expression or before a dot?
    1491         VariableExpression variableExpression = new VariableExpression(text);
    1492         configureAST(variableExpression, node);
    1493         return variableExpression;
    1494     }
    1495
    1496     protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
    1497         AST node = rangeNode.getFirstChild();
    1498         Expression left = expression(node);
    1499         Expression right = expression(node.getNextSibling());
    1500         RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
    1501         configureAST(rangeExpression, rangeNode);
    1502         return rangeExpression;
    1503     }
    1504
    1505     protected Expression spreadExpression(AST node) {
    1506         AST exprNode = node.getFirstChild();
    1507         AST listNode = exprNode.getFirstChild();
    1508         Expression right = expression(listNode);
    1509         SpreadExpression spreadExpression = new SpreadExpression(right);
    1510         configureAST(spreadExpression, node);
    1511         return spreadExpression;
    1512     }
    1513
    1514     protected Expression spreadMapExpression(AST node) {
    1515         AST exprNode = node.getFirstChild();
    1516         Expression expr = expression(exprNode);
    1517         SpreadMapExpression spreadMapExpression = new SpreadMapExpression(expr);
    1518         configureAST(spreadMapExpression, node);
    1519         return spreadMapExpression;
    1520     }
    1521
    1522     protected Expression methodPointerExpression(AST node) {
    1523         AST exprNode = node.getFirstChild();
    1524         String methodName = identifier(exprNode.getNextSibling());
    1525         Expression expression = expression(exprNode);
    1526         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(expression, methodName);
    1527         configureAST(methodPointerExpression, node);
    1528         return methodPointerExpression;
    1529     }
    1530
    1531 /*  commented out due to groovy.g non-determinisms
    1532   protected Expression defaultMethodPointerExpression(AST node) {
    1533         AST exprNode = node.getFirstChild();
    1534         String methodName = exprNode.toString();
    1535         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
    1536         configureAST(methodPointerExpression, node);
    1537         return methodPointerExpression;
    1538     }
    1539 */
    1540
    1541     protected Expression listExpression(AST listNode) {
    1542         List expressions = new ArrayList();
    1543         AST elist = listNode.getFirstChild();
    1544         assertNodeType(ELIST, elist);
    1545
    1546         for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
    1547             // check for stray labeled arguments:
    1548             switch (node.getType()) {
    1549             case LABELED_ARG:       assertNodeType(COMMA, node);       break;  // helpful error?
    1550             case SPREAD_MAP_ARG:    assertNodeType(SPREAD_ARG, node);  break;  // helpful error
    1551             }
    1552             expressions.add(expression(node));
    1553         }
    1554         ListExpression listExpression = new ListExpression(expressions);
    1555         configureAST(listExpression, listNode);
    1556         return listExpression;
    1557     }
    1558
    1559     /***
    1560      * Typically only used for map constructors I think?
    1561      */
    1562     protected Expression mapExpression(AST mapNode) {
    1563         List expressions = new ArrayList();
    1564         AST elist = mapNode.getFirstChild();
    1565         if (elist != null) {  // totally empty in the case of [:]
    1566             assertNodeType(ELIST, elist);
    1567             for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
    1568                 switch (node.getType()) {
    1569                 case LABELED_ARG:
    1570                 case SPREAD_MAP_ARG:
    1571                     break;  // legal cases
    1572                 case SPREAD_ARG:
    1573                     assertNodeType(SPREAD_MAP_ARG, node);  break;  // helpful error
    1574                 default:
    1575                     assertNodeType(LABELED_ARG, node);  break;  // helpful error
    1576                 }
    1577                 expressions.add(mapEntryExpression(node));
    1578             }
    1579         }
    1580         MapExpression mapExpression = new MapExpression(expressions);
    1581         configureAST(mapExpression, mapNode);
    1582         return mapExpression;
    1583     }
    1584
    1585     protected MapEntryExpression mapEntryExpression(AST node) {
    1586         if (node.getType() == SPREAD_MAP_ARG) {
    1587             AST rightNode = node.getFirstChild();
    1588             Expression keyExpression = spreadMapExpression(node);
    1589             Expression rightExpression = expression(rightNode);
    1590             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
    1591             configureAST(mapEntryExpression, node);
    1592             return mapEntryExpression;
    1593         }
    1594         else {
    1595             AST keyNode = node.getFirstChild();
    1596             Expression keyExpression = expression(keyNode);
    1597             AST valueNode = keyNode.getNextSibling();
    1598             Expression valueExpression = expression(valueNode);
    1599             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
    1600             configureAST(mapEntryExpression, node);
    1601             return mapEntryExpression;
    1602         }
    1603     }
    1604
    1605
    1606     protected Expression instanceofExpression(AST node) {
    1607         AST leftNode = node.getFirstChild();
    1608         Expression leftExpression = expression(leftNode);
    1609
    1610         AST rightNode = leftNode.getNextSibling();
    1611         ClassNode type = buildName(rightNode);
    1612         assertTypeNotNull(type, rightNode);
    1613
    1614         Expression rightExpression = new ClassExpression(type);
    1615         configureAST(rightExpression, rightNode);
    1616         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
    1617         configureAST(binaryExpression, node);
    1618         return binaryExpression;
    1619     }
    1620
    1621     protected void assertTypeNotNull(ClassNode type, AST rightNode) {
    1622         if (type == null) {
    1623             throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
    1624         }
    1625     }
    1626
    1627     protected Expression asExpression(AST node) {
    1628         AST leftNode = node.getFirstChild();
    1629         Expression leftExpression = expression(leftNode);
    1630
    1631         AST rightNode = leftNode.getNextSibling();
    1632         ClassNode type = buildName(rightNode);
    1633
    1634         return CastExpression.asExpression(type, leftExpression);
    1635     }
    1636
    1637     protected Expression castExpression(AST castNode) {
    1638         AST node = castNode.getFirstChild();
    1639         ClassNode type = buildName(node);
    1640         assertTypeNotNull(type, node);
    1641
    1642         AST expressionNode = node.getNextSibling();
    1643         Expression expression = expression(expressionNode);
    1644
    1645         CastExpression castExpression = new CastExpression(type, expression);
    1646         configureAST(castExpression, castNode);
    1647         return castExpression;
    1648     }
    1649
    1650
    1651     protected Expression indexExpression(AST indexNode) {
    1652         AST leftNode = indexNode.getFirstChild();
    1653         Expression leftExpression = expression(leftNode);
    1654
    1655         AST rightNode = leftNode.getNextSibling();
    1656         Expression rightExpression = expression(rightNode);
    1657
    1658         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, indexNode), rightExpression);
    1659         configureAST(binaryExpression, indexNode);
    1660         return binaryExpression;
    1661     }
    1662
    1663     protected Expression binaryExpression(int type, AST node) {
    1664         Token token = makeToken(type, node);
    1665
    1666         AST leftNode = node.getFirstChild();
    1667         Expression leftExpression = expression(leftNode);
    1668
    1669         AST rightNode = leftNode.getNextSibling();
    1670         if (rightNode == null) {
    1671             return leftExpression;
    1672         }
    1673
    1674         if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
    1675             if (leftExpression instanceof VariableExpression || leftExpression.getClass() == PropertyExpression.class
    1676                                                              || leftExpression instanceof FieldExpression
    1677                                                              || leftExpression instanceof AttributeExpression
    1678                                                              || leftExpression instanceof DeclarationExpression) {
    1679                 // Do nothing.
    1680             }
    1681             else if (leftExpression instanceof ConstantExpression) {
    1682                 throw new ASTRuntimeException(node, "\n[" + ((ConstantExpression) leftExpression).getValue() + "] is a constant expression, but it should be a variable expression");
    1683             }
    1684             else if (leftExpression instanceof BinaryExpression) {
    1685                 Expression leftexp = ((BinaryExpression) leftExpression).getLeftExpression();
    1686                 int lefttype = ((BinaryExpression) leftExpression).getOperation().getType();
    1687                 if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR) && lefttype != Types.LEFT_SQUARE_BRACKET) {
    1688                     throw new ASTRuntimeException(node, "\n" + ((BinaryExpression) leftExpression).getText() + " is a binary expression, but it should be a variable expression");
    1689                 }
    1690             }
    1691             else if (leftExpression instanceof GStringExpression) {
    1692                 throw new ASTRuntimeException(node, "\n\"" + ((GStringExpression) leftExpression).getText() + "\" is a GString expression, but it should be a variable expression");
    1693             }
    1694             else if (leftExpression instanceof MethodCallExpression) {
    1695                 throw new ASTRuntimeException(node, "\n\"" + ((MethodCallExpression) leftExpression).getText() + "\" is a method call expression, but it should be a variable expression");
    1696             }
    1697             else if (leftExpression instanceof MapExpression) {
    1698                 throw new ASTRuntimeException(node, "\n'" + ((MapExpression) leftExpression).getText() + "' is a map expression, but it should be a variable expression");
    1699             }
    1700             else {
    1701                 throw new ASTRuntimeException(node, "\n" + leftExpression.getClass() + ", with its value '" + leftExpression.getText() + "', is a bad expression as the LSH of an assignment operator");
    1702             }
    1703         }
    1704         /*if (rightNode == null) {
    1705             throw new NullPointerException("No rightNode associated with binary expression");
    1706         }*/
    1707         Expression rightExpression = expression(rightNode);
    1708         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
    1709         configureAST(binaryExpression, node);
    1710         return binaryExpression;
    1711     }
    1712
    1713     protected Expression prefixExpression(AST node, int token) {
    1714         Expression expression = expression(node.getFirstChild());
    1715         PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
    1716         configureAST(prefixExpression, node);
    1717         return prefixExpression;
    1718     }
    1719
    1720     protected Expression postfixExpression(AST node, int token) {
    1721         Expression expression = expression(node.getFirstChild());
    1722         PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
    1723         configureAST(postfixExpression, node);
    1724         return postfixExpression;
    1725     }
    1726
    1727     protected BooleanExpression booleanExpression(AST node) {
    1728         BooleanExpression booleanExpression = new BooleanExpression(expression(node));
    1729         configureAST(booleanExpression, node);
    1730         return booleanExpression;
    1731     }
    1732
    1733     protected Expression dotExpression(AST node) {
    1734         // lets decide if this is a propery invocation or a method call
    1735         AST leftNode = node.getFirstChild();
    1736         if (leftNode != null) {
    1737             AST identifierNode = leftNode.getNextSibling();
    1738             if (identifierNode != null) {
    1739                 Expression leftExpression = expression(leftNode);
    1740                 if (isType(SELECT_SLOT, identifierNode)) {
    1741                     Expression field = expression(identifierNode.getFirstChild(),true);
    1742                     AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field, node.getType() != DOT);
    1743                     if (node.getType() == SPREAD_DOT) {
    1744                         attributeExpression.setSpreadSafe(true);
    1745                     }
    1746                     configureAST(attributeExpression, node);
    1747                     return attributeExpression;
    1748                 }
    1749                 Expression property = expression(identifierNode,true);
    1750
    1751                 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
    1752                 if (node.getType() == SPREAD_DOT) {
    1753                     propertyExpression.setSpreadSafe(true);
    1754                 }
    1755                 configureAST(propertyExpression, node);
    1756                 return propertyExpression;
    1757             }
    1758         }
    1759         return methodCallExpression(node);
    1760     }
    1761
    1762     protected Expression specialConstructorCallExpression(AST methodCallNode, ClassNode special) {
    1763         AST node = methodCallNode.getFirstChild();
    1764         Expression arguments = arguments(node);
    1765
    1766         ConstructorCallExpression expression = new ConstructorCallExpression(special, arguments);
    1767         configureAST(expression, methodCallNode);
    1768         return expression;
    1769     }
    1770
    1771     private int getTypeInParenthesis(AST node) {
    1772         if (! isType(EXPR,node) ) node = node.getFirstChild();
    1773         while (node!=null &&isType(EXPR,node) && node.getNextSibling()==null) {
    1774             node = node.getFirstChild();
    1775         }
    1776         if (node==null) return -1;
    1777         return node.getType();
    1778     }
    1779
    1780     protected Expression methodCallExpression(AST methodCallNode) {
    1781         AST node = methodCallNode.getFirstChild();
    1782         /* // Bad idea, since foo(1)(2) is valid Groovy for foo(1).call(2).
    1783         if (isType(METHOD_CALL, node)) {
    1784             // sometimes method calls get wrapped in method calls for some wierd reason
    1785             return methodCallExpression(node);
    1786         }
    1787         */
    1788
    1789         Expression objectExpression;
    1790         AST selector;
    1791         AST elist = node.getNextSibling();
    1792
    1793         boolean implicitThis = false;
    1794         boolean safe = isType(OPTIONAL_DOT, node);
    1795         boolean spreadSafe = isType(SPREAD_DOT, node);
    1796         if (isType(DOT, node) || safe || spreadSafe) {
    1797             AST objectNode = node.getFirstChild();
    1798             objectExpression = expression(objectNode);
    1799             selector = objectNode.getNextSibling();
    1800         } else {
    1801             implicitThis = true;
    1802             objectExpression = VariableExpression.THIS_EXPRESSION;
    1803             selector = node;
    1804         }
    1805
    1806         Expression name = null;
    1807         if (isType(LITERAL_super, selector)) {
    1808             implicitThis = true;
    1809             name = new ConstantExpression("super");
    1810             if (objectExpression == VariableExpression.THIS_EXPRESSION) {
    1811                 objectExpression = VariableExpression.SUPER_EXPRESSION;
    1812             }
    1813         } else if (isPrimitiveTypeLiteral(selector)) {
    1814             throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
    1815                     + " cannot be used as a method name");
    1816         } else if (isType(SELECT_SLOT, selector)) {
    1817             Expression field = expression(selector.getFirstChild(),true);
    1818             AttributeExpression attributeExpression = new AttributeExpression(objectExpression, field, node.getType() != DOT);
    1819             configureAST(attributeExpression, node);
    1820             Expression arguments = arguments(elist);
    1821             MethodCallExpression expression = new MethodCallExpression(attributeExpression, "call", arguments);
    1822             configureAST(expression, methodCallNode);
    1823             return expression;
    1824         } else if
    1825                (isType(DYNAMIC_MEMBER, selector) || isType(IDENT,selector) ||
    1826                 isType(STRING_CONSTRUCTOR,selector) || isType (STRING_LITERAL,selector))
    1827         {
    1828             name = expression(selector,true);
    1829         } else {
    1830             implicitThis = false;
    1831             name = new ConstantExpression("call");
    1832             objectExpression = expression(selector,true);
    1833         }
    1834
    1835         Expression arguments = arguments(elist);
    1836         MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
    1837         expression.setSafe(safe);
    1838         expression.setSpreadSafe(spreadSafe);
    1839         expression.setImplicitThis(implicitThis);
    1840         Expression ret = expression;
    1841         //FIXME: do we really want this() to create a new object regardless
    1842         // the position.. for example not as first statement in a constructor
    1843         // this=first statement in contructor is handled by specialConstructorCallExpression
    1844         // we may have to add a check and remove this part of the code
    1845         if (implicitThis && "this".equals(expression.getMethodAsString())) {
    1846             ret = new ConstructorCallExpression(this.classNode, arguments);
    1847         }
    1848         configureAST(ret, methodCallNode);
    1849         return ret;
    1850     }
    1851
    1852     protected Expression constructorCallExpression(AST node) {
    1853         AST constructorCallNode = node;
    1854         ClassNode type = buildName(constructorCallNode);
    1855
    1856         if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
    1857             node = node.getFirstChild();
    1858         }
    1859
    1860         AST elist = node.getNextSibling();
    1861
    1862         if (elist == null && isType(ELIST, node)) {
    1863             elist = node;
    1864             if ("(".equals(type.getName())) {
    1865                 type = classNode;
    1866             }
    1867         }
    1868
    1869         if (isType(ARRAY_DECLARATOR, elist)) {
    1870             AST expressionNode = elist.getFirstChild();
    1871             if (expressionNode == null) {
    1872                 throw new ASTRuntimeException(elist, "No expression for the array constructor call");
    1873             }
    1874             List size = arraySizeExpression(expressionNode);
    1875             ArrayExpression arrayExpression = new ArrayExpression(type, null, size);
    1876             configureAST(arrayExpression, constructorCallNode);
    1877             return arrayExpression;
    1878         }
    1879         Expression arguments = arguments(elist);
    1880         ConstructorCallExpression expression = new ConstructorCallExpression(type, arguments);
    1881         configureAST(expression, constructorCallNode);
    1882         return expression;
    1883     }
    1884
    1885     protected List arraySizeExpression(AST node) {
    1886         List list;
    1887         Expression size = null;
    1888     	if (isType(ARRAY_DECLARATOR,node)) {
    1889     		AST right = node.getNextSibling();
    1890         	if (right!=null) {
    1891         		size = expression(right);
    1892         	} else {
    1893         		size = ConstantExpression.EMTPY_EXPRESSION;
    1894         	}
    1895         	list = arraySizeExpression(node.getFirstChild());
    1896         } else {
    1897         	size = expression(node);
    1898         	list = new ArrayList();
    1899         }
    1900     	list.add(size);
    1901     	return list;
    1902     }
    1903
    1904     protected Expression arguments(AST elist) {
    1905         List expressionList = new ArrayList();
    1906         // FIXME: all labeled arguments should follow any unlabeled arguments
    1907         boolean namedArguments = false;
    1908         for (AST node = elist; node != null; node = node.getNextSibling()) {
    1909             if (isType(ELIST, node)) {
    1910                 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
    1911                     namedArguments |= addArgumentExpression(child, expressionList);
    1912                 }
    1913             }
    1914             else {
    1915                 namedArguments |= addArgumentExpression(node, expressionList);
    1916             }
    1917         }
    1918         if (namedArguments) {
    1919             if (!expressionList.isEmpty()) {
    1920                 // lets remove any non-MapEntryExpression instances
    1921                 // such as if the last expression is a ClosureExpression
    1922                 // so lets wrap the named method calls in a Map expression
    1923                 List argumentList = new ArrayList();
    1924                 for (Iterator iter = expressionList.iterator(); iter.hasNext();) {
    1925                     Expression expression = (Expression) iter.next();
    1926                     if (!(expression instanceof MapEntryExpression)) {
    1927                         argumentList.add(expression);
    1928                     }
    1929                 }
    1930                 if (!argumentList.isEmpty()) {
    1931                     expressionList.removeAll(argumentList);
    1932                     MapExpression mapExpression = new MapExpression(expressionList);
    1933                     configureAST(mapExpression, elist);
    1934                     argumentList.add(0, mapExpression);
    1935                     ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
    1936                     configureAST(argumentListExpression, elist);
    1937                     return argumentListExpression;
    1938                 }
    1939             }
    1940             NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
    1941             configureAST(namedArgumentListExpression, elist);
    1942             return namedArgumentListExpression;
    1943         }
    1944         else {
    1945             ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
    1946             configureAST(argumentListExpression, elist);
    1947             return argumentListExpression;
    1948         }
    1949     }
    1950
    1951     protected boolean addArgumentExpression(AST node, List expressionList) {
    1952         if (node.getType() == SPREAD_MAP_ARG) {
    1953             AST rightNode = node.getFirstChild();
    1954             Expression keyExpression = spreadMapExpression(node);
    1955             Expression rightExpression = expression(rightNode);
    1956             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
    1957             expressionList.add(mapEntryExpression);
    1958             return true;
    1959         }
    1960         else {
    1961             Expression expression = expression(node);
    1962             expressionList.add(expression);
    1963             return expression instanceof MapEntryExpression;
    1964         }
    1965     }
    1966
    1967     protected Expression expressionList(AST node) {
    1968         List expressionList = new ArrayList();
    1969         for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
    1970             expressionList.add(expression(child));
    1971         }
    1972         if (expressionList.size() == 1) {
    1973             return (Expression) expressionList.get(0);
    1974         }
    1975         else {
    1976             ListExpression listExpression = new ListExpression(expressionList);
    1977             configureAST(listExpression, node);
    1978             return listExpression;
    1979         }
    1980     }
    1981
    1982     protected ClosureExpression closureExpression(AST node) {
    1983         AST paramNode = node.getFirstChild();
    1984         Parameter[] parameters = null;
    1985         AST codeNode = paramNode;
    1986         if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
    1987             parameters = parameters(paramNode);
    1988             codeNode = paramNode.getNextSibling();
    1989         }
    1990         Statement code = statementListNoChild(codeNode);
    1991         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
    1992         configureAST(closureExpression, node);
    1993         return closureExpression;
    1994     }
    1995
    1996     protected Expression blockExpression(AST node) {
    1997         AST codeNode = node.getFirstChild();
    1998         if (codeNode == null)  return ConstantExpression.NULL;
    1999         if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
    2000             // Simplify common case of {expr} to expr.
    2001             return expression(codeNode);
    2002         }
    2003         Parameter[] parameters = Parameter.EMPTY_ARRAY;
    2004         Statement code = statementListNoChild(codeNode);
    2005         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
    2006         configureAST(closureExpression, node);
    2007         // Call it immediately.
    2008         String callName = "call";
    2009         Expression noArguments = new ArgumentListExpression();
    2010         MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
    2011         configureAST(call, node);
    2012         return call;
    2013     }
    2014
    2015     protected Expression negateExpression(AST negateExpr) {
    2016         AST node = negateExpr.getFirstChild();
    2017
    2018         // if we are a number literal then lets just parse it
    2019         // as the negation operator on MIN_INT causes rounding to a long
    2020         String text = node.getText();
    2021         switch (node.getType()) {
    2022             case NUM_DOUBLE:
    2023             case NUM_FLOAT:
    2024             case NUM_BIG_DECIMAL:
    2025                 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
    2026                 configureAST(constantExpression, negateExpr);
    2027                 return constantExpression;
    2028
    2029             case NUM_BIG_INT:
    2030             case NUM_INT:
    2031             case NUM_LONG:
    2032                 ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
    2033                 configureAST(constantLongExpression, negateExpr);
    2034                 return constantLongExpression;
    2035
    2036             default:
    2037                 NegationExpression negationExpression = new NegationExpression(expression(node));
    2038                 configureAST(negationExpression, negateExpr);
    2039                 return negationExpression;
    2040         }
    2041     }
    2042
    2043     protected ConstantExpression decimalExpression(AST node) {
    2044         String text = node.getText();
    2045         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
    2046         configureAST(constantExpression, node);
    2047         return constantExpression;
    2048     }
    2049
    2050     protected ConstantExpression integerExpression(AST node) {
    2051         String text = node.getText();
    2052         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseInteger(text));
    2053         configureAST(constantExpression, node);
    2054         return constantExpression;
    2055     }
    2056
    2057     protected Expression gstring(AST gstringNode) {
    2058         List strings = new ArrayList();
    2059         List values = new ArrayList();
    2060
    2061         StringBuffer buffer = new StringBuffer();
    2062
    2063         boolean isPrevString = false;
    2064
    2065         for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
    2066             int type = node.getType();
    2067             String text = null;
    2068             switch (type) {
    2069
    2070                 case STRING_LITERAL:
    2071                     if (isPrevString)  assertNodeType(IDENT, node);  // parser bug
    2072                     isPrevString = true;
    2073                     text = node.getText();
    2074                     ConstantExpression constantExpression = new ConstantExpression(text);
    2075                     configureAST(constantExpression, node);
    2076                     strings.add(constantExpression);
    2077                     buffer.append(text);
    2078                     break;
    2079
    2080                 default:
    2081                     {
    2082                         if (!isPrevString)  assertNodeType(IDENT, node);  // parser bug
    2083                         isPrevString = false;
    2084                         Expression expression = expression(node);
    2085                         values.add(expression);
    2086                         buffer.append("$");
    2087                         buffer.append(expression.getText());
    2088                     }
    2089                     break;
    2090             }
    2091         }
    2092         GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
    2093         configureAST(gStringExpression, gstringNode);
    2094         return gStringExpression;
    2095     }
    2096
    2097     protected ClassNode type(AST typeNode) {
    2098         // TODO intern types?
    2099         // TODO configureAST(...)
    2100         return buildName(typeNode.getFirstChild());
    2101     }
    2102
    2103     public static String qualifiedName(AST qualifiedNameNode) {
    2104         if (isType(IDENT, qualifiedNameNode)) {
    2105             return qualifiedNameNode.getText();
    2106         }
    2107         if (isType(DOT, qualifiedNameNode)) {
    2108             AST node = qualifiedNameNode.getFirstChild();
    2109             StringBuffer buffer = new StringBuffer();
    2110             boolean first = true;
    2111
    2112             for (; node != null; node = node.getNextSibling()) {
    2113                 if (first) {
    2114                     first = false;
    2115                 }
    2116                 else {
    2117                     buffer.append(".");
    2118                 }
    2119                 buffer.append(qualifiedName(node));
    2120             }
    2121             return buffer.toString();
    2122         }
    2123         else {
    2124             return qualifiedNameNode.getText();
    2125         }
    2126     }
    2127
    2128     protected ClassNode makeType(AST typeNode) {
    2129         ClassNode answer = ClassHelper.DYNAMIC_TYPE;
    2130         AST node = typeNode.getFirstChild();
    2131         if (node != null) {
    2132             if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
    2133                 return makeType(node).makeArray();
    2134              }
    2135             return ClassHelper.make(qualifiedName(node));
    2136         }
    2137         return answer;
    2138     }
    2139
    2140     /***
    2141      * Performs a name resolution to see if the given name is a type from imports,
    2142      * aliases or newly created classes
    2143      */
    2144     /*protected String resolveTypeName(String name, boolean safe) {
    2145         if (name == null) {
    2146             return null;
    2147         }
    2148         return resolveNewClassOrName(name, safe);
    2149     }*/
    2150
    2151     /***
    2152      * Extracts an identifier from the Antlr AST and then performs a name resolution
    2153      * to see if the given name is a type from imports, aliases or newly created classes
    2154      */
    2155     protected ClassNode buildName(AST node) {
    2156         if (isType(TYPE, node)) {
    2157             node = node.getFirstChild();
    2158         }
    2159         ClassNode answer = null;
    2160         if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
    2161             answer = ClassHelper.make(qualifiedName(node));
    2162         }
    2163         else if (isPrimitiveTypeLiteral(node)) {
    2164             answer = ClassHelper.make(node.getText());
    2165         }
    2166         else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
    2167             AST child = node.getFirstChild();
    2168             return buildName(child).makeArray();
    2169         }
    2170         else {
    2171             String identifier = node.getText();
    2172             answer = ClassHelper.make(identifier);
    2173         }
    2174         AST nextSibling = node.getNextSibling();
    2175         if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
    2176             return answer.makeArray();
    2177         }
    2178         else {
    2179             return answer;
    2180         }
    2181     }
    2182
    2183     protected boolean isPrimitiveTypeLiteral(AST node) {
    2184         int type = node.getType();
    2185         switch (type) {
    2186             case LITERAL_boolean:
    2187             case LITERAL_byte:
    2188             case LITERAL_char:
    2189             case LITERAL_double:
    2190             case LITERAL_float:
    2191             case LITERAL_int:
    2192             case LITERAL_long:
    2193             case LITERAL_short:
    2194                 return true;
    2195
    2196             default:
    2197                 return false;
    2198         }
    2199     }
    2200
    2201     /***
    2202      * Extracts an identifier from the Antlr AST
    2203      */
    2204     protected String identifier(AST node) {
    2205         assertNodeType(IDENT, node);
    2206         return node.getText();
    2207     }
    2208
    2209     protected String label(AST labelNode) {
    2210         AST node = labelNode.getFirstChild();
    2211         if (node == null) {
    2212             return null;
    2213         }
    2214         return identifier(node);
    2215     }
    2216
    2217
    2218
    2219     // Helper methods
    2220     //-------------------------------------------------------------------------
    2221
    2222
    2223     /***
    2224      * Returns true if the modifiers flags contain a visibility modifier
    2225      */
    2226     protected boolean hasVisibility(int modifiers) {
    2227         return (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
    2228     }
    2229
    2230     protected void configureAST(ASTNode node, AST ast) {
    2231         if (ast==null) throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure "+node.getClass().getName()+" with null Node");
    2232         node.setColumnNumber(ast.getColumn());
    2233         node.setLineNumber(ast.getLine());
    2234         if (ast instanceof GroovySourceAST) {
    2235             node.setLastColumnNumber(((GroovySourceAST)ast).getColumnLast());
    2236             node.setLastLineNumber(((GroovySourceAST)ast).getLineLast());
    2237         }
    2238
    2239         // TODO we could one day store the Antlr AST on the Groovy AST
    2240         // node.setCSTNode(ast);
    2241     }
    2242
    2243     protected static Token makeToken(int typeCode, AST node) {
    2244         return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
    2245     }
    2246
    2247     protected String getFirstChildText(AST node) {
    2248         AST child = node.getFirstChild();
    2249         return child != null ? child.getText() : null;
    2250     }
    2251
    2252
    2253     public static boolean isType(int typeCode, AST node) {
    2254         return node != null && node.getType() == typeCode;
    2255     }
    2256
    2257     private String getTokenName(int token) {
    2258         if (tokenNames==null) return ""+token;
    2259         return tokenNames[token];
    2260     }
    2261
    2262     private String getTokenName(AST node) {
    2263         if (node==null) return "null";
    2264         return getTokenName(node.getType());
    2265     }
    2266
    2267     protected void assertNodeType(int type, AST node) {
    2268         if (node == null) {
    2269             throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
    2270         }
    2271         if (node.getType() != type) {
    2272             throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
    2273         }
    2274     }
    2275
    2276     protected void notImplementedYet(AST node) {
    2277         throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
    2278     }
    2279
    2280     protected void unknownAST(AST node) {
    2281         if (node.getType() == CLASS_DEF) {
    2282             throw new ASTRuntimeException(node,
    2283                     "Class definition not expected here. Possible attempt to use inner class. " +
    2284                             "Inner classes not supported, perhaps try using a closure instead.");
    2285         }
    2286         throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
    2287     }
    2288
    2289     protected void dumpTree(AST ast) {
    2290         for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
    2291             dump(node);
    2292         }
    2293     }
    2294
    2295     protected void dump(AST node) {
    2296         System.out.println("Type: " + getTokenName(node) + " text: " + node.getText());
    2297     }
    2298 }