blob: 0f66573b919ad887fee80e15694f6ffe24a986ad [file] [log] [blame]
/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed 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 String[] tokenNames;
private Stack stack;
public PreJava2GroovyConverter(String[] tokenNames) {
this.tokenNames = 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);
}
/**
* <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 getParentNode() {
Object currentNode = stack.pop();
Object parentNode = stack.peek();
stack.push(currentNode);
return (GroovySourceAST) parentNode;
}
private GroovySourceAST getGrandParentNode() {
Object currentNode = stack.pop();
Object parentNode = stack.pop();
Object grandParentNode = stack.peek();
stack.push(parentNode);
stack.push(currentNode);
return (GroovySourceAST) grandParentNode;
}
}