/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.codehaus.groovy.antlr.java; import java.util.Stack; import org.codehaus.groovy.antlr.GroovySourceAST; import org.codehaus.groovy.antlr.treewalker.VisitorAdapter; /** This class mutates the Java AST, whilst it is still a Java AST, in readiness for conversion to Groovy, yippee-ky-a ! */ public class PreJava2GroovyConverter extends VisitorAdapter{ private final Stack stack; public PreJava2GroovyConverter(String[] tokenNames) { this.stack = new Stack(); } public void visitDefault(GroovySourceAST t,int visit) { if (visit == OPENING_VISIT) { if (t.getType() == JavaTokenTypes.LITERAL_do) { visitJavaLiteralDo(t); } else if (t.getType() == JavaTokenTypes.ARRAY_INIT) { visitJavaArrayInit(t); } } } private void visitJavaLiteralDo(GroovySourceAST t) { // todo - incomplete, as body of do...while... should be executed at least once, which this doesn't provide. swapTwoChildren(t); } /** * Handle Arrays. Examples: * * <pre> * String[] myArray = new String[] {"a","b","c"}; * * becomes * * String[] myArray = ["a", "b", "c"] * * --- * * To convert node (t) and surrounding nodes into the right structure for List Constructor * * (a) java/EXPR * | * +- (b) java/new * | * + (t) java/ARRAY_INIT * * becomes * * (a) groovy/LIST_CONSTRUCTOR (via ARRAY_INIT as temporary marker type) * | * +- (t) groovy/ELIST * * * note: node (b) is thrown away... * </pre> */ private void visitJavaArrayInit(GroovySourceAST t) { // given that we might have a grandParent... if (stack.size() > 2) { GroovySourceAST grandParent = getGrandParentNode(); if (grandParent.getType() == JavaTokenTypes.EXPR) { grandParent.setType(JavaTokenTypes.ARRAY_INIT); //set type as indicator for Java2GroovyConvertor to turn into LIST_CONSTRUCTOR grandParent.setFirstChild(t); t.setType(JavaTokenTypes.ELIST); } } } /** To swap two children of node t... * *<pre> * (t) * | * | * (a) -- (b) * * t.down = firstNode * a.right = b * b.right = null *</pre> * becomes *<pre> * (t) * | * | * (b) -- (a) * * t.down = b * a.right = null * b.right = a *</pre> * * todo - build API of basic tree mutations like this method. */ public void swapTwoChildren(GroovySourceAST t) { // this swaps the two child nodes, see javadoc above for explanation of implementation GroovySourceAST a = (GroovySourceAST) t.getFirstChild(); GroovySourceAST b = (GroovySourceAST) a.getNextSibling(); t.setFirstChild(b); a.setNextSibling(null); b.setNextSibling(a); } public void push(GroovySourceAST t) { stack.push(t); } public GroovySourceAST pop() { if (!stack.empty()) { return (GroovySourceAST) stack.pop(); } return null; } private GroovySourceAST getGrandParentNode() { Object currentNode = stack.pop(); Object parentNode = stack.pop(); Object grandParentNode = stack.peek(); stack.push(parentNode); stack.push(currentNode); return (GroovySourceAST) grandParentNode; } }