/*
* xtc - The eXTensible Compiler
* Copyright (C) 2011 Robert Grimm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package oop;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.LinkedList;
import java.util.Scanner;
import xtc.parser.ParseException;
import xtc.parser.Result;
import xtc.tree.GNode;
import xtc.tree.Node;
import xtc.tree.Visitor;
import xtc.lang.JavaFiveParser;
/**
* A translator from (a subset of) Java to (a subset of) C++.
*
* @author Robert Grimm
* @version $Revision$
*/
public class TestTranslator extends xtc.util.Tool {
private String outFileName = "";
/** Create a new translator. */
public TestTranslator() {
// Nothing to do.
}
public String getName() {
return "JavaGrinder - A Java to C++ Translator";
}
public String getCopy() {
return "Christopher Lee, Daniel Uebelein, Justin Bernegger, & Steven Socha";
}
public void init() {
super.init();
runtime.
bool("printJavaAST", "printJavaAST", false, "Print Java AST.").
bool("countMethods", "countMethods", false, "Count all Java methods.").
bool("translate", "translate", false, "Translate a Java file to a C++ file.");
}
public Node parse(Reader in, File file) throws IOException, ParseException {
outFileName = file.getName().substring(0, file.getName().indexOf('.')); // This is the only place I could find where I could save the name of the argument file.
JavaFiveParser parser = // But I'm ignorant and there's probably a more elegant way of getting it.
new JavaFiveParser(in, file.toString(), (int)file.length());
Result result = parser.pCompilationUnit(0);
return (Node)parser.value(result);
}
/*
* Existing Issues
* - Not all visitors created so the printing of each line (cc or h) will not be perfect at all, predict outputs using AST before testing
* - Formatting will be a constant issue as we add in more visitors, debug and check outputs often
* - primitive types are not c++ 32bit versions (ex int32_t), have to change that
* - most of the formatting to c++ has not been done yet
*/
public void process(Node node) {
if (runtime.test("printJavaAST")) {
runtime.console().format(node).pln().flush();
}
if (runtime.test("translate")) {
new Visitor() {
private FileWriter writerCC;
private FileWriter writerH;
private File fileCC;
private File fileH;
private BufferedWriter outCC;
private BufferedWriter outH;
private File java_langH;
private LinkedList<String> includesCC;
private LinkedList<String> nameSpaceCC;
private LinkedList<String> methodCC;
private LinkedList<String> vTableDefCC;
private LinkedList<String> includesH;
private LinkedList<String> nameSpaceH;
private LinkedList<String> forwardDeclarationsH;
private LinkedList<String> constructorH;
private LinkedList<String> dataLayoutH;
private LinkedList<String> methodsImplementedH;
private LinkedList<String> vTableH;
private LinkedList<vTableLayoutLine> OvTableLayoutH;
private LinkedList<vTableAddressLine> OvTableAddressH;
private LinkedList<vTableLayoutLine> vTableLayoutH;
private LinkedList<vTableAddressLine> vTableAddressH;
private vTableLayoutLine currentLayoutLineTemplate;
private vTableLayoutLine currentLayoutLine;
private vTableAddressLine currentAddressLineTemplate;
private vTableAddressLine currentAddressLine;
private LinkedList<String> classTracker; //tracks what classes have been visited, not used yet
private LinkedList<String> ccstring;
private LinkedList<String> hstring;
private boolean hflag;
private boolean hreturntype;
private boolean hparameter;
private int cccount;
private String marginSpaceCC;
private String marginSpaceH;
private String className;
//the source directory for the .java files
private String basedirectory = "./";
/** What it says on the tin.*/
private void createFilesAndWriters(){
try{
java_langH = new File(basedirectory + "java_lang.h");
fileCC = new File(basedirectory + outFileName + ".cc");
fileH = new File(basedirectory + outFileName + ".h");
fileCC.createNewFile();
fileH.createNewFile();
includesCC = new LinkedList<String>();
includesCC.add("#include \""+outFileName+".h\";");
includesCC.add("#include \"java_lang.h\"");
nameSpaceCC = new LinkedList<String>();
methodCC = new LinkedList<String>();
vTableDefCC = new LinkedList<String>();
includesH = new LinkedList<String>();
nameSpaceH = new LinkedList<String>();
forwardDeclarationsH = new LinkedList<String>();
constructorH = new LinkedList<String>();
dataLayoutH = new LinkedList<String>();
methodsImplementedH = new LinkedList<String>();
vTableH = new LinkedList<String>();
OvTableLayoutH = new LinkedList<vTableLayoutLine>();
OvTableAddressH = new LinkedList<vTableAddressLine>();
vTableLayoutH = new LinkedList<vTableLayoutLine>();
vTableAddressH = new LinkedList<vTableAddressLine>();
writerCC = new FileWriter(fileCC);
writerH = new FileWriter(fileH);
outCC = new BufferedWriter(writerCC);
outH = new BufferedWriter(writerH);
ccstring = new LinkedList<String>();
hstring = new LinkedList<String>();
marginSpaceH = " ";
marginSpaceCC = " ";
readJavaLang();
}
catch (IOException e){
e.printStackTrace();
System.out.println("Something's up with the files and writers. Bitch.");
}
}
/** Final assembly of .cc and .h files */
private void assembleFile(){
assembleElement(includesCC,outCC);
assembleElement(nameSpaceCC,outCC);
assembleElement(methodCC,outCC);
assembleElement(vTableDefCC,outCC);
try {
outCC.close();
} catch (IOException e) {
e.printStackTrace();
}
assembleElement(includesH,outH);
assembleElement(nameSpaceH,outH);
assembleElement(forwardDeclarationsH,outH);
assembleElement(dataLayoutH,outH);
assembleElement(constructorH,outH);
assembleElement(methodsImplementedH,outH);
assembleElement(vTableH,outH);
//assembleVTable(vTableLayoutH,vTableAddressH,outH); //Will need it's own implementation to handle LinkedList<LinkedList> and insertion location details
try {
outH.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Aseembles elements from list into appropriate file.
*
* @param Element List of elements.
* @param file File aseembled to (outH or outCC).
*/
private void assembleElement(LinkedList<String> Element, BufferedWriter file){
while(!Element.isEmpty()){
try {
String vtablesearch = Element.peek();
file.write((String)Element.remove(0)+"\n");
if (vtablesearch.contains("//vTableStart")){
assembleVTable(file);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void assembleVTable(BufferedWriter file){
String classsearch = vTableLayoutH.peek().vTableClass;
while(!vTableLayoutH.isEmpty()){
String classcheck = vTableLayoutH.peek().vTableClass;
if(classcheck.equals(classsearch)){
vTableLayoutLine line = vTableLayoutH.pop();
try {
file.write(line.vTableLine);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
break;
}
}
while(!vTableAddressH.isEmpty()){
String classcheck = vTableAddressH.peek().vTableClass;
if(classcheck.equals(classsearch)){
vTableAddressLine line = vTableAddressH.pop();
try {
file.write(line.vTableLine);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
break;
}
}
}
private void addStringsToList(GNode n){
for(Object s: n){
if (s instanceof String){
if (hflag == true){
hstring.add(((String)s));
}
else{
ccstring.add(((String)s));
}
}
}
}
/**
* Reads java_lang.h and assembles java.lang.Object vtable in a LinkedList format
*
*/
public void readJavaLang(){
/*
try {
Scanner scan = new Scanner(java_langH);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
//vTableLayoutH
vTableLayoutLine line = new vTableLayoutLine();
line.setVTableClass("Object");
line.setReturnType("Class");
line.setMethodName("__isa");
line.createVTableLine();
OvTableLayoutH.add(line);
line = new vTableLayoutLine();
line.setVTableClass("Object");
line.setReturnType("int32_t");
line.setMethodName("hashCode");
line.setReferenceParameter("Object");
line.createVTableLine();
OvTableLayoutH.add(line);
line = new vTableLayoutLine();
line.setVTableClass("Object");
line.setReturnType("bool");
line.setMethodName("equals");
line.setReferenceParameter("Object");
line.setParameters("Object");
line.createVTableLine();
OvTableLayoutH.add(line);
line = new vTableLayoutLine();
line.setVTableClass("Object");
line.setReturnType("Class");
line.setMethodName("getClass");
line.setReferenceParameter("Object");
line.createVTableLine();
OvTableLayoutH.add(line);
line = new vTableLayoutLine();
line.setVTableClass("Object");
line.setReturnType("String");
line.setMethodName("toString");
line.setReferenceParameter("Object");
line.createVTableLine();
OvTableLayoutH.add(line);
//vTableAddressH
vTableAddressLine liner = new vTableAddressLine();
liner.setVTableClass("Object");
liner.setClassname("__Object");
liner.setMethodName("__isa");
liner.createVTableLine();
OvTableAddressH.add(liner);
liner = new vTableAddressLine();
liner.setVTableClass("Object");
liner.setClassname("__Object");
liner.setMethodName("hashCode");
liner.createVTableLine();
OvTableAddressH.add(liner);
liner = new vTableAddressLine();
liner.setVTableClass("Object");
liner.setClassname("__Object");
liner.setMethodName("equals");
liner.createVTableLine();
OvTableAddressH.add(liner);
liner = new vTableAddressLine();
liner.setVTableClass("Object");
liner.setClassname("__Object");
liner.setMethodName("getClass");
liner.createVTableLine();
OvTableAddressH.add(liner);
liner = new vTableAddressLine();
liner.setVTableClass("Object");
liner.setClassname("__Object");
liner.setMethodName("toString");
liner.createVTableLine();
OvTableAddressH.add(liner);
//testing
/*
while(!(OvTableLayoutH.isEmpty())){
vTableLayoutLine current = OvTableLayoutH.pop();
System.out.print(current.vTableLine);
}
while(!(OvTableAddressH.isEmpty())){
vTableAddressLine current = OvTableAddressH.pop();
System.out.print(current.vTableLine);
}
*/
}
public void convertVLayoutPrelim(String classname){
//clone the OvTableLayoutH
LinkedList<vTableLayoutLine> cloneOL = new LinkedList<vTableLayoutLine>();
int counter = 0;
try{
while(true){
vTableLayoutLine current = OvTableLayoutH.get(counter);
vTableLayoutLine news = new vTableLayoutLine();
news.setMethodName(current.methodname);
news.resetParameters(current.parameters);
news.setReferenceParameter(current.referenceparameter);
news.setReturnType(current.returntype);
news.setVTableClass(current.vTableClass);
cloneOL.add(news);
counter = counter + 1;
}
}
catch(Exception e){
//System.out.println("counter = " + counter);
}
LinkedList<vTableLayoutLine> newclone = new LinkedList<vTableLayoutLine>();
while(!(cloneOL.isEmpty())){
vTableLayoutLine current = cloneOL.pop();
current.setReferenceParameter(classname);
current.setVTableClass(classname);
current.createVTableLine();
newclone.add(current);
}
//testing
/*
while(!(newclone.isEmpty())){
vTableLayoutLine current = newclone.pop();
System.out.print(current.vTableLine);
}
*/
//return newclone;
vTableLayoutH.addAll(newclone);
}
//in progress conversion of addresslines to the right reference types
public void convertVTableAddress(String classname){
LinkedList<vTableAddressLine> cloneOA= new LinkedList<vTableAddressLine>();
int counter = 0;
try{
while(true){
vTableAddressLine current = OvTableAddressH.get(counter);
vTableAddressLine news = new vTableAddressLine();
//news.resetParameters(current.parameters);
//news.setReferenceParameter(current.referenceparameter);
//news.setReturnType(current.returntype);
news.setVTableClass(current.vTableClass);
news.setTypeCast(current.typecast);
news.setClassname(current.classname);
news.setMethodName(current.methodname);
cloneOA.add(news);
counter = counter + 1;
}
}
catch(Exception e){
//System.out.println("counter = " + counter);
}
LinkedList<vTableAddressLine> newclone = new LinkedList<vTableAddressLine>();
while(!(cloneOA.isEmpty())){
vTableAddressLine current = cloneOA.pop();
//current.setReferenceParameter(classname);
current.setVTableClass(classname);
if(current.methodname.equals("getClass")){
//current.classname = "__" + classname;
current.typecast = "(Class(*)(__" + classname + "))";
}
current.createVTableLine();
newclone.add(current);
}
vTableAddressH.addAll(newclone);
}
public void searchForMethodOverride(){
String classsearch = currentLayoutLine.vTableClass;
//System.out.println(classsearch);
String methodsearch = currentLayoutLine.methodname;
//System.out.println(methodsearch);
String parametersearch = currentLayoutLine.parameters;
//System.out.println(parametersearch);
String returntypesearch = currentLayoutLine.returntype;
//System.out.println(returntypesearch);
//System.out.println();
int counter = 0;
try{
boolean found = false;
while(true){
vTableLayoutLine current = vTableLayoutH.get(counter);
//if (current.vTableClass.equals(classsearch) && current.returntype.equals(returntypesearch) && current.methodname.equals(methodsearch) && current.parameters.equals(parametersearch)){
if(current.vTableLine.equals(currentLayoutLine.vTableLine)) {
vTableLayoutH.remove(counter);
found = true;
//System.out.println("found over");
break;
}
counter = counter + 1;
}
if(found == true){
counter = 0;
classsearch = currentAddressLine.vTableClass;
methodsearch = currentAddressLine.methodname;
//System.out.println("looking for " + methodsearch);
while(true){
vTableAddressLine current = vTableAddressH.get(counter);
//System.out.println(current.vTableClass + " " + current.methodname);
if(current.vTableClass.equals(classsearch) && current.methodname.equals(methodsearch) && !current.methodname.equals(null)){
vTableAddressH.remove(counter);
break;
}
counter = counter + 1;
}
}
}
catch (Exception e){
}
}
/**
* Possible Parents: None
* Writes to Elements: No
*
* @param n GNode from the parser
*/
public void visitCompilationUnit(GNode n){
createFilesAndWriters();
visit(n);
assembleFile();
}
/**
* Possible Parents:
* Writes to Elements: No
*
* covers byte, int, short, long
* @param n
*/
public void visitIntegerLiteral(GNode n){
addStringsToList(n);
}
/**
* Possible Parents:
* Writes to Elements: No
*
* @param n
*/
public void visitBooleanLiteral(GNode n){
addStringsToList(n);
}
/**
* Possible Parents:
* Writes to Elements: No
*
* @param n
*/
public void visitFloatingPointLiteral(GNode n){
addStringsToList(n);
}
/**
* Possible Parents:
* Writes to Elements: No
*
* @param n
*/
public void visitStringLiteral(GNode n){
addStringsToList(n);
}
/**
* Possible Parents:
* Writes to Elements: No
*
* handles addition and subtraction
* @param n
*/
public void visitAdditiveExpression(GNode n){
ExpressionHandler(n);
}
/**
* Possible Parents:
* Writes to Elemenst: No
*
* handles multiplication, division and modulus
* @param n
*/
public void visitMultiplicativeExpression(GNode n){
ExpressionHandler(n);
}
/**
* Possible Parents: Block
* Writes to Elements: methodCC
*
* @param n
*/
public void visitExpressionStatement(GNode n){
visit(n);
if (hflag == true){
hstring.add(";\r");
}
else{
ccstring.add(";\r");
}
String s = "";
while(hstring.size()!=0){
s.concat(hstring.pop());
}
}
/**
* Possible Parents: ExpressionStatement
* Writes to Elements: No
*
* @param n
*/
public void visitExpression(GNode n){
ExpressionHandler(n);
}
/**
* Writes to Elements: No
*
* @param n
*/
public void ExpressionHandler(GNode n){
for(Object o: n){
if (o instanceof Node){
dispatch((Node)o);
}
}
addStringsToList(n);
}
/**
* Possible Parents: ClassBody
* Writes to Elements: dataLayoutH
*
* @param n
*/
public void visitFieldDeclaration(GNode n){
visit(n);
if (hflag == true){
String hLine = marginSpaceH;
while(hstring.size()>0){
hLine = hLine + hstring.pop();
}
hLine = hLine + ";";
dataLayoutH.add(hLine);
}
}
/**
* Possible Parents: FieldDeclaration, MethodDeclaration
* Writes to Elements: No
*
* @param n
*/
public void visitVoidType(GNode n){
if (hflag == true){
hstring.add("void ");
}
else{
ccstring.add("void ");
}
}
/**
* Possible Parents: FieldDeclaration
* Writes to Elements: No
*
* @param n
*/
public void visitType(GNode n){
visit(n);
if (hflag == true){ //adding a space after the type name
hstring.add(" ");
}
else{
ccstring.add(" ");
}
}
/**
* Possible Parents: Type
* Writes to Elements: No
*
* primitive type specific, ex int, double, float, etc.
* @param n
*/
public void visitPrimitiveType(GNode n){
if(hreturntype == true){
String returntype = n.getString(0);
if(returntype.equals("int")){
returntype = "int32_t";
}
currentLayoutLine.setReturnType(returntype);
}
else if (hparameter == true){
String parameter = n.getString(0);
if(parameter.equals("int")){
parameter = "int32_t";
}
currentLayoutLine.setParameters(parameter);
}
addStringsToList(n);
}
/**
* Possible Parents: Expression
* Writes to Elements: No
*
* the name of the variable
* @param n
*/
public void visitPrimaryIdentifier(GNode n){
addStringsToList(n);
}
/**
* Possible Parents: PackageDeclaration, Type
* Writes to Elements: No
*
*
* @param n
*/
public void visitQualifiedIdentifier(GNode n){
if(hreturntype == true){
String returntype = n.getString(0);
currentLayoutLine.setReturnType(returntype);
}
else if (hparameter == true){
String parameter = n.getString(0);
currentLayoutLine.setParameters(parameter);
}
int i = 0;
while (i < n.size()){
if (hflag == true){
if(0<i && i<n.size()){
hstring.add(".");
}
hstring.add(((String)n.getString(i)));
}
else{
if(0<i && i<n.size()){
ccstring.add(".");
}
ccstring.add(((String)n.getString(i)));
}
i++;
}
}
/**
* Possible Parents: ClassDeclaration, FieldDeclaration, ConstructorDeclaration, MethodDeclaration
* Writes to Elements: No
*
*
* @param n
*/
public void visitModifiers(GNode n){
if (hflag == false){
visit(n);
}
}
/**
* Possible Parents: Modifiers
* Writes to Elements: No
*
* public, private, protected, abstract, static, etc.
* @param n
*/
public void visitModifier(GNode n){
addStringsToList(n);
if (hflag == true){
hstring.add(" ");
}
else{
ccstring.add(" ");
}
}
/**
* Possible Parents: FieldDeclaration
* Writes to Elements: No
*
*
* @param n
*/
public void visitDeclarators(GNode n){
visit(n);
}
/**
* Possible Parents: Declarators
* Writes to Elements: methodCC, dataLayoutH
*
* Large construct for declaring a variable
* @param n
*/
public void visitDeclarator(GNode n){
if(hflag == true){
hstring.add(" ");
hstring.add(n.getString(0));
}
else{
ccstring.add(n.getString(0));
if(n.hasVariable()) //check for other children, if has children then =, else nothing
ccstring.add("=");
visit(n);
}
}
/**
* Possible Parents: ClassBody
* Writes to Elements: No
*
* @param n
*/
public void visitBlock(GNode n){
visit(n);
}
/**
* Possible Parents: ClassDeclaration
* Writes to Elements: No
*
* @param n
*/
public void visitClassBody(GNode n){
for(Object o: n){
if (o instanceof Node){
if(((GNode)o).getName().equals("FieldDeclaration")){
hflag = true;
}
else{
hflag = false;
}
dispatch((Node)o);
}
}
}
/**
* Possible Parents: ClassBody
* Writes to Elements: No
*
* @param n
*/
public void visitConstructorDeclaration(GNode n){
hflag = true;
dispatch((Node)n.getNode(3));
String hLine;
hLine = marginSpaceH + "__" + className;
while (hstring.size()>0){
hLine = hLine + hstring.pop();
}
hLine = hLine + ";";
constructorH.add(hLine);
hflag = false;
visit(n);
}
/**
* Possible Parents:
* Writes to Elemenst: No
*
* handles multiplication, division and modulus
* @param n
*/
public void visitPostfixExpression(GNode n){
ccstring.clear();
}
/**
* Possible Parents: ConstructorDeclaration, MethodDeclaration
* Writes to Elements: No
*
* method arguments
* @param n
*/
public void visitFormalParameters(GNode n){
if (hflag == true){
hstring.add("(");
int i = 0;
for(Object o: n){
if (o instanceof Node){
dispatch((Node)o);
}
i++;
if (i < n.size()){
hstring.add(",");
}
}
hstring.add(")");
}
else{
ccstring.add("(");
int i = 0;
for(Object o: n){
if (o instanceof Node){
dispatch((Node)o);
}
i++;
if (i < n.size()){
ccstring.add(",");
}
}
ccstring.add(")");
}
}
/**
* Possible Parents: FormalParameters
* Writes to Elements: No
*
* @param n
*/
public void visitFormalParameter(GNode n){
for(Object o: n){
if (o instanceof Node){
dispatch((Node)o);
}
}
addStringsToList(n);
}
/**
* Possible Parents: ExpressionStatement, EqualityExpression, AdditiveExpression, Expression
* Writes to Elements: No
*
* @param n
*/
public void visitCallExpression(GNode n){
String ceString = "";
for(Object o: n){
if (o instanceof Node){
Node c = (Node)o;
if (c.hasName("SelectionExpression")){
dispatch((Node)o);
}
}
}
addStringsToList(n);
int i = cccount;
while(i < ccstring.size()){
ceString = ceString + ccstring.get(i) + "::";
ccstring.remove(i);
}
ceString = ceString.substring(0, ceString.length() -2);
if(ceString.contentEquals("System::out::println") || ceString.contentEquals("System::out::print")){
ceString = "";
if(!includesCC.contains("#include <iostream>"))
includesCC.add("#include <iostream>");
for(Object o: n){
if (o instanceof Node){
Node c = (Node)o;
if (c.hasName("Arguments")){
dispatch((Node)o);
}
}
}
i = cccount;
while(i < ccstring.size()){
ceString = ceString + ccstring.get(i);
ccstring.remove(i);
}
ceString = marginSpaceCC + "std::cout << " + ceString + "<< std::endl;\n";
ccstring.add(ceString);
cccount++;
}
visit(n);
}
/**
* Only used for System.out.println... for now
* Possible Parents: CallExpression
* Writes to Elements: MethodCC (special case)
*
* @param n
*/
public void visitSelectionExpression(GNode n){
visit(n);
addStringsToList(n);
}
/**
* Possible Parents: None (Comma)
* Writes to Elements: MethodCC
*
* @param n
*/
public void visitConditionalStatement(GNode n){
hflag=false;
visit(n);
}
/**
* Possible Parents: ConditionalStatement,
* Writes to Elements: ccLine
*
* @param n
*/
public void visitEqualityExpression(GNode n){
visit(n);
System.out.println(ccstring);
String condition = ccstring.remove(2);
String ccLine = "if("+ccstring.pop()+condition+ccstring.pop()+"=="+ccstring.pop()+")";
System.out.println(ccLine);
methodCC.add(ccLine);
ccLine="";
}
/**
* Possible Parents: CompilationUnit
* Writes to Elements: includesCC, includesH
*
* @param n
*/
public void visitImportDeclaration(GNode n){
String hLine = ""; //Creating the string line for includesH
hflag = true;
hLine = hLine + "#include <";
visit(n);
while(hstring.size()!=0){
hLine = hLine + hstring.pop();
}
hLine= hLine + ">;";
includesH.add(hLine);
hflag = false;
String ccLine = ""; //Creating the string line for includesCC
ccLine = ccLine + "#include <";
visit(n);
while(ccstring.size()!=0){
ccLine = ccLine + ccstring.pop();
}
ccLine= ccLine + ">;";
includesCC.add(ccLine);
}
/**
* Possible Parents: CompilationUnit
* Writes to Elements: namespaceCC, namespaceH
*
*
* @param n
*/
public void visitPackageDeclaration(GNode n){
String hLine = "";
hflag = true;
visit(n);
while(hstring.peekFirst()!=null){
if(hstring.peekFirst()=="."){
hstring.pop();
marginSpaceH = marginSpaceH + " ";
hLine = marginSpaceH;
}
hLine = hLine + "namespace ";
hLine = hLine + hstring.pop() + "{";
nameSpaceH.add(hLine);
}
hflag = false;
String ccLine = "";
visit(n);
while(ccstring.peekFirst()!=null){
if(ccstring.peekFirst()=="."){
ccstring.pop();
marginSpaceCC = marginSpaceCC + " ";
ccLine = marginSpaceCC;
}
ccLine = ccLine + "namespace ";
ccLine = ccLine + ccstring.pop() + "{";
nameSpaceCC.add(ccLine);
}
}
/**
* Possible Parents: CompilationUnit
* Writes to Elements: forwardDeclarationsH, dataLayoutH
*
* @param n
*/
public void visitClassDeclaration(GNode n){
String hLine;
className = n.getString(1);
hLine = marginSpaceH + "struct __" + className + ";"; //Adding 'struct __ClassName;' to forwardDeclarationH
forwardDeclarationsH.add(hLine);
hLine = marginSpaceH + "struct __" + className + "_VT;"; //Adding 'struct __ClassName_VT'; to forwardDeclarationH
forwardDeclarationsH.add(hLine);
hLine = ""; //Adding an empty line to forwardDeclarationH
forwardDeclarationsH.add(hLine);
hLine = marginSpaceH + "typedef __" + className + "* " + className + ";"; //Adding 'typedef __ClassName* ClassName;' to forwardDeclarationH
forwardDeclarationsH.add(hLine);
hLine = marginSpaceH + "struct __" + className + " {"; //Adding 'struct __ClassName {' to dataLayoutH
dataLayoutH.add(hLine);
marginSpaceH = marginSpaceH + " ";
hLine = marginSpaceH + "__" + className + "_VT* __vptr;"; //Adding '__ClassName_VT* __vptr; {' to dataLayoutH
dataLayoutH.add(hLine);
hLine = marginSpaceH + "static Class __class();"; //Adding 'static Class __class();' to vTableH
vTableH.add(hLine);
hLine = marginSpaceH + "static __" + className + "_VT __vtable;"; //Adding 'static __ClassName_VT __vtable;' to vTableH
vTableH.add(hLine);
marginSpaceH = marginSpaceH.substring(2);
hLine = marginSpaceH + "};";
vTableH.add(hLine);
hLine = "//vTableStart " + className;
vTableH.add(hLine);
hLine = "\r";
vTableH.add(hLine);
currentLayoutLineTemplate = new vTableLayoutLine();
currentLayoutLineTemplate.setReferenceParameter(className);
currentLayoutLineTemplate.setVTableClass(className);
currentAddressLineTemplate = new vTableAddressLine();
currentAddressLineTemplate.setVTableClass(className);
currentAddressLineTemplate.setClassname(className);
vTableAddressLine liner = new vTableAddressLine();
vTableLayoutLine line = new vTableLayoutLine();
line.setVTableClass(className);
liner.setVTableClass(className);
line.createStructLine("struct " + "__" + className + "_VT { \r");
liner.createStructLine("__" + className + "_VT() \r : ");
vTableAddressH.add(liner);
vTableLayoutH.add(line);
//LinkedList<vTableLayoutLine> cloneOL = new LinkedList<vTableLayoutLine>();
//LinkedList<vTableAddressLine> cloneOA = new LinkedList<vTableAddressLine>();
//cloneOA.addAll(OvTableAddressH);
//cloneOL.addAll(OvTableLayoutH);
convertVLayoutPrelim(className);
convertVTableAddress(className);
//while(!cloneOL.isEmpty()){
// vTableLayoutH.add(cloneOL.pop());
//}
//cloneOA = convertVTableAddress(cloneOA, className);
visit(n);
line = new vTableLayoutLine();
liner = new vTableAddressLine();
line.setVTableClass(className);
liner.setVTableClass(className);
line.createStructLine("\r");
liner.createStructLine(" { \r" + marginSpaceH + "} \r" + marginSpaceH + "}; \r");
vTableAddressH.add(liner);
vTableLayoutH.add(line);
}
public void visitArguments(GNode n){
visit(n);
}
public void visitMethodDeclaration(GNode n){
// --- header file --- (nothing here yet, really)
hflag = true;
String hLine = "";
addStringsToList(n);
String methodName = hstring.pop();
hstring.clear();
currentLayoutLine = new vTableLayoutLine();
currentLayoutLine.setReferenceParameter(currentLayoutLineTemplate.referenceparameter);
currentLayoutLine.setVTableClass(currentLayoutLineTemplate.vTableClass);
currentLayoutLine.setMethodName(n.getString(3));
currentAddressLine = new vTableAddressLine();
currentAddressLine.setVTableClass(currentAddressLineTemplate.vTableClass);
currentAddressLine.setMethodName(n.getString(3));
currentAddressLine.setClassname("__" + currentAddressLineTemplate.classname);
for(Object o: n){ // I'm making the assumption that the h file won't need to look
if (o instanceof Node){ // in the block of the method; I could be wrong.
Node c = (Node)o; // (but I don't think so)
if (!c.hasName("Block")){
if(c.hasName("Type")){
hparameter = false;
hreturntype = true;
}
else if (c.hasName("FormalParameters")){
hparameter = true;
hreturntype = false;
}
else{
hparameter = false;
hreturntype = false;
}
dispatch((Node)o);
}
}
}
currentLayoutLine.createVTableLine();
currentAddressLine.createVTableLine();
searchForMethodOverride();
if(!currentLayoutLine.methodname.equals("main")){
vTableLayoutH.add(currentLayoutLine);
vTableAddressH.add(currentAddressLine);
}
// while(!hstring.isEmpty()){
// hLine = hLine + hstring.pop() + " "; <---- printing stuff haphazardly, just to look at it
// }
// methodsImplementedH.add(hLine);
// --- cc file ---
hflag = false;
String ccLine = "";
ccstring.clear();
cccount = 0;
// actual method declaration line
if(methodName == "main"){
ccLine = "int main()";
}
else{
for(Object o: n){
if (o instanceof Node){
Node c = (Node)o;
if (!c.hasName("Block")){
dispatch((Node)o);
}
}
}
while(!ccstring.isEmpty()){
if (ccstring.peekFirst() == "public"
|| ccstring.peekFirst() == "private"
|| ccstring.peekFirst() == "protected"){
ccLine = marginSpaceCC.substring(2) + ccstring.pop() + ":\n" + marginSpaceCC;
}
else if (ccstring.peekFirst().charAt(0) == '('){
ccLine = ccLine + methodName + ccstring.pop();
}
else{
ccLine = ccLine + ccstring.pop();
}
}
}
ccLine = ccLine + "{";
marginSpaceCC.concat(" ");
methodCC.add(ccLine);
// method block
ccLine = marginSpaceCC;
for(Object o: n){
if (o instanceof Node){
Node c = (Node)o;
if (c.hasName("Block")){
dispatch((Node)o);
}
}
}
for(int i = 0; i < cccount; i++){
ccLine = ccLine + ccstring.pop();
}
ccLine = ccLine + marginSpaceCC + "return 0;\n" + marginSpaceCC + "}";
methodCC.add(ccLine);
}
/**
*
*
* @param n
*/
public void visit(Node n) {
for (Object o : n) if (o instanceof Node) dispatch((Node)o);
}
}.dispatch(node);
}
}
/**
* Run the translator with the specified command line arguments.
*
* @param args The command line arguments.
*/
public static void main(String[] args) {
new TestTranslator().run(args);
}
}
/*
* VTableLayout line can be broken up into several parts
* return type (*methodname) (parameters)
*
* VTableAddress line can be broken up into several parts
* methodname((anyspecialcasting)&class::methodname);
*
*
Class __isa;
int32_t (*hashCode)(Object);
bool (*equals)(Object, Object);
Class (*getClass)(Object);
String (*toString)(Object);
*/
class vTableLayoutLine{
String vTableClass;
String returntype;
String methodname;
String parameters;
String referenceparameter;
String vTableLine;
int parametercount = 0;
public vTableLayoutLine(){
parameters = ",";
}
public void setReturnType(String returnable){
returntype = returnable;
}
public void setReferenceParameter(String reference){
referenceparameter = reference;
}
public void setMethodName(String methodnamable){
methodname = methodnamable;
}
public void resetParameters(String parameter){
if(!parameter.equals(",")){
parameters = parameter;
parametercount = 1;
}
}
public void setParameters(String parameter){
if(parametercount == 0){
parameters = parameters + parameter;
parametercount++;
}
else{
parameters = parameters + "," + parameter;
parametercount++;
}
}
public void setVTableClass(String typeclass){
vTableClass = typeclass;
}
public void createStructLine(String definition){
vTableLine = definition;
}
public void createVTableLine(){
if(returntype == null)
returntype = "void";
vTableLine = returntype + " "; //+ "(*" + methodname + ") " + parameters + "); \r";
if (methodname.equals("__isa")){
vTableLine = vTableLine + methodname;
}
else{
vTableLine = vTableLine + "(*" + methodname + ") ";
vTableLine = vTableLine + "(" + referenceparameter;
if (parametercount > 0){
vTableLine = vTableLine + parameters;
}
vTableLine = vTableLine + ")";
}
vTableLine = vTableLine + "; \r";
}
}
class vTableAddressLine{
String vTableClass;
String methodname;
String typecast;
String classname;
String vTableLine;
public vTableAddressLine(){
}
public void setMethodName(String methodnamable){
methodname = methodnamable;
}
public void setTypeCast(String typecastable){
typecast = typecastable;
}
public void setClassname(String classnamable){
classname = classnamable;
}
public void setVTableClass(String classable){
vTableClass = classable;
}
public void createVTableLine(){
//methodname((anyspecialcasting)&class::methodname);
if(methodname.equals("__isa")){
vTableLine = methodname + "(";
vTableLine = vTableLine + "&" + "__" + classname + "::" + "__class()" + ")";
}
else{
vTableLine = ", \r" + methodname + "(";
if(!(typecast == null)){
vTableLine = vTableLine + "(" + typecast + ")";
}
vTableLine = vTableLine + "&" + classname + "::" + methodname + ")";
}
}
public void createStructLine(String definition){
vTableLine = definition;
}
}