org.codehaus.groovy.antlr.java.PreJava2GroovyConverter Maven / Gradle / Ivy
/*
* 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 org.codehaus.groovy.antlr.GroovySourceAST;
import org.codehaus.groovy.antlr.treewalker.VisitorAdapter;
import java.util.Stack;
/** 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 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:
*
*
* 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...
*
*/
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...
*
*
* (t)
* |
* |
* (a) -- (b)
*
* t.down = firstNode
* a.right = b
* b.right = null
*
* becomes
*
* (t)
* |
* |
* (b) -- (a)
*
* t.down = b
* a.right = null
* b.right = a
*
*
* 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;
}
}