/* */ package xtc.oop; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.util.LinkedList; 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 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<String> vTableLayoutH; private LinkedList<String> ccstring; private LinkedList<String> hstring; private boolean hflag; 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{ 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\";"); 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>(); vTableLayoutH = new LinkedList<String>(); 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 = ""; } catch (IOException e){ e.printStackTrace(); System.out.println("Something's up with the files and writers. Bitch."); } } /** Final aseembly 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(constructorH,outH); assembleElement(dataLayoutH,outH); assembleElement(methodsImplementedH,outH); assembleElement(vTableH,outH); assembleElement(vTableLayoutH,outH); 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 { file.write((String)Element.remove(0)+"\n"); } catch (IOException e) { e.printStackTrace(); } } } 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)); } } } } /** * 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); System.out.println(ccstring); } /** * Possible Parents: * Writes to Elemenst: No * * handles multiplication, division and modulus * @param n */ public void visitPostfixExpression(GNode n){ ccstring.clear(); } /** * 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()); } s = ""; while(ccstring.size()!=0){ s.concat(ccstring.pop()); } includesCC.add(s); } /** * 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); } } System.out.println(ccstring); addStringsToList(n); //Adjusted... MAKE SURE THIS WORKS!!! } /** * 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(); } // System.out.println(hLine); dataLayoutH.add(hLine); } } /** * Possible Parents: FieldDeclaration * Writes to Elements: No * * @param n */ public void visitType(GNode n){ visit(n); } /** * Possible Parents: Type * Writes to Elements: No * * primitive type specific, ex int, double, float, etc. * @param n */ public void visitPrimitiveType(GNode n){ 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){ 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); } /** * 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(n.getString(0)); //check for other children, if has children then =, else nothing if(n.hasVariable()) hstring.add("="); visit(n); hstring.add("; \r"); } else{ ccstring.add(n.getString(0) + "="); visit(n); ccstring.add("; \r"); } String s = ""; while(hstring.size()!=0){ s.concat(hstring.pop()); } dataLayoutH.add(s); s = ""; while(ccstring.size()!=0){ s.concat(ccstring.pop()); } methodCC.add(s); //System.out.print(n.getString(0)); //if(n.get(1) != null) visit(n.getNode(1)); //System.out.print("="); //visit(n); //System.out.print(";\r"); } /** * 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){ visit(n); } /** * Possible Parents: ConstructorDeclaration, MethodDeclaration * Writes to Elements: No * * method arguments * @param n */ public void visitFormalParameters(GNode n){ //add the first parenthesis visit(n); //add the closing parenthesis and the opening curly brace } /** * 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){ // System.out.println("Visiting Call"); ExpressionHandler(n); addStringsToList(n); // System.out.println(ccstring); 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); // System.out.println(ccstring); if(ccstring.size()>3 && ccstring.get(0).startsWith("System") && ccstring.get(1).startsWith("out") && ccstring.get(2).startsWith("println")){ // System.out.println("There's a print!"); } } /** * 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); visit(n); } /** * * * @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); } }