0001: /**
0002: *
0003: * Copyright 2004 James Strachan
0004: *
0005: * Licensed under the Apache License, Version 2.0 (the "License");
0006: * you may not use this file except in compliance with the License.
0007: * You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: *
0017: **/package org.codehaus.groovy.antlr;
0018:
0019: import antlr.RecognitionException;
0020: import antlr.TokenStreamException;
0021: import antlr.TokenStreamRecognitionException;
0022: import antlr.collections.AST;
0023: import com.thoughtworks.xstream.XStream;
0024:
0025: import org.codehaus.groovy.GroovyBugError;
0026: import org.codehaus.groovy.antlr.parser.GroovyLexer;
0027: import org.codehaus.groovy.antlr.parser.GroovyRecognizer;
0028: import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
0029: import org.codehaus.groovy.antlr.treewalker.*;
0030: import org.codehaus.groovy.ast.*;
0031: import org.codehaus.groovy.ast.expr.*;
0032: import org.codehaus.groovy.ast.stmt.*;
0033: import org.codehaus.groovy.control.CompilationFailedException;
0034: import org.codehaus.groovy.control.ParserPlugin;
0035: import org.codehaus.groovy.control.SourceUnit;
0036: import org.codehaus.groovy.syntax.*;
0037: import org.objectweb.asm.Opcodes;
0038:
0039: import java.io.*;
0040: import java.security.AccessController;
0041: import java.security.PrivilegedAction;
0042: import java.util.ArrayList;
0043: import java.util.Iterator;
0044: import java.util.List;
0045:
0046: /**
0047: * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime
0048: *
0049: * @author <a href="mailto:jstrachan@protique.com">James Strachan</a>
0050: * @version $Revision: 4526 $
0051: */
0052: public class AntlrParserPlugin extends ASTHelper implements
0053: ParserPlugin, GroovyTokenTypes {
0054:
0055: private AST ast;
0056: private ClassNode classNode;
0057: private String[] tokenNames;
0058:
0059: public Reduction parseCST(final SourceUnit sourceUnit, Reader reader)
0060: throws CompilationFailedException {
0061: ast = null;
0062:
0063: setController(sourceUnit);
0064:
0065: SourceBuffer sourceBuffer = new SourceBuffer();
0066: UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(
0067: reader, sourceBuffer);
0068: GroovyLexer lexer = new GroovyLexer(unicodeReader);
0069: unicodeReader.setLexer(lexer);
0070: GroovyRecognizer parser = GroovyRecognizer.make(lexer);
0071: parser.setSourceBuffer(sourceBuffer);
0072: tokenNames = parser.getTokenNames();
0073: parser.setFilename(sourceUnit.getName());
0074:
0075: // start parsing at the compilationUnit rule
0076: try {
0077: parser.compilationUnit();
0078: } catch (TokenStreamRecognitionException tsre) {
0079: RecognitionException e = tsre.recog;
0080: SyntaxException se = new SyntaxException(e.getMessage(), e,
0081: e.getLine(), e.getColumn());
0082: se.setFatal(true);
0083: sourceUnit.addError(se);
0084: } catch (RecognitionException e) {
0085: SyntaxException se = new SyntaxException(e.getMessage(), e,
0086: e.getLine(), e.getColumn());
0087: se.setFatal(true);
0088: sourceUnit.addError(se);
0089: } catch (TokenStreamException e) {
0090: sourceUnit.addException(e);
0091: }
0092:
0093: ast = parser.getAST();
0094:
0095: AntlrASTProcessor snippets = new AntlrASTProcessSnippets(
0096: sourceBuffer);
0097: ast = snippets.process(ast);
0098:
0099: AccessController.doPrivileged(new PrivilegedAction() {
0100: public Object run() {
0101: outputASTInVariousFormsIfNeeded(sourceUnit);
0102: return null;
0103: }
0104: });
0105:
0106: return null; //new Reduction(Tpken.EOF);
0107: }
0108:
0109: public SourceSummary getSummary() {
0110: SummaryCollector summaryCollector = new SummaryCollector();
0111: AntlrASTProcessor treewalker = new PreOrderTraversal(
0112: summaryCollector);
0113: treewalker.process(ast);
0114: return summaryCollector.getSourceSummary();
0115: }
0116:
0117: private void outputASTInVariousFormsIfNeeded(SourceUnit sourceUnit) {
0118: // straight xstream output of AST
0119: if ("xml".equals(System.getProperty("antlr.ast"))) {
0120: saveAsXML(sourceUnit.getName(), ast);
0121: }
0122:
0123: // 'pretty printer' output of AST
0124: if ("groovy".equals(System.getProperty("antlr.ast"))) {
0125: try {
0126: PrintStream out = new PrintStream(new FileOutputStream(
0127: sourceUnit.getName() + ".pretty.groovy"));
0128: Visitor visitor = new SourcePrinter(out, tokenNames);
0129: AntlrASTProcessor treewalker = new SourceCodeTraversal(
0130: visitor);
0131: treewalker.process(ast);
0132: } catch (FileNotFoundException e) {
0133: System.out.println("Cannot create "
0134: + sourceUnit.getName() + ".pretty.groovy");
0135: }
0136: }
0137:
0138: // output AST in format suitable for opening in http://freemind.sourceforge.net
0139: // which is a really nice way of seeing the AST, folding nodes etc
0140: if ("mindmap".equals(System.getProperty("antlr.ast"))) {
0141: try {
0142: PrintStream out = new PrintStream(new FileOutputStream(
0143: sourceUnit.getName() + ".mm"));
0144: Visitor visitor = new MindMapPrinter(out, tokenNames);
0145: AntlrASTProcessor treewalker = new PreOrderTraversal(
0146: visitor);
0147: treewalker.process(ast);
0148: } catch (FileNotFoundException e) {
0149: System.out.println("Cannot create "
0150: + sourceUnit.getName() + ".mm");
0151: }
0152: }
0153:
0154: // html output of AST
0155: if ("html".equals(System.getProperty("antlr.ast"))) {
0156: try {
0157: PrintStream out = new PrintStream(new FileOutputStream(
0158: sourceUnit.getName() + ".html"));
0159: List v = new ArrayList();
0160: v.add(new NodeAsHTMLPrinter(out, tokenNames));
0161: v.add(new SourcePrinter(out, tokenNames));
0162: Visitor visitors = new CompositeVisitor(v);
0163: AntlrASTProcessor treewalker = new SourceCodeTraversal(
0164: visitors);
0165: treewalker.process(ast);
0166: } catch (FileNotFoundException e) {
0167: System.out.println("Cannot create "
0168: + sourceUnit.getName() + ".html");
0169: }
0170: }
0171:
0172: }
0173:
0174: private void saveAsXML(String name, AST ast) {
0175: XStream xstream = new XStream();
0176: try {
0177: xstream.toXML(ast, new FileWriter(name + ".antlr.xml"));
0178: System.out.println("Written AST to " + name + ".antlr.xml");
0179: } catch (Exception e) {
0180: System.out.println("Couldn't write to " + name
0181: + ".antlr.xml");
0182: e.printStackTrace();
0183: }
0184: }
0185:
0186: public ModuleNode buildAST(SourceUnit sourceUnit,
0187: ClassLoader classLoader, Reduction cst)
0188: throws ParserException {
0189: setClassLoader(classLoader);
0190: makeModule();
0191: try {
0192: convertGroovy(ast);
0193: } catch (ASTRuntimeException e) {
0194: throw new ASTParserException(e.getMessage() + ". File: "
0195: + sourceUnit.getName(), e);
0196: }
0197: return output;
0198: }
0199:
0200: /**
0201: * Converts the Antlr AST to the Groovy AST
0202: */
0203: protected void convertGroovy(AST node) {
0204: while (node != null) {
0205: int type = node.getType();
0206: switch (type) {
0207: case PACKAGE_DEF:
0208: packageDef(node);
0209: break;
0210:
0211: case IMPORT:
0212: importDef(node);
0213: break;
0214:
0215: case CLASS_DEF:
0216: classDef(node);
0217: break;
0218:
0219: case INTERFACE_DEF:
0220: interfaceDef(node);
0221: break;
0222:
0223: case METHOD_DEF:
0224: methodDef(node);
0225: break;
0226:
0227: default: {
0228: Statement statement = statement(node);
0229: output.addStatement(statement);
0230: }
0231: }
0232: node = node.getNextSibling();
0233: }
0234: }
0235:
0236: // Top level control structures
0237: //-------------------------------------------------------------------------
0238:
0239: protected void packageDef(AST packageDef) {
0240: AST node = packageDef.getFirstChild();
0241: if (isType(ANNOTATIONS, node)) {
0242: node = node.getNextSibling();
0243: }
0244: String name = qualifiedName(node);
0245: setPackageName(name);
0246: }
0247:
0248: protected void importDef(AST importNode) {
0249: // TODO handle static imports
0250:
0251: AST node = importNode.getFirstChild();
0252:
0253: String alias = null;
0254: if (isType(LITERAL_as, node)) {
0255: //import is like "import Foo as Bar"
0256: node = node.getFirstChild();
0257: AST aliasNode = node.getNextSibling();
0258: alias = identifier(aliasNode);
0259: }
0260:
0261: if (node.getNumberOfChildren() == 0) {
0262: // import is like "import Foo"
0263: String name = identifier(node);
0264: ClassNode type = ClassHelper.make(name);
0265: configureAST(type, importNode);
0266: importClass(type, name, alias);
0267: return;
0268: }
0269:
0270: AST packageNode = node.getFirstChild();
0271: String packageName = qualifiedName(packageNode);
0272: AST nameNode = packageNode.getNextSibling();
0273: if (isType(STAR, nameNode)) {
0274: // import is like "import foo.*"
0275: importPackageWithStar(packageName);
0276: if (alias != null)
0277: throw new GroovyBugError(
0278: "imports like 'import foo.* as Bar' are not "
0279: + "supported and should be caught by the grammar");
0280: } else {
0281: // import is like "import foo.Bar"
0282: String name = identifier(nameNode);
0283: ClassNode type = ClassHelper.make(packageName + "." + name);
0284: configureAST(type, importNode);
0285: importClass(type, name, alias);
0286: }
0287: }
0288:
0289: protected void interfaceDef(AST classDef) {
0290: List annotations = new ArrayList();
0291: AST node = classDef.getFirstChild();
0292: int modifiers = Opcodes.ACC_PUBLIC;
0293: if (isType(MODIFIERS, node)) {
0294: modifiers = modifiers(node, annotations, modifiers);
0295: node = node.getNextSibling();
0296: }
0297: modifiers |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE;
0298:
0299: String name = identifier(node);
0300: node = node.getNextSibling();
0301: ClassNode super Class = ClassHelper.OBJECT_TYPE;
0302:
0303: ClassNode[] interfaces = {};
0304: if (isType(EXTENDS_CLAUSE, node)) {
0305: interfaces = interfaces(node);
0306: node = node.getNextSibling();
0307: }
0308:
0309: addNewClassName(name);
0310: classNode = new ClassNode(dot(getPackageName(), name),
0311: modifiers, super Class, interfaces, null);
0312: classNode.addAnnotations(annotations);
0313: configureAST(classNode, classDef);
0314:
0315: assertNodeType(OBJBLOCK, node);
0316: objectBlock(node);
0317: output.addClass(classNode);
0318: classNode = null;
0319: }
0320:
0321: protected void classDef(AST classDef) {
0322: List annotations = new ArrayList();
0323: AST node = classDef.getFirstChild();
0324: int modifiers = Opcodes.ACC_PUBLIC;
0325: if (isType(MODIFIERS, node)) {
0326: modifiers = modifiers(node, annotations, modifiers);
0327: node = node.getNextSibling();
0328: }
0329:
0330: String name = identifier(node);
0331: node = node.getNextSibling();
0332:
0333: ClassNode super Class = null;
0334: if (isType(EXTENDS_CLAUSE, node)) {
0335: super Class = makeType(node);
0336: node = node.getNextSibling();
0337: }
0338:
0339: ClassNode[] interfaces = {};
0340: if (isType(IMPLEMENTS_CLAUSE, node)) {
0341: interfaces = interfaces(node);
0342: node = node.getNextSibling();
0343: }
0344:
0345: // TODO read mixins
0346: MixinNode[] mixins = {};
0347:
0348: addNewClassName(name);
0349: classNode = new ClassNode(dot(getPackageName(), name),
0350: modifiers, super Class, interfaces, mixins);
0351: classNode.addAnnotations(annotations);
0352: configureAST(classNode, classDef);
0353:
0354: assertNodeType(OBJBLOCK, node);
0355: objectBlock(node);
0356: output.addClass(classNode);
0357: classNode = null;
0358: }
0359:
0360: protected void objectBlock(AST objectBlock) {
0361: for (AST node = objectBlock.getFirstChild(); node != null; node = node
0362: .getNextSibling()) {
0363: int type = node.getType();
0364: switch (type) {
0365: case OBJBLOCK:
0366: objectBlock(node);
0367: break;
0368:
0369: case METHOD_DEF:
0370: methodDef(node);
0371: break;
0372:
0373: case CTOR_IDENT:
0374: constructorDef(node);
0375: break;
0376:
0377: case VARIABLE_DEF:
0378: fieldDef(node);
0379: break;
0380:
0381: case STATIC_INIT:
0382: staticInit(node);
0383: break;
0384:
0385: case INSTANCE_INIT:
0386: objectInit(node);
0387: break;
0388:
0389: default:
0390: unknownAST(node);
0391: }
0392: }
0393: }
0394:
0395: protected void throwsList(AST node, List list) {
0396: String clazz = identifier(node);
0397: ClassNode exception = ClassHelper.make(clazz);
0398: list.add(exception);
0399: AST next = node.getNextSibling();
0400: if (next != null)
0401: throwsList(next, list);
0402: next = node.getFirstChild();
0403: if (next != null)
0404: throwsList(next, list);
0405: }
0406:
0407: protected void methodDef(AST methodDef) {
0408: List annotations = new ArrayList();
0409: AST node = methodDef.getFirstChild();
0410: int modifiers = Opcodes.ACC_PUBLIC;
0411: if (isType(MODIFIERS, node)) {
0412: modifiers = modifiers(node, annotations, modifiers);
0413: node = node.getNextSibling();
0414: }
0415:
0416: if (classNode != null
0417: && (classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) {
0418: modifiers |= Opcodes.ACC_ABSTRACT;
0419: }
0420:
0421: ClassNode returnType = null;
0422: if (isType(TYPE, node)) {
0423: returnType = makeType(node);
0424: node = node.getNextSibling();
0425: }
0426:
0427: String name = identifier(node);
0428: if (classNode != null) {
0429: if (classNode.getNameWithoutPackage().equals(name)) {
0430: throw new ASTRuntimeException(methodDef,
0431: "Invalid constructor format. Try remove the 'def' expression?");
0432: }
0433: }
0434: node = node.getNextSibling();
0435:
0436: assertNodeType(PARAMETERS, node);
0437: Parameter[] parameters = parameters(node);
0438: if (parameters == null)
0439: parameters = Parameter.EMPTY_ARRAY;
0440: node = node.getNextSibling();
0441:
0442: ClassNode[] exceptions = new ClassNode[0];
0443: if (isType(LITERAL_throws, node)) {
0444: AST throwsNode = node.getFirstChild();
0445: List exceptionList = new ArrayList();
0446: throwsList(throwsNode, exceptionList);
0447: exceptions = (ClassNode[]) exceptionList
0448: .toArray(exceptions);
0449: node = node.getNextSibling();
0450: }
0451:
0452: Statement code = null;
0453: if ((modifiers & Opcodes.ACC_ABSTRACT) == 0) {
0454: if (node == null) {
0455: throw new ASTRuntimeException(methodDef,
0456: "You defined a method without body. Try adding a body, or declare it abstract.");
0457: }
0458: assertNodeType(SLIST, node);
0459: code = statementList(node);
0460: }
0461:
0462: MethodNode methodNode = new MethodNode(name, modifiers,
0463: returnType, parameters, exceptions, code);
0464: methodNode.addAnnotations(annotations);
0465: configureAST(methodNode, methodDef);
0466: if (classNode != null) {
0467: classNode.addMethod(methodNode);
0468: } else {
0469: output.addMethod(methodNode);
0470: }
0471: }
0472:
0473: protected void staticInit(AST staticInit) {
0474: BlockStatement code = (BlockStatement) statementList(staticInit);
0475: classNode.addStaticInitializerStatements(code.getStatements(),
0476: false);
0477: }
0478:
0479: protected void objectInit(AST init) {
0480: BlockStatement code = (BlockStatement) statementList(init);
0481: classNode.addObjectInitializerStatements(code);
0482: }
0483:
0484: protected void constructorDef(AST constructorDef) {
0485: List annotations = new ArrayList();
0486: AST node = constructorDef.getFirstChild();
0487: int modifiers = Opcodes.ACC_PUBLIC;
0488: if (isType(MODIFIERS, node)) {
0489: modifiers = modifiers(node, annotations, modifiers);
0490: node = node.getNextSibling();
0491: }
0492:
0493: assertNodeType(PARAMETERS, node);
0494: Parameter[] parameters = parameters(node);
0495: if (parameters == null)
0496: parameters = Parameter.EMPTY_ARRAY;
0497: node = node.getNextSibling();
0498:
0499: ClassNode[] exceptions = new ClassNode[0];
0500: if (isType(LITERAL_throws, node)) {
0501: AST throwsNode = node.getFirstChild();
0502: List exceptionList = new ArrayList();
0503: throwsList(throwsNode, exceptionList);
0504: exceptions = (ClassNode[]) exceptionList
0505: .toArray(exceptions);
0506: node = node.getNextSibling();
0507: }
0508:
0509: assertNodeType(SLIST, node);
0510: Statement code = statementList(node);
0511:
0512: ConstructorNode constructorNode = classNode.addConstructor(
0513: modifiers, parameters, exceptions, code);
0514: constructorNode.addAnnotations(annotations);
0515: configureAST(constructorNode, constructorDef);
0516: }
0517:
0518: protected void fieldDef(AST fieldDef) {
0519: List annotations = new ArrayList();
0520: AST node = fieldDef.getFirstChild();
0521:
0522: int modifiers = 0;
0523: if (isType(MODIFIERS, node)) {
0524: modifiers = modifiers(node, annotations, modifiers);
0525: node = node.getNextSibling();
0526: }
0527:
0528: if (classNode.isInterface()) {
0529: modifiers |= Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
0530: if ((modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) == 0) {
0531: modifiers |= Opcodes.ACC_PUBLIC;
0532: }
0533: }
0534:
0535: ClassNode type = null;
0536: if (isType(TYPE, node)) {
0537: type = makeType(node);
0538: node = node.getNextSibling();
0539: }
0540:
0541: String name = identifier(node);
0542: node = node.getNextSibling();
0543:
0544: Expression initialValue = null;
0545: if (node != null) {
0546: assertNodeType(ASSIGN, node);
0547: initialValue = expression(node);
0548: }
0549:
0550: if (initialValue == null && type != null) {
0551: if (type == ClassHelper.int_TYPE) {
0552: initialValue = new ConstantExpression(new Integer(0));
0553: } else if (type == ClassHelper.long_TYPE) {
0554: initialValue = new ConstantExpression(new Long(0L));
0555: } else if (type == ClassHelper.double_TYPE) {
0556: initialValue = new ConstantExpression(new Double(0.0));
0557: } else if (type == ClassHelper.float_TYPE) {
0558: initialValue = new ConstantExpression(new Float(0.0F));
0559: } else if (type == ClassHelper.boolean_TYPE) {
0560: initialValue = ConstantExpression.FALSE;
0561: } else if (type == ClassHelper.short_TYPE) {
0562: initialValue = new ConstantExpression(new Short(
0563: (short) 0));
0564: } else if (type == ClassHelper.byte_TYPE) {
0565: initialValue = new ConstantExpression(
0566: new Byte((byte) 0));
0567: } else if (type == ClassHelper.char_TYPE) {
0568: initialValue = new ConstantExpression(new Character(
0569: (char) 0));
0570: }
0571: }
0572:
0573: FieldNode fieldNode = new FieldNode(name, modifiers, type,
0574: classNode, initialValue);
0575: fieldNode.addAnnotations(annotations);
0576: configureAST(fieldNode, fieldDef);
0577:
0578: if (!hasVisibility(modifiers)) {
0579: // lets set the modifiers on the field
0580: int fieldModifiers = 0;
0581: int flags = Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT
0582: | Opcodes.ACC_VOLATILE | Opcodes.ACC_FINAL;
0583:
0584: if (!hasVisibility(modifiers)) {
0585: modifiers |= Opcodes.ACC_PUBLIC;
0586: fieldModifiers |= Opcodes.ACC_PRIVATE;
0587: }
0588:
0589: // lets pass along any other modifiers we need
0590: fieldModifiers |= (modifiers & flags);
0591: fieldNode.setModifiers(fieldModifiers);
0592:
0593: PropertyNode propertyNode = new PropertyNode(fieldNode,
0594: modifiers, null, null);
0595: configureAST(propertyNode, fieldDef);
0596: classNode.addProperty(propertyNode);
0597: } else {
0598: fieldNode.setModifiers(modifiers);
0599: classNode.addField(fieldNode);
0600: }
0601: }
0602:
0603: protected ClassNode[] interfaces(AST node) {
0604: List interfaceList = new ArrayList();
0605: for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode
0606: .getNextSibling()) {
0607: interfaceList.add(ClassHelper
0608: .make(qualifiedName(implementNode)));
0609: }
0610: ClassNode[] interfaces = {};
0611: if (!interfaceList.isEmpty()) {
0612: interfaces = new ClassNode[interfaceList.size()];
0613: interfaceList.toArray(interfaces);
0614:
0615: }
0616: return interfaces;
0617: }
0618:
0619: protected Parameter[] parameters(AST parametersNode) {
0620: AST node = parametersNode.getFirstChild();
0621: if (node == null) {
0622: if (isType(IMPLICIT_PARAMETERS, parametersNode))
0623: return Parameter.EMPTY_ARRAY;
0624: return null;
0625: } else {
0626: List parameters = new ArrayList();
0627: do {
0628: parameters.add(parameter(node));
0629: node = node.getNextSibling();
0630: } while (node != null);
0631: Parameter[] answer = new Parameter[parameters.size()];
0632: parameters.toArray(answer);
0633: return answer;
0634: }
0635: }
0636:
0637: protected Parameter parameter(AST paramNode) {
0638: List annotations = new ArrayList();
0639: AST node = paramNode.getFirstChild();
0640:
0641: int modifiers = 0;
0642: if (isType(MODIFIERS, node)) {
0643: modifiers = modifiers(node, annotations, modifiers);
0644: node = node.getNextSibling();
0645: }
0646:
0647: ClassNode type = ClassHelper.DYNAMIC_TYPE;
0648: if (isType(TYPE, node)) {
0649: type = makeType(node);
0650: node = node.getNextSibling();
0651: }
0652:
0653: String name = identifier(node);
0654: node = node.getNextSibling();
0655: VariableExpression leftExpression = new VariableExpression(
0656: name, type);
0657: configureAST(leftExpression, paramNode);
0658:
0659: Parameter parameter = null;
0660: if (node != null) {
0661: assertNodeType(ASSIGN, node);
0662: Expression rightExpression = expression(node
0663: .getFirstChild());
0664: parameter = new Parameter(type, name, rightExpression);
0665: } else
0666: parameter = new Parameter(type, name);
0667:
0668: // TODO
0669: //configureAST(parameter,paramNode);
0670: //parameter.addAnnotations(annotations);
0671: return parameter;
0672: }
0673:
0674: protected int modifiers(AST modifierNode, List annotations,
0675: int defaultModifiers) {
0676: assertNodeType(MODIFIERS, modifierNode);
0677:
0678: boolean access = false;
0679: int answer = 0;
0680:
0681: for (AST node = modifierNode.getFirstChild(); node != null; node = node
0682: .getNextSibling()) {
0683: int type = node.getType();
0684: switch (type) {
0685: // annotations
0686: case ANNOTATION:
0687: annotations.add(annotation(node));
0688: break;
0689:
0690: // core access scope modifiers
0691: case LITERAL_private:
0692: answer = setModifierBit(node, answer,
0693: Opcodes.ACC_PRIVATE);
0694: access = setAccessTrue(node, access);
0695: break;
0696:
0697: case LITERAL_protected:
0698: answer = setModifierBit(node, answer,
0699: Opcodes.ACC_PROTECTED);
0700: access = setAccessTrue(node, access);
0701: break;
0702:
0703: case LITERAL_public:
0704: answer = setModifierBit(node, answer,
0705: Opcodes.ACC_PUBLIC);
0706: access = setAccessTrue(node, access);
0707: break;
0708:
0709: // other modifiers
0710: case ABSTRACT:
0711: answer = setModifierBit(node, answer,
0712: Opcodes.ACC_ABSTRACT);
0713: break;
0714:
0715: case FINAL:
0716: answer = setModifierBit(node, answer, Opcodes.ACC_FINAL);
0717: break;
0718:
0719: case LITERAL_native:
0720: answer = setModifierBit(node, answer,
0721: Opcodes.ACC_NATIVE);
0722: break;
0723:
0724: case LITERAL_static:
0725: answer = setModifierBit(node, answer,
0726: Opcodes.ACC_STATIC);
0727: break;
0728:
0729: case STRICTFP:
0730: answer = setModifierBit(node, answer,
0731: Opcodes.ACC_STRICT);
0732: break;
0733:
0734: case LITERAL_synchronized:
0735: answer = setModifierBit(node, answer,
0736: Opcodes.ACC_SYNCHRONIZED);
0737: break;
0738:
0739: case LITERAL_transient:
0740: answer = setModifierBit(node, answer,
0741: Opcodes.ACC_TRANSIENT);
0742: break;
0743:
0744: case LITERAL_volatile:
0745: answer = setModifierBit(node, answer,
0746: Opcodes.ACC_VOLATILE);
0747: break;
0748:
0749: default:
0750: unknownAST(node);
0751: }
0752: }
0753: if (!access) {
0754: answer |= defaultModifiers;
0755: }
0756: return answer;
0757: }
0758:
0759: protected boolean setAccessTrue(AST node, boolean access) {
0760: if (!access) {
0761: return true;
0762: } else {
0763: throw new ASTRuntimeException(
0764: node,
0765: "Cannot specify modifier: "
0766: + node.getText()
0767: + " when access scope has already been defined");
0768: }
0769: }
0770:
0771: protected int setModifierBit(AST node, int answer, int bit) {
0772: if ((answer & bit) != 0) {
0773: throw new ASTRuntimeException(node,
0774: "Cannot repeat modifier: " + node.getText());
0775: }
0776: return answer | bit;
0777: }
0778:
0779: protected AnnotationNode annotation(AST annotationNode) {
0780: AST node = annotationNode.getFirstChild();
0781: String name = identifier(node);
0782: AnnotationNode annotatedNode = new AnnotationNode(ClassHelper
0783: .make(name));
0784: configureAST(annotatedNode, node);
0785: while (true) {
0786: node = node.getNextSibling();
0787: if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) {
0788: AST memberNode = node.getFirstChild();
0789: String param = identifier(memberNode);
0790: Expression expression = expression(memberNode
0791: .getNextSibling());
0792: annotatedNode.addMember(param, expression);
0793: } else {
0794: break;
0795: }
0796: }
0797: return annotatedNode;
0798: }
0799:
0800: // Statements
0801: //-------------------------------------------------------------------------
0802:
0803: protected Statement statement(AST node) {
0804: Statement statement = null;
0805: int type = node.getType();
0806: switch (type) {
0807: case SLIST:
0808: case LITERAL_finally:
0809: statement = statementList(node);
0810: break;
0811:
0812: case METHOD_CALL:
0813: statement = methodCall(node);
0814: break;
0815:
0816: case VARIABLE_DEF:
0817: statement = variableDef(node);
0818: break;
0819:
0820: case LABELED_STAT:
0821: statement = labelledStatement(node);
0822: break;
0823:
0824: case LITERAL_assert:
0825: statement = assertStatement(node);
0826: break;
0827:
0828: case LITERAL_break:
0829: statement = breakStatement(node);
0830: break;
0831:
0832: case LITERAL_continue:
0833: statement = continueStatement(node);
0834: break;
0835:
0836: case LITERAL_if:
0837: statement = ifStatement(node);
0838: break;
0839:
0840: case LITERAL_for:
0841: statement = forStatement(node);
0842: break;
0843:
0844: case LITERAL_return:
0845: statement = returnStatement(node);
0846: break;
0847:
0848: case LITERAL_synchronized:
0849: statement = synchronizedStatement(node);
0850: break;
0851:
0852: case LITERAL_switch:
0853: statement = switchStatement(node);
0854: break;
0855:
0856: case LITERAL_with:
0857: statement = withStatement(node);
0858: break;
0859:
0860: case LITERAL_try:
0861: statement = tryStatement(node);
0862: break;
0863:
0864: case LITERAL_throw:
0865: statement = throwStatement(node);
0866: break;
0867:
0868: case LITERAL_while:
0869: statement = whileStatement(node);
0870: break;
0871:
0872: default:
0873: statement = new ExpressionStatement(expression(node));
0874: }
0875: if (statement != null) {
0876: configureAST(statement, node);
0877: }
0878: return statement;
0879: }
0880:
0881: protected Statement statementList(AST code) {
0882: return statementListNoChild(code.getFirstChild());
0883: }
0884:
0885: protected Statement statementListNoChild(AST node) {
0886: BlockStatement block = new BlockStatement();
0887: // no need to configureAST(block,node); as node is probably null
0888: for (; node != null; node = node.getNextSibling()) {
0889: block.addStatement(statement(node));
0890: }
0891: return block;
0892: }
0893:
0894: protected Statement assertStatement(AST assertNode) {
0895: AST node = assertNode.getFirstChild();
0896: BooleanExpression booleanExpression = booleanExpression(node);
0897: Expression messageExpression = null;
0898:
0899: node = node.getNextSibling();
0900: if (node != null) {
0901: messageExpression = expression(node);
0902: } else {
0903: messageExpression = ConstantExpression.NULL;
0904: }
0905: AssertStatement assertStatement = new AssertStatement(
0906: booleanExpression, messageExpression);
0907: configureAST(assertStatement, assertNode);
0908: return assertStatement;
0909: }
0910:
0911: protected Statement breakStatement(AST node) {
0912: BreakStatement breakStatement = new BreakStatement(label(node));
0913: configureAST(breakStatement, node);
0914: return breakStatement;
0915: }
0916:
0917: protected Statement continueStatement(AST node) {
0918: ContinueStatement continueStatement = new ContinueStatement(
0919: label(node));
0920: configureAST(continueStatement, node);
0921: return continueStatement;
0922: }
0923:
0924: protected Statement forStatement(AST forNode) {
0925: assertNotLegacyFor(forNode);
0926: AST inNode = forNode.getFirstChild();
0927: AST variableNode = inNode.getFirstChild();
0928: AST collectionNode = variableNode.getNextSibling();
0929:
0930: ClassNode type = ClassHelper.OBJECT_TYPE;
0931: if (isType(VARIABLE_DEF, variableNode)) {
0932: AST typeNode = variableNode.getFirstChild();
0933: assertNodeType(TYPE, typeNode);
0934:
0935: type = type(typeNode);
0936: variableNode = typeNode.getNextSibling();
0937: }
0938: String variable = identifier(variableNode);
0939:
0940: Expression collectionExpression = expression(collectionNode);
0941: Statement block = statement(inNode.getNextSibling());
0942: Parameter forParameter = new Parameter(type, variable);
0943:
0944: ForStatement forStatement = new ForStatement(forParameter,
0945: collectionExpression, block);
0946: configureAST(forStatement, forNode);
0947: return forStatement;
0948: }
0949:
0950: private void assertNotLegacyFor(AST forNode) {
0951: AST childNode = forNode.getFirstChild();
0952: boolean legacy = false;
0953: while (childNode != null) {
0954: int type = childNode.getType();
0955: if (type == FOR_INIT || type == FOR_CONDITION
0956: || type == FOR_ITERATOR) {
0957: legacy = true;
0958: break;
0959: }
0960: childNode = childNode.getNextSibling();
0961: }
0962: if (legacy) {
0963: throw new ASTRuntimeException(
0964: forNode,
0965: "For statement contains unexpected tokens. Possible attempt to use unsupported Java-style for loop.");
0966: }
0967: }
0968:
0969: protected Statement ifStatement(AST ifNode) {
0970: AST node = ifNode.getFirstChild();
0971: assertNodeType(EXPR, node);
0972: BooleanExpression booleanExpression = booleanExpression(node);
0973:
0974: node = node.getNextSibling();
0975: Statement ifBlock = statement(node);
0976:
0977: Statement elseBlock = EmptyStatement.INSTANCE;
0978: node = node.getNextSibling();
0979: if (node != null) {
0980: elseBlock = statement(node);
0981: }
0982: IfStatement ifStatement = new IfStatement(booleanExpression,
0983: ifBlock, elseBlock);
0984: configureAST(ifStatement, ifNode);
0985: return ifStatement;
0986: }
0987:
0988: protected Statement labelledStatement(AST labelNode) {
0989: AST node = labelNode.getFirstChild();
0990: String label = identifier(node);
0991: Statement statement = statement(node.getNextSibling());
0992: statement.setStatementLabel(label);
0993: return statement;
0994: }
0995:
0996: protected Statement methodCall(AST code) {
0997: Expression expression = methodCallExpression(code);
0998: ExpressionStatement expressionStatement = new ExpressionStatement(
0999: expression);
1000: configureAST(expressionStatement, code);
1001: return expressionStatement;
1002: }
1003:
1004: protected Statement variableDef(AST variableDef) {
1005: AST node = variableDef.getFirstChild();
1006: ClassNode type = null;
1007: if (isType(MODIFIERS, node)) {
1008: node = node.getNextSibling();
1009: }
1010: if (isType(TYPE, node)) {
1011: type = makeType(node);
1012: node = node.getNextSibling();
1013: }
1014:
1015: String name = identifier(node);
1016: node = node.getNextSibling();
1017:
1018: VariableExpression leftExpression = new VariableExpression(
1019: name, type);
1020: configureAST(leftExpression, variableDef);
1021:
1022: Expression rightExpression = ConstantExpression.NULL;
1023: if (node != null) {
1024: assertNodeType(ASSIGN, node);
1025:
1026: rightExpression = expression(node.getFirstChild());
1027: }
1028: Token token = makeToken(Types.ASSIGN, variableDef);
1029:
1030: // TODO should we have a variable declaration statement?
1031: DeclarationExpression expression = new DeclarationExpression(
1032: leftExpression, token, rightExpression);
1033: configureAST(expression, variableDef);
1034: ExpressionStatement expressionStatement = new ExpressionStatement(
1035: expression);
1036: configureAST(expressionStatement, variableDef);
1037: return expressionStatement;
1038: }
1039:
1040: protected Statement returnStatement(AST node) {
1041: AST exprNode = node.getFirstChild();
1042:
1043: // This will pick up incorrect sibling node if 'node' is a plain 'return'
1044: //
1045: //if (exprNode == null) {
1046: // exprNode = node.getNextSibling();
1047: //}
1048: if (exprNode != null) {
1049: Expression expression = expression(exprNode);
1050: if (expression instanceof ConstantExpression) {
1051: ConstantExpression constantExpr = (ConstantExpression) expression;
1052: if (constantExpr.getValue() == null) {
1053: return ReturnStatement.RETURN_NULL_OR_VOID;
1054: }
1055: }
1056: ReturnStatement returnStatement = new ReturnStatement(
1057: expression);
1058: configureAST(returnStatement, node);
1059: return returnStatement;
1060: } else {
1061: return ReturnStatement.RETURN_NULL_OR_VOID;
1062: }
1063: }
1064:
1065: protected Statement switchStatement(AST switchNode) {
1066: AST node = switchNode.getFirstChild();
1067: Expression expression = expression(node);
1068: Statement defaultStatement = EmptyStatement.INSTANCE;
1069:
1070: List list = new ArrayList();
1071: for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node
1072: .getNextSibling()) {
1073: AST child = node.getFirstChild();
1074: if (isType(LITERAL_case, child)) {
1075: list.add(caseStatement(child));
1076: } else {
1077: defaultStatement = statement(child.getNextSibling());
1078: }
1079: }
1080: if (node != null) {
1081: unknownAST(node);
1082: }
1083: SwitchStatement switchStatement = new SwitchStatement(
1084: expression, list, defaultStatement);
1085: configureAST(switchStatement, switchNode);
1086: return switchStatement;
1087: }
1088:
1089: protected CaseStatement caseStatement(AST node) {
1090: List expressions = new ArrayList();
1091: Statement statement = EmptyStatement.INSTANCE;
1092: AST nextSibling = node;
1093: do {
1094: Expression expression = expression(nextSibling
1095: .getFirstChild());
1096: expressions.add(expression);
1097: nextSibling = nextSibling.getNextSibling();
1098: } while (isType(LITERAL_case, nextSibling));
1099: if (!isType(LITERAL_default, nextSibling)
1100: && nextSibling != null) {
1101: statement = statement(nextSibling);
1102: }
1103: CaseStatement answer;
1104: if (expressions.size() == 1) {
1105: // single case uses original code for effiiency
1106: answer = new CaseStatement((Expression) expressions.get(0),
1107: statement);
1108: } else {
1109: // multiple cases in casegroup are grouped as an expression
1110: // doesn't seem to mix well with certain case expressions, e.g. regex
1111: ListExpression listExpression = new ListExpression(
1112: expressions);
1113: answer = new CaseStatement(listExpression, statement);
1114: }
1115: configureAST(answer, node);
1116: return answer;
1117: }
1118:
1119: protected Statement synchronizedStatement(AST syncNode) {
1120: AST node = syncNode.getFirstChild();
1121: Expression expression = expression(node);
1122: Statement code = statement(node.getNextSibling());
1123: SynchronizedStatement synchronizedStatement = new SynchronizedStatement(
1124: expression, code);
1125: configureAST(synchronizedStatement, syncNode);
1126: return synchronizedStatement;
1127: }
1128:
1129: protected Statement throwStatement(AST node) {
1130: AST expressionNode = node.getFirstChild();
1131: if (expressionNode == null) {
1132: expressionNode = node.getNextSibling();
1133: }
1134: if (expressionNode == null) {
1135: throw new ASTRuntimeException(node,
1136: "No expression available");
1137: }
1138: ThrowStatement throwStatement = new ThrowStatement(
1139: expression(expressionNode));
1140: configureAST(throwStatement, node);
1141: return throwStatement;
1142: }
1143:
1144: protected Statement tryStatement(AST tryStatementNode) {
1145: AST tryNode = tryStatementNode.getFirstChild();
1146: Statement tryStatement = statement(tryNode);
1147: Statement finallyStatement = EmptyStatement.INSTANCE;
1148: AST node = tryNode.getNextSibling();
1149:
1150: // lets do the catch nodes
1151: List catches = new ArrayList();
1152: for (; node != null && isType(LITERAL_catch, node); node = node
1153: .getNextSibling()) {
1154: catches.add(catchStatement(node));
1155: }
1156:
1157: if (isType(LITERAL_finally, node)) {
1158: finallyStatement = statement(node);
1159: node = node.getNextSibling();
1160: }
1161:
1162: TryCatchStatement tryCatchStatement = new TryCatchStatement(
1163: tryStatement, finallyStatement);
1164: configureAST(tryCatchStatement, tryStatementNode);
1165: for (Iterator iter = catches.iterator(); iter.hasNext();) {
1166: CatchStatement statement = (CatchStatement) iter.next();
1167: tryCatchStatement.addCatch(statement);
1168: }
1169: return tryCatchStatement;
1170: }
1171:
1172: protected CatchStatement catchStatement(AST catchNode) {
1173: AST node = catchNode.getFirstChild();
1174: Parameter parameter = parameter(node);
1175: ClassNode exceptionType = parameter.getType();
1176: String variable = parameter.getName();
1177: node = node.getNextSibling();
1178: Statement code = statement(node);
1179: Parameter catchParameter = new Parameter(exceptionType,
1180: variable);
1181: CatchStatement answer = new CatchStatement(catchParameter, code);
1182: configureAST(answer, catchNode);
1183: return answer;
1184: }
1185:
1186: protected Statement whileStatement(AST whileNode) {
1187: AST node = whileNode.getFirstChild();
1188: assertNodeType(EXPR, node);
1189: BooleanExpression booleanExpression = booleanExpression(node);
1190:
1191: node = node.getNextSibling();
1192: Statement block = statement(node);
1193: WhileStatement whileStatement = new WhileStatement(
1194: booleanExpression, block);
1195: configureAST(whileStatement, whileNode);
1196: return whileStatement;
1197: }
1198:
1199: protected Statement withStatement(AST node) {
1200: notImplementedYet(node);
1201: return null;
1202: /** TODO */
1203: }
1204:
1205: // Expressions
1206: //-------------------------------------------------------------------------
1207:
1208: protected Expression expression(AST node) {
1209: return expression(node, false);
1210: }
1211:
1212: protected Expression expression(AST node, boolean convertToConstant) {
1213: Expression expression = expressionSwitch(node);
1214: if (convertToConstant) {
1215: // a method name can never be a VariableExprssion, so it must converted
1216: // to a ConstantExpression then. This is needed as the expression
1217: // method doesn't know we want a ConstantExpression instead of a
1218: // VariableExpression
1219: if (expression != VariableExpression.THIS_EXPRESSION
1220: && expression != VariableExpression.SUPER_EXPRESSION
1221: && expression instanceof VariableExpression) {
1222: VariableExpression ve = (VariableExpression) expression;
1223: expression = new ConstantExpression(ve.getName());
1224: }
1225: }
1226: configureAST(expression, node);
1227: return expression;
1228: }
1229:
1230: protected Expression expressionSwitch(AST node) {
1231: int type = node.getType();
1232: switch (type) {
1233: case EXPR:
1234: return expression(node.getFirstChild());
1235:
1236: case ELIST:
1237: return expressionList(node);
1238:
1239: case SLIST:
1240: return blockExpression(node);
1241:
1242: case CLOSABLE_BLOCK:
1243: return closureExpression(node);
1244:
1245: case SUPER_CTOR_CALL:
1246: return specialConstructorCallExpression(node,
1247: ClassNode.SUPER);
1248:
1249: case METHOD_CALL:
1250: return methodCallExpression(node);
1251:
1252: case LITERAL_new:
1253: return constructorCallExpression(node.getFirstChild());
1254:
1255: case CTOR_CALL:
1256: return specialConstructorCallExpression(node,
1257: ClassNode.THIS);
1258:
1259: case QUESTION:
1260: return ternaryExpression(node);
1261:
1262: case OPTIONAL_DOT:
1263: case SPREAD_DOT:
1264: case DOT:
1265: return dotExpression(node);
1266:
1267: case IDENT:
1268: case LITERAL_boolean:
1269: case LITERAL_byte:
1270: case LITERAL_char:
1271: case LITERAL_double:
1272: case LITERAL_float:
1273: case LITERAL_int:
1274: case LITERAL_long:
1275: case LITERAL_short:
1276: case LITERAL_void:
1277: return variableExpression(node);
1278:
1279: case LIST_CONSTRUCTOR:
1280: return listExpression(node);
1281:
1282: case MAP_CONSTRUCTOR:
1283: return mapExpression(node);
1284:
1285: case LABELED_ARG:
1286: return mapEntryExpression(node);
1287:
1288: case SPREAD_ARG:
1289: return spreadExpression(node);
1290:
1291: case SPREAD_MAP_ARG:
1292: return spreadMapExpression(node);
1293:
1294: // commented out of groovy.g due to non determinisms
1295: //case MEMBER_POINTER_DEFAULT:
1296: // return defaultMethodPointerExpression(node);
1297:
1298: case MEMBER_POINTER:
1299: return methodPointerExpression(node);
1300:
1301: case INDEX_OP:
1302: return indexExpression(node);
1303:
1304: case LITERAL_instanceof :
1305: return instanceof Expression(node);
1306:
1307: case LITERAL_as:
1308: return asExpression(node);
1309:
1310: case TYPECAST:
1311: return castExpression(node);
1312:
1313: // literals
1314:
1315: case LITERAL_true:
1316: return ConstantExpression.TRUE;
1317:
1318: case LITERAL_false:
1319: return ConstantExpression.FALSE;
1320:
1321: case LITERAL_null:
1322: return ConstantExpression.NULL;
1323:
1324: case STRING_LITERAL:
1325: ConstantExpression constantExpression = new ConstantExpression(
1326: node.getText());
1327: configureAST(constantExpression, node);
1328: return constantExpression;
1329:
1330: case STRING_CONSTRUCTOR:
1331: return gstring(node);
1332:
1333: case NUM_DOUBLE:
1334: case NUM_FLOAT:
1335: case NUM_BIG_DECIMAL:
1336: return decimalExpression(node);
1337:
1338: case NUM_BIG_INT:
1339: case NUM_INT:
1340: case NUM_LONG:
1341: return integerExpression(node);
1342:
1343: case LITERAL_this :
1344: return VariableExpression.THIS_EXPRESSION;
1345:
1346: case LITERAL_super :
1347: return VariableExpression.SUPER_EXPRESSION;
1348:
1349: // Unary expressions
1350: case LNOT:
1351: NotExpression notExpression = new NotExpression(
1352: expression(node.getFirstChild()));
1353: configureAST(notExpression, node);
1354: return notExpression;
1355:
1356: case UNARY_MINUS:
1357: return negateExpression(node);
1358:
1359: case BNOT:
1360: BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(
1361: expression(node.getFirstChild()));
1362: configureAST(bitwiseNegExpression, node);
1363: return bitwiseNegExpression;
1364:
1365: case UNARY_PLUS:
1366: return expression(node.getFirstChild());
1367:
1368: // Prefix expressions
1369: case INC:
1370: return prefixExpression(node, Types.PLUS_PLUS);
1371:
1372: case DEC:
1373: return prefixExpression(node, Types.MINUS_MINUS);
1374:
1375: // Postfix expressions
1376: case POST_INC:
1377: return postfixExpression(node, Types.PLUS_PLUS);
1378:
1379: case POST_DEC:
1380: return postfixExpression(node, Types.MINUS_MINUS);
1381:
1382: // Binary expressions
1383:
1384: case ASSIGN:
1385: return binaryExpression(Types.ASSIGN, node);
1386:
1387: case EQUAL:
1388: return binaryExpression(Types.COMPARE_EQUAL, node);
1389:
1390: case NOT_EQUAL:
1391: return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1392:
1393: case COMPARE_TO:
1394: return binaryExpression(Types.COMPARE_TO, node);
1395:
1396: case LE:
1397: return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1398:
1399: case LT:
1400: return binaryExpression(Types.COMPARE_LESS_THAN, node);
1401:
1402: case GT:
1403: return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1404:
1405: case GE:
1406: return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL,
1407: node);
1408:
1409: /**
1410: * TODO treble equal?
1411: return binaryExpression(Types.COMPARE_IDENTICAL, node);
1412:
1413: case ???:
1414: return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
1415:
1416: case ???:
1417: return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
1418:
1419: */
1420:
1421: case LAND:
1422: return binaryExpression(Types.LOGICAL_AND, node);
1423:
1424: case LOR:
1425: return binaryExpression(Types.LOGICAL_OR, node);
1426:
1427: case BAND:
1428: return binaryExpression(Types.BITWISE_AND, node);
1429:
1430: case BAND_ASSIGN:
1431: return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1432:
1433: case BOR:
1434: return binaryExpression(Types.BITWISE_OR, node);
1435:
1436: case BOR_ASSIGN:
1437: return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1438:
1439: case BXOR:
1440: return binaryExpression(Types.BITWISE_XOR, node);
1441:
1442: case BXOR_ASSIGN:
1443: return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1444:
1445: case PLUS:
1446: return binaryExpression(Types.PLUS, node);
1447:
1448: case PLUS_ASSIGN:
1449: return binaryExpression(Types.PLUS_EQUAL, node);
1450:
1451: case MINUS:
1452: return binaryExpression(Types.MINUS, node);
1453:
1454: case MINUS_ASSIGN:
1455: return binaryExpression(Types.MINUS_EQUAL, node);
1456:
1457: case STAR:
1458: return binaryExpression(Types.MULTIPLY, node);
1459:
1460: case STAR_ASSIGN:
1461: return binaryExpression(Types.MULTIPLY_EQUAL, node);
1462:
1463: case STAR_STAR:
1464: return binaryExpression(Types.POWER, node);
1465:
1466: case STAR_STAR_ASSIGN:
1467: return binaryExpression(Types.POWER_EQUAL, node);
1468:
1469: case DIV:
1470: return binaryExpression(Types.DIVIDE, node);
1471:
1472: case DIV_ASSIGN:
1473: return binaryExpression(Types.DIVIDE_EQUAL, node);
1474:
1475: case MOD:
1476: return binaryExpression(Types.MOD, node);
1477:
1478: case MOD_ASSIGN:
1479: return binaryExpression(Types.MOD_EQUAL, node);
1480:
1481: case SL:
1482: return binaryExpression(Types.LEFT_SHIFT, node);
1483:
1484: case SL_ASSIGN:
1485: return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1486:
1487: case SR:
1488: return binaryExpression(Types.RIGHT_SHIFT, node);
1489:
1490: case SR_ASSIGN:
1491: return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1492:
1493: case BSR:
1494: return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1495:
1496: case BSR_ASSIGN:
1497: return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL,
1498: node);
1499:
1500: // Regex
1501: case REGEX_FIND:
1502: return binaryExpression(Types.FIND_REGEX, node);
1503:
1504: case REGEX_MATCH:
1505: return binaryExpression(Types.MATCH_REGEX, node);
1506:
1507: // Ranges
1508: case RANGE_INCLUSIVE:
1509: return rangeExpression(node, true);
1510:
1511: case RANGE_EXCLUSIVE:
1512: return rangeExpression(node, false);
1513:
1514: case DYNAMIC_MEMBER:
1515: return dynamicMemberExpression(node);
1516:
1517: case LITERAL_in:
1518: return binaryExpression(Types.KEYWORD_IN, node);
1519:
1520: default:
1521: unknownAST(node);
1522: }
1523: return null;
1524: }
1525:
1526: protected Expression dynamicMemberExpression(AST dynamicMemberNode) {
1527: AST node = dynamicMemberNode.getFirstChild();
1528: return expression(node);
1529: }
1530:
1531: protected Expression ternaryExpression(AST ternaryNode) {
1532: AST node = ternaryNode.getFirstChild();
1533: BooleanExpression booleanExpression = booleanExpression(node);
1534: node = node.getNextSibling();
1535: Expression left = expression(node);
1536: Expression right = expression(node.getNextSibling());
1537: TernaryExpression ternaryExpression = new TernaryExpression(
1538: booleanExpression, left, right);
1539: configureAST(ternaryExpression, ternaryNode);
1540: return ternaryExpression;
1541: }
1542:
1543: protected Expression variableExpression(AST node) {
1544: String text = node.getText();
1545:
1546: // TODO we might wanna only try to resolve the name if we are
1547: // on the left hand side of an expression or before a dot?
1548: VariableExpression variableExpression = new VariableExpression(
1549: text);
1550: configureAST(variableExpression, node);
1551: return variableExpression;
1552: }
1553:
1554: protected Expression rangeExpression(AST rangeNode,
1555: boolean inclusive) {
1556: AST node = rangeNode.getFirstChild();
1557: Expression left = expression(node);
1558: Expression right = expression(node.getNextSibling());
1559: RangeExpression rangeExpression = new RangeExpression(left,
1560: right, inclusive);
1561: configureAST(rangeExpression, rangeNode);
1562: return rangeExpression;
1563: }
1564:
1565: protected Expression spreadExpression(AST node) {
1566: AST exprNode = node.getFirstChild();
1567: AST listNode = exprNode.getFirstChild();
1568: Expression right = expression(listNode);
1569: SpreadExpression spreadExpression = new SpreadExpression(right);
1570: configureAST(spreadExpression, node);
1571: return spreadExpression;
1572: }
1573:
1574: protected Expression spreadMapExpression(AST node) {
1575: AST exprNode = node.getFirstChild();
1576: Expression expr = expression(exprNode);
1577: SpreadMapExpression spreadMapExpression = new SpreadMapExpression(
1578: expr);
1579: configureAST(spreadMapExpression, node);
1580: return spreadMapExpression;
1581: }
1582:
1583: protected Expression methodPointerExpression(AST node) {
1584: AST exprNode = node.getFirstChild();
1585: String methodName = identifier(exprNode.getNextSibling());
1586: Expression expression = expression(exprNode);
1587: MethodPointerExpression methodPointerExpression = new MethodPointerExpression(
1588: expression, methodName);
1589: configureAST(methodPointerExpression, node);
1590: return methodPointerExpression;
1591: }
1592:
1593: /* commented out due to groovy.g non-determinisms
1594: protected Expression defaultMethodPointerExpression(AST node) {
1595: AST exprNode = node.getFirstChild();
1596: String methodName = exprNode.toString();
1597: MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
1598: configureAST(methodPointerExpression, node);
1599: return methodPointerExpression;
1600: }
1601: */
1602:
1603: protected Expression listExpression(AST listNode) {
1604: List expressions = new ArrayList();
1605: AST elist = listNode.getFirstChild();
1606: assertNodeType(ELIST, elist);
1607:
1608: for (AST node = elist.getFirstChild(); node != null; node = node
1609: .getNextSibling()) {
1610: // check for stray labeled arguments:
1611: switch (node.getType()) {
1612: case LABELED_ARG:
1613: assertNodeType(COMMA, node);
1614: break; // helpful error?
1615: case SPREAD_MAP_ARG:
1616: assertNodeType(SPREAD_ARG, node);
1617: break; // helpful error
1618: }
1619: expressions.add(expression(node));
1620: }
1621: ListExpression listExpression = new ListExpression(expressions);
1622: configureAST(listExpression, listNode);
1623: return listExpression;
1624: }
1625:
1626: /**
1627: * Typically only used for map constructors I think?
1628: */
1629: protected Expression mapExpression(AST mapNode) {
1630: List expressions = new ArrayList();
1631: AST elist = mapNode.getFirstChild();
1632: if (elist != null) { // totally empty in the case of [:]
1633: assertNodeType(ELIST, elist);
1634: for (AST node = elist.getFirstChild(); node != null; node = node
1635: .getNextSibling()) {
1636: switch (node.getType()) {
1637: case LABELED_ARG:
1638: case SPREAD_MAP_ARG:
1639: break; // legal cases
1640: case SPREAD_ARG:
1641: assertNodeType(SPREAD_MAP_ARG, node);
1642: break; // helpful error
1643: default:
1644: assertNodeType(LABELED_ARG, node);
1645: break; // helpful error
1646: }
1647: expressions.add(mapEntryExpression(node));
1648: }
1649: }
1650: MapExpression mapExpression = new MapExpression(expressions);
1651: configureAST(mapExpression, mapNode);
1652: return mapExpression;
1653: }
1654:
1655: protected MapEntryExpression mapEntryExpression(AST node) {
1656: if (node.getType() == SPREAD_MAP_ARG) {
1657: AST rightNode = node.getFirstChild();
1658: Expression keyExpression = spreadMapExpression(node);
1659: Expression rightExpression = expression(rightNode);
1660: MapEntryExpression mapEntryExpression = new MapEntryExpression(
1661: keyExpression, rightExpression);
1662: configureAST(mapEntryExpression, node);
1663: return mapEntryExpression;
1664: } else {
1665: AST keyNode = node.getFirstChild();
1666: Expression keyExpression = expression(keyNode);
1667: AST valueNode = keyNode.getNextSibling();
1668: Expression valueExpression = expression(valueNode);
1669: MapEntryExpression mapEntryExpression = new MapEntryExpression(
1670: keyExpression, valueExpression);
1671: configureAST(mapEntryExpression, node);
1672: return mapEntryExpression;
1673: }
1674: }
1675:
1676: protected Expression instanceof Expression(AST node) {
1677: AST leftNode = node.getFirstChild();
1678: Expression leftExpression = expression(leftNode);
1679:
1680: AST rightNode = leftNode.getNextSibling();
1681: ClassNode type = buildName(rightNode);
1682: assertTypeNotNull(type, rightNode);
1683:
1684: Expression rightExpression = new ClassExpression(type);
1685: configureAST(rightExpression, rightNode);
1686: BinaryExpression binaryExpression = new BinaryExpression(
1687: leftExpression, makeToken(Types.KEYWORD_INSTANCEOF,
1688: node), rightExpression);
1689: configureAST(binaryExpression, node);
1690: return binaryExpression;
1691: }
1692:
1693: protected void assertTypeNotNull(ClassNode type, AST rightNode) {
1694: if (type == null) {
1695: throw new ASTRuntimeException(rightNode,
1696: "No type available for: "
1697: + qualifiedName(rightNode));
1698: }
1699: }
1700:
1701: protected Expression asExpression(AST node) {
1702: AST leftNode = node.getFirstChild();
1703: Expression leftExpression = expression(leftNode);
1704:
1705: AST rightNode = leftNode.getNextSibling();
1706: ClassNode type = buildName(rightNode);
1707:
1708: return CastExpression.asExpression(type, leftExpression);
1709: }
1710:
1711: protected Expression castExpression(AST castNode) {
1712: AST node = castNode.getFirstChild();
1713: ClassNode type = buildName(node);
1714: assertTypeNotNull(type, node);
1715:
1716: AST expressionNode = node.getNextSibling();
1717: Expression expression = expression(expressionNode);
1718:
1719: CastExpression castExpression = new CastExpression(type,
1720: expression);
1721: configureAST(castExpression, castNode);
1722: return castExpression;
1723: }
1724:
1725: protected Expression indexExpression(AST indexNode) {
1726: AST leftNode = indexNode.getFirstChild();
1727: Expression leftExpression = expression(leftNode);
1728:
1729: AST rightNode = leftNode.getNextSibling();
1730: Expression rightExpression = expression(rightNode);
1731:
1732: BinaryExpression binaryExpression = new BinaryExpression(
1733: leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET,
1734: indexNode), rightExpression);
1735: configureAST(binaryExpression, indexNode);
1736: return binaryExpression;
1737: }
1738:
1739: protected Expression binaryExpression(int type, AST node) {
1740: Token token = makeToken(type, node);
1741:
1742: AST leftNode = node.getFirstChild();
1743: Expression leftExpression = expression(leftNode);
1744:
1745: AST rightNode = leftNode.getNextSibling();
1746: if (rightNode == null) {
1747: return leftExpression;
1748: }
1749:
1750: if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
1751: if (leftExpression instanceof VariableExpression
1752: || leftExpression.getClass() == PropertyExpression.class
1753: || leftExpression instanceof FieldExpression
1754: || leftExpression instanceof AttributeExpression
1755: || leftExpression instanceof DeclarationExpression) {
1756: // Do nothing.
1757: } else if (leftExpression instanceof ConstantExpression) {
1758: throw new ASTRuntimeException(
1759: node,
1760: "\n["
1761: + ((ConstantExpression) leftExpression)
1762: .getValue()
1763: + "] is a constant expression, but it should be a variable expression");
1764: } else if (leftExpression instanceof BinaryExpression) {
1765: Expression leftexp = ((BinaryExpression) leftExpression)
1766: .getLeftExpression();
1767: int lefttype = ((BinaryExpression) leftExpression)
1768: .getOperation().getType();
1769: if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR)
1770: && lefttype != Types.LEFT_SQUARE_BRACKET) {
1771: throw new ASTRuntimeException(
1772: node,
1773: "\n"
1774: + ((BinaryExpression) leftExpression)
1775: .getText()
1776: + " is a binary expression, but it should be a variable expression");
1777: }
1778: } else if (leftExpression instanceof GStringExpression) {
1779: throw new ASTRuntimeException(
1780: node,
1781: "\n\""
1782: + ((GStringExpression) leftExpression)
1783: .getText()
1784: + "\" is a GString expression, but it should be a variable expression");
1785: } else if (leftExpression instanceof MethodCallExpression) {
1786: throw new ASTRuntimeException(
1787: node,
1788: "\n\""
1789: + ((MethodCallExpression) leftExpression)
1790: .getText()
1791: + "\" is a method call expression, but it should be a variable expression");
1792: } else if (leftExpression instanceof MapExpression) {
1793: throw new ASTRuntimeException(
1794: node,
1795: "\n'"
1796: + ((MapExpression) leftExpression)
1797: .getText()
1798: + "' is a map expression, but it should be a variable expression");
1799: } else {
1800: throw new ASTRuntimeException(
1801: node,
1802: "\n"
1803: + leftExpression.getClass()
1804: + ", with its value '"
1805: + leftExpression.getText()
1806: + "', is a bad expression as the LSH of an assignment operator");
1807: }
1808: }
1809: /*if (rightNode == null) {
1810: throw new NullPointerException("No rightNode associated with binary expression");
1811: }*/
1812: Expression rightExpression = expression(rightNode);
1813: BinaryExpression binaryExpression = new BinaryExpression(
1814: leftExpression, token, rightExpression);
1815: configureAST(binaryExpression, node);
1816: return binaryExpression;
1817: }
1818:
1819: protected Expression prefixExpression(AST node, int token) {
1820: Expression expression = expression(node.getFirstChild());
1821: PrefixExpression prefixExpression = new PrefixExpression(
1822: makeToken(token, node), expression);
1823: configureAST(prefixExpression, node);
1824: return prefixExpression;
1825: }
1826:
1827: protected Expression postfixExpression(AST node, int token) {
1828: Expression expression = expression(node.getFirstChild());
1829: PostfixExpression postfixExpression = new PostfixExpression(
1830: expression, makeToken(token, node));
1831: configureAST(postfixExpression, node);
1832: return postfixExpression;
1833: }
1834:
1835: protected BooleanExpression booleanExpression(AST node) {
1836: BooleanExpression booleanExpression = new BooleanExpression(
1837: expression(node));
1838: configureAST(booleanExpression, node);
1839: return booleanExpression;
1840: }
1841:
1842: protected Expression dotExpression(AST node) {
1843: // lets decide if this is a propery invocation or a method call
1844: AST leftNode = node.getFirstChild();
1845: if (leftNode != null) {
1846: AST identifierNode = leftNode.getNextSibling();
1847: if (identifierNode != null) {
1848: Expression leftExpression = expression(leftNode);
1849: if (isType(SELECT_SLOT, identifierNode)) {
1850: Expression field = expression(identifierNode
1851: .getFirstChild(), true);
1852: AttributeExpression attributeExpression = new AttributeExpression(
1853: leftExpression, field,
1854: node.getType() != DOT);
1855: if (node.getType() == SPREAD_DOT) {
1856: attributeExpression.setSpreadSafe(true);
1857: }
1858: configureAST(attributeExpression, node);
1859: return attributeExpression;
1860: }
1861: Expression property = expression(identifierNode, true);
1862:
1863: PropertyExpression propertyExpression = new PropertyExpression(
1864: leftExpression, property, node.getType() != DOT);
1865: if (node.getType() == SPREAD_DOT) {
1866: propertyExpression.setSpreadSafe(true);
1867: }
1868: configureAST(propertyExpression, node);
1869: return propertyExpression;
1870: }
1871: }
1872: return methodCallExpression(node);
1873: }
1874:
1875: protected Expression specialConstructorCallExpression(
1876: AST methodCallNode, ClassNode special) {
1877: AST node = methodCallNode.getFirstChild();
1878: Expression arguments = arguments(node);
1879:
1880: ConstructorCallExpression expression = new ConstructorCallExpression(
1881: special, arguments);
1882: configureAST(expression, methodCallNode);
1883: return expression;
1884: }
1885:
1886: private int getTypeInParenthesis(AST node) {
1887: if (!isType(EXPR, node))
1888: node = node.getFirstChild();
1889: while (node != null && isType(EXPR, node)
1890: && node.getNextSibling() == null) {
1891: node = node.getFirstChild();
1892: }
1893: if (node == null)
1894: return -1;
1895: return node.getType();
1896: }
1897:
1898: protected Expression methodCallExpression(AST methodCallNode) {
1899: AST node = methodCallNode.getFirstChild();
1900: /* // Bad idea, since foo(1)(2) is valid Groovy for foo(1).call(2).
1901: if (isType(METHOD_CALL, node)) {
1902: // sometimes method calls get wrapped in method calls for some wierd reason
1903: return methodCallExpression(node);
1904: }
1905: */
1906:
1907: Expression objectExpression;
1908: AST selector;
1909: AST elist = node.getNextSibling();
1910:
1911: boolean implicitThis = false;
1912: boolean safe = isType(OPTIONAL_DOT, node);
1913: boolean spreadSafe = isType(SPREAD_DOT, node);
1914: if (isType(DOT, node) || safe || spreadSafe) {
1915: AST objectNode = node.getFirstChild();
1916: objectExpression = expression(objectNode);
1917: selector = objectNode.getNextSibling();
1918: } else {
1919: implicitThis = true;
1920: objectExpression = VariableExpression.THIS_EXPRESSION;
1921: selector = node;
1922: }
1923:
1924: Expression name = null;
1925: if (isType(LITERAL_super , selector)) {
1926: implicitThis = true;
1927: name = new ConstantExpression("super");
1928: if (objectExpression == VariableExpression.THIS_EXPRESSION) {
1929: objectExpression = VariableExpression.SUPER_EXPRESSION;
1930: }
1931: } else if (isPrimitiveTypeLiteral(selector)) {
1932: throw new ASTRuntimeException(selector,
1933: "Primitive type literal: " + selector.getText()
1934: + " cannot be used as a method name");
1935: } else if (isType(SELECT_SLOT, selector)) {
1936: Expression field = expression(selector.getFirstChild(),
1937: true);
1938: AttributeExpression attributeExpression = new AttributeExpression(
1939: objectExpression, field, node.getType() != DOT);
1940: configureAST(attributeExpression, node);
1941: Expression arguments = arguments(elist);
1942: MethodCallExpression expression = new MethodCallExpression(
1943: attributeExpression, "call", arguments);
1944: configureAST(expression, methodCallNode);
1945: return expression;
1946: } else if (isType(DYNAMIC_MEMBER, selector)
1947: || isType(IDENT, selector)
1948: || isType(STRING_CONSTRUCTOR, selector)
1949: || isType(STRING_LITERAL, selector)) {
1950: name = expression(selector, true);
1951: } else {
1952: implicitThis = false;
1953: name = new ConstantExpression("call");
1954: objectExpression = expression(selector, true);
1955: }
1956:
1957: Expression arguments = arguments(elist);
1958: MethodCallExpression expression = new MethodCallExpression(
1959: objectExpression, name, arguments);
1960: expression.setSafe(safe);
1961: expression.setSpreadSafe(spreadSafe);
1962: expression.setImplicitThis(implicitThis);
1963: Expression ret = expression;
1964: //FIXME: do we really want this() to create a new object regardless
1965: // the position.. for example not as first statement in a constructor
1966: // this=first statement in contructor is handled by specialConstructorCallExpression
1967: // we may have to add a check and remove this part of the code
1968: if (implicitThis
1969: && "this".equals(expression.getMethodAsString())) {
1970: ret = new ConstructorCallExpression(this .classNode,
1971: arguments);
1972: }
1973: configureAST(ret, methodCallNode);
1974: return ret;
1975: }
1976:
1977: protected Expression constructorCallExpression(AST node) {
1978: AST constructorCallNode = node;
1979: ClassNode type = buildName(constructorCallNode);
1980:
1981: if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
1982: node = node.getFirstChild();
1983: }
1984:
1985: AST elist = node.getNextSibling();
1986:
1987: if (elist == null && isType(ELIST, node)) {
1988: elist = node;
1989: if ("(".equals(type.getName())) {
1990: type = classNode;
1991: }
1992: }
1993:
1994: if (isType(ARRAY_DECLARATOR, elist)) {
1995: AST expressionNode = elist.getFirstChild();
1996: if (expressionNode == null) {
1997: throw new ASTRuntimeException(elist,
1998: "No expression for the array constructor call");
1999: }
2000: List size = arraySizeExpression(expressionNode);
2001: ArrayExpression arrayExpression = new ArrayExpression(type,
2002: null, size);
2003: configureAST(arrayExpression, constructorCallNode);
2004: return arrayExpression;
2005: }
2006: Expression arguments = arguments(elist);
2007: ConstructorCallExpression expression = new ConstructorCallExpression(
2008: type, arguments);
2009: configureAST(expression, constructorCallNode);
2010: return expression;
2011: }
2012:
2013: protected List arraySizeExpression(AST node) {
2014: List list;
2015: Expression size = null;
2016: if (isType(ARRAY_DECLARATOR, node)) {
2017: AST right = node.getNextSibling();
2018: if (right != null) {
2019: size = expression(right);
2020: } else {
2021: size = ConstantExpression.EMTPY_EXPRESSION;
2022: }
2023: list = arraySizeExpression(node.getFirstChild());
2024: } else {
2025: size = expression(node);
2026: list = new ArrayList();
2027: }
2028: list.add(size);
2029: return list;
2030: }
2031:
2032: protected Expression arguments(AST elist) {
2033: List expressionList = new ArrayList();
2034: // FIXME: all labeled arguments should follow any unlabeled arguments
2035: boolean namedArguments = false;
2036: for (AST node = elist; node != null; node = node
2037: .getNextSibling()) {
2038: if (isType(ELIST, node)) {
2039: for (AST child = node.getFirstChild(); child != null; child = child
2040: .getNextSibling()) {
2041: namedArguments |= addArgumentExpression(child,
2042: expressionList);
2043: }
2044: } else {
2045: namedArguments |= addArgumentExpression(node,
2046: expressionList);
2047: }
2048: }
2049: if (namedArguments) {
2050: if (!expressionList.isEmpty()) {
2051: // lets remove any non-MapEntryExpression instances
2052: // such as if the last expression is a ClosureExpression
2053: // so lets wrap the named method calls in a Map expression
2054: List argumentList = new ArrayList();
2055: for (Iterator iter = expressionList.iterator(); iter
2056: .hasNext();) {
2057: Expression expression = (Expression) iter.next();
2058: if (!(expression instanceof MapEntryExpression)) {
2059: argumentList.add(expression);
2060: }
2061: }
2062: if (!argumentList.isEmpty()) {
2063: expressionList.removeAll(argumentList);
2064: MapExpression mapExpression = new MapExpression(
2065: expressionList);
2066: configureAST(mapExpression, elist);
2067: argumentList.add(0, mapExpression);
2068: ArgumentListExpression argumentListExpression = new ArgumentListExpression(
2069: argumentList);
2070: configureAST(argumentListExpression, elist);
2071: return argumentListExpression;
2072: }
2073: }
2074: NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(
2075: expressionList);
2076: configureAST(namedArgumentListExpression, elist);
2077: return namedArgumentListExpression;
2078: } else {
2079: ArgumentListExpression argumentListExpression = new ArgumentListExpression(
2080: expressionList);
2081: configureAST(argumentListExpression, elist);
2082: return argumentListExpression;
2083: }
2084: }
2085:
2086: protected boolean addArgumentExpression(AST node,
2087: List expressionList) {
2088: if (node.getType() == SPREAD_MAP_ARG) {
2089: AST rightNode = node.getFirstChild();
2090: Expression keyExpression = spreadMapExpression(node);
2091: Expression rightExpression = expression(rightNode);
2092: MapEntryExpression mapEntryExpression = new MapEntryExpression(
2093: keyExpression, rightExpression);
2094: expressionList.add(mapEntryExpression);
2095: return true;
2096: } else {
2097: Expression expression = expression(node);
2098: expressionList.add(expression);
2099: return expression instanceof MapEntryExpression;
2100: }
2101: }
2102:
2103: protected Expression expressionList(AST node) {
2104: List expressionList = new ArrayList();
2105: for (AST child = node.getFirstChild(); child != null; child = child
2106: .getNextSibling()) {
2107: expressionList.add(expression(child));
2108: }
2109: if (expressionList.size() == 1) {
2110: return (Expression) expressionList.get(0);
2111: } else {
2112: ListExpression listExpression = new ListExpression(
2113: expressionList);
2114: configureAST(listExpression, node);
2115: return listExpression;
2116: }
2117: }
2118:
2119: protected ClosureExpression closureExpression(AST node) {
2120: AST paramNode = node.getFirstChild();
2121: Parameter[] parameters = null;
2122: AST codeNode = paramNode;
2123: if (isType(PARAMETERS, paramNode)
2124: || isType(IMPLICIT_PARAMETERS, paramNode)) {
2125: parameters = parameters(paramNode);
2126: codeNode = paramNode.getNextSibling();
2127: }
2128: Statement code = statementListNoChild(codeNode);
2129: ClosureExpression closureExpression = new ClosureExpression(
2130: parameters, code);
2131: configureAST(closureExpression, node);
2132: return closureExpression;
2133: }
2134:
2135: protected Expression blockExpression(AST node) {
2136: AST codeNode = node.getFirstChild();
2137: if (codeNode == null)
2138: return ConstantExpression.NULL;
2139: if (codeNode.getType() == EXPR
2140: && codeNode.getNextSibling() == null) {
2141: // Simplify common case of {expr} to expr.
2142: return expression(codeNode);
2143: }
2144: Parameter[] parameters = Parameter.EMPTY_ARRAY;
2145: Statement code = statementListNoChild(codeNode);
2146: ClosureExpression closureExpression = new ClosureExpression(
2147: parameters, code);
2148: configureAST(closureExpression, node);
2149: // Call it immediately.
2150: String callName = "call";
2151: Expression noArguments = new ArgumentListExpression();
2152: MethodCallExpression call = new MethodCallExpression(
2153: closureExpression, callName, noArguments);
2154: configureAST(call, node);
2155: return call;
2156: }
2157:
2158: protected Expression negateExpression(AST negateExpr) {
2159: AST node = negateExpr.getFirstChild();
2160:
2161: // if we are a number literal then lets just parse it
2162: // as the negation operator on MIN_INT causes rounding to a long
2163: String text = node.getText();
2164: switch (node.getType()) {
2165: case NUM_DOUBLE:
2166: case NUM_FLOAT:
2167: case NUM_BIG_DECIMAL:
2168: ConstantExpression constantExpression = new ConstantExpression(
2169: Numbers.parseDecimal("-" + text));
2170: configureAST(constantExpression, negateExpr);
2171: return constantExpression;
2172:
2173: case NUM_BIG_INT:
2174: case NUM_INT:
2175: case NUM_LONG:
2176: ConstantExpression constantLongExpression = new ConstantExpression(
2177: Numbers.parseInteger("-" + text));
2178: configureAST(constantLongExpression, negateExpr);
2179: return constantLongExpression;
2180:
2181: default:
2182: NegationExpression negationExpression = new NegationExpression(
2183: expression(node));
2184: configureAST(negationExpression, negateExpr);
2185: return negationExpression;
2186: }
2187: }
2188:
2189: protected ConstantExpression decimalExpression(AST node) {
2190: String text = node.getText();
2191: ConstantExpression constantExpression = new ConstantExpression(
2192: Numbers.parseDecimal(text));
2193: configureAST(constantExpression, node);
2194: return constantExpression;
2195: }
2196:
2197: protected ConstantExpression integerExpression(AST node) {
2198: String text = node.getText();
2199: ConstantExpression constantExpression = new ConstantExpression(
2200: Numbers.parseInteger(text));
2201: configureAST(constantExpression, node);
2202: return constantExpression;
2203: }
2204:
2205: protected Expression gstring(AST gstringNode) {
2206: List strings = new ArrayList();
2207: List values = new ArrayList();
2208:
2209: StringBuffer buffer = new StringBuffer();
2210:
2211: boolean isPrevString = false;
2212:
2213: for (AST node = gstringNode.getFirstChild(); node != null; node = node
2214: .getNextSibling()) {
2215: int type = node.getType();
2216: String text = null;
2217: switch (type) {
2218:
2219: case STRING_LITERAL:
2220: if (isPrevString)
2221: assertNodeType(IDENT, node); // parser bug
2222: isPrevString = true;
2223: text = node.getText();
2224: ConstantExpression constantExpression = new ConstantExpression(
2225: text);
2226: configureAST(constantExpression, node);
2227: strings.add(constantExpression);
2228: buffer.append(text);
2229: break;
2230:
2231: default: {
2232: if (!isPrevString)
2233: assertNodeType(IDENT, node); // parser bug
2234: isPrevString = false;
2235: Expression expression = expression(node);
2236: values.add(expression);
2237: buffer.append("$");
2238: buffer.append(expression.getText());
2239: }
2240: break;
2241: }
2242: }
2243: GStringExpression gStringExpression = new GStringExpression(
2244: buffer.toString(), strings, values);
2245: configureAST(gStringExpression, gstringNode);
2246: return gStringExpression;
2247: }
2248:
2249: protected ClassNode type(AST typeNode) {
2250: // TODO intern types?
2251: // TODO configureAST(...)
2252: return buildName(typeNode.getFirstChild());
2253: }
2254:
2255: public static String qualifiedName(AST qualifiedNameNode) {
2256: if (isType(IDENT, qualifiedNameNode)) {
2257: return qualifiedNameNode.getText();
2258: }
2259: if (isType(DOT, qualifiedNameNode)) {
2260: AST node = qualifiedNameNode.getFirstChild();
2261: StringBuffer buffer = new StringBuffer();
2262: boolean first = true;
2263:
2264: for (; node != null; node = node.getNextSibling()) {
2265: if (first) {
2266: first = false;
2267: } else {
2268: buffer.append(".");
2269: }
2270: buffer.append(qualifiedName(node));
2271: }
2272: return buffer.toString();
2273: } else {
2274: return qualifiedNameNode.getText();
2275: }
2276: }
2277:
2278: protected ClassNode makeType(AST typeNode) {
2279: ClassNode answer = ClassHelper.DYNAMIC_TYPE;
2280: AST node = typeNode.getFirstChild();
2281: if (node != null) {
2282: if (isType(INDEX_OP, node)
2283: || isType(ARRAY_DECLARATOR, node)) {
2284: return makeType(node).makeArray();
2285: }
2286: return ClassHelper.make(qualifiedName(node));
2287: }
2288: return answer;
2289: }
2290:
2291: /**
2292: * Performs a name resolution to see if the given name is a type from imports,
2293: * aliases or newly created classes
2294: */
2295: /*protected String resolveTypeName(String name, boolean safe) {
2296: if (name == null) {
2297: return null;
2298: }
2299: return resolveNewClassOrName(name, safe);
2300: }*/
2301:
2302: /**
2303: * Extracts an identifier from the Antlr AST and then performs a name resolution
2304: * to see if the given name is a type from imports, aliases or newly created classes
2305: */
2306: protected ClassNode buildName(AST node) {
2307: if (isType(TYPE, node)) {
2308: node = node.getFirstChild();
2309: }
2310: ClassNode answer = null;
2311: if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
2312: answer = ClassHelper.make(qualifiedName(node));
2313: } else if (isPrimitiveTypeLiteral(node)) {
2314: answer = ClassHelper.make(node.getText());
2315: } else if (isType(INDEX_OP, node)
2316: || isType(ARRAY_DECLARATOR, node)) {
2317: AST child = node.getFirstChild();
2318: return buildName(child).makeArray();
2319: } else {
2320: String identifier = node.getText();
2321: answer = ClassHelper.make(identifier);
2322: }
2323: AST nextSibling = node.getNextSibling();
2324: if (isType(INDEX_OP, nextSibling)
2325: || isType(ARRAY_DECLARATOR, node)) {
2326: return answer.makeArray();
2327: } else {
2328: return answer;
2329: }
2330: }
2331:
2332: protected boolean isPrimitiveTypeLiteral(AST node) {
2333: int type = node.getType();
2334: switch (type) {
2335: case LITERAL_boolean:
2336: case LITERAL_byte:
2337: case LITERAL_char:
2338: case LITERAL_double:
2339: case LITERAL_float:
2340: case LITERAL_int:
2341: case LITERAL_long:
2342: case LITERAL_short:
2343: return true;
2344:
2345: default:
2346: return false;
2347: }
2348: }
2349:
2350: /**
2351: * Extracts an identifier from the Antlr AST
2352: */
2353: protected String identifier(AST node) {
2354: assertNodeType(IDENT, node);
2355: return node.getText();
2356: }
2357:
2358: protected String label(AST labelNode) {
2359: AST node = labelNode.getFirstChild();
2360: if (node == null) {
2361: return null;
2362: }
2363: return identifier(node);
2364: }
2365:
2366: // Helper methods
2367: //-------------------------------------------------------------------------
2368:
2369: /**
2370: * Returns true if the modifiers flags contain a visibility modifier
2371: */
2372: protected boolean hasVisibility(int modifiers) {
2373: return (modifiers & (Opcodes.ACC_PRIVATE
2374: | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
2375: }
2376:
2377: protected void configureAST(ASTNode node, AST ast) {
2378: if (ast == null)
2379: throw new ASTRuntimeException(ast,
2380: "PARSER BUG: Tried to configure "
2381: + node.getClass().getName()
2382: + " with null Node");
2383: node.setColumnNumber(ast.getColumn());
2384: node.setLineNumber(ast.getLine());
2385: if (ast instanceof GroovySourceAST) {
2386: node.setLastColumnNumber(((GroovySourceAST) ast)
2387: .getColumnLast());
2388: node.setLastLineNumber(((GroovySourceAST) ast)
2389: .getLineLast());
2390: }
2391:
2392: // TODO we could one day store the Antlr AST on the Groovy AST
2393: // node.setCSTNode(ast);
2394: }
2395:
2396: protected static Token makeToken(int typeCode, AST node) {
2397: return Token.newSymbol(typeCode, node.getLine(), node
2398: .getColumn());
2399: }
2400:
2401: protected String getFirstChildText(AST node) {
2402: AST child = node.getFirstChild();
2403: return child != null ? child.getText() : null;
2404: }
2405:
2406: public static boolean isType(int typeCode, AST node) {
2407: return node != null && node.getType() == typeCode;
2408: }
2409:
2410: private String getTokenName(int token) {
2411: if (tokenNames == null)
2412: return "" + token;
2413: return tokenNames[token];
2414: }
2415:
2416: private String getTokenName(AST node) {
2417: if (node == null)
2418: return "null";
2419: return getTokenName(node.getType());
2420: }
2421:
2422: protected void assertNodeType(int type, AST node) {
2423: if (node == null) {
2424: throw new ASTRuntimeException(node,
2425: "No child node available in AST when expecting type: "
2426: + getTokenName(type));
2427: }
2428: if (node.getType() != type) {
2429: throw new ASTRuntimeException(node,
2430: "Unexpected node type: " + getTokenName(node)
2431: + " found when expecting type: "
2432: + getTokenName(type));
2433: }
2434: }
2435:
2436: protected void notImplementedYet(AST node) {
2437: throw new ASTRuntimeException(node,
2438: "AST node not implemented yet for type: "
2439: + getTokenName(node));
2440: }
2441:
2442: protected void unknownAST(AST node) {
2443: if (node.getType() == CLASS_DEF) {
2444: throw new ASTRuntimeException(
2445: node,
2446: "Class definition not expected here. Possible attempt to use inner class. "
2447: + "Inner classes not supported, perhaps try using a closure instead.");
2448: }
2449: throw new ASTRuntimeException(node, "Unknown type: "
2450: + getTokenName(node));
2451: }
2452:
2453: protected void dumpTree(AST ast) {
2454: for (AST node = ast.getFirstChild(); node != null; node = node
2455: .getNextSibling()) {
2456: dump(node);
2457: }
2458: }
2459:
2460: protected void dump(AST node) {
2461: System.out.println("Type: " + getTokenName(node) + " text: "
2462: + node.getText());
2463: }
2464: }
|