package Compiler; import java.util.ArrayList; import java.util.List; import Compiler.Expression.*; import Compiler.Statement.*; /** * Class to take a convert a list of statements into equivalent C source code */ public class Translator{ List CCode = new ArrayList<>(); private Environment environment = new Environment(); /** * Method to take a list of statements and convert to C code * @param statements a list of statement objects * @param printC a variable to say if the produced C code should be outputted * @return a list of strings for each line of the produced C code */ public List compileToC(List statements, boolean printC){ //Write basic include header files CCode.add("#include "); CCode.add("#include "); CCode.add("#include "); //Try and write each statement, with a space between each try{ for (Statement statement: statements){ evaluateStatement(statement); CCode.add(""); } } catch (Error e){ } //Output the C code if desired if (printC) { for(String t:CCode){ System.out.println(t); } System.out.println(""); } return CCode; } /** * Method to write a single statement to C * @param statement the statement to write to C */ private void evaluateStatement(Statement statement){ //Call the correct function for each statement type switch(statement.getStatmentType()){ case "main": evalMainFunction((MainFunction)statement); break; case "function": evalFunction((Function)statement); break; case "functionDec": evalFunctionDeclaration((FunctionDeclaration)statement); break; case "exprStmt": evalExpressionStatement((ExpressionStatement)statement); break; case "varDec": evalVariableDeclaration((VariableDeclaration)statement); break; case "stringDec": evalStringDeclaration((StringDeclaration)statement); break; case "arrayDec": evalArrayDeclaration((ArrayDeclaration)statement); break; case "block": evalBlockStatement((BlockStatement)statement); break; case "print": evalPrintStatement((PrintStatement)statement); break; case "ifStmt": evalIfStatement((IfStatement)statement); break; case "doStmt": evalDoStatement((DoStatement)statement); break; case "dowhileStmt": evalDoWhileStatement((DoWhileStatement)statement); break; case "return": evalReturnStatement((ReturnStatement)statement); break; } } /** * Method to write the main function * @param stmt statement to write */ private void evalMainFunction(MainFunction stmt){ CCode.add("int main(){"); evaluateStatement(stmt.block); CCode.add("}"); } /** * Method to write a function * @param stmt statement to write */ private void evalFunction(Function stmt){ String functionString; if(!(stmt.returnType==null)){ functionString = stmt.returnType+" "+stmt.name.text+"("; }else{ functionString = "void "+stmt.name.text+"("; } boolean first=true; //Write each function argument into C for(int i=0;i"+evaluateExpression(expr.right); case LESS: return evaluateExpression(expr.left)+"<"+evaluateExpression(expr.right); case GREATER_EQUAL: return evaluateExpression(expr.left)+">="+evaluateExpression(expr.right); case LESS_EQUAL: return evaluateExpression(expr.left)+"<="+evaluateExpression(expr.right); case EQUALITY: return evaluateExpression(expr.left)+"=="+evaluateExpression(expr.right); case AND: return evaluateExpression(expr.left)+"&&"+evaluateExpression(expr.right); case OR: return evaluateExpression(expr.left)+"||"+evaluateExpression(expr.right); case EXPONENT: return "pow("+evaluateExpression(expr.left)+","+evaluateExpression(expr.right)+")"; case NOT_EQUAL: return evaluateExpression(expr.left)+"!="+evaluateExpression(expr.right); default: break; } return null; } /** * Method to write a singular expression * @param expr the expression to write * @return the string representation of the expression */ private String evaluateSingularExpression(Singular expr){ switch (expr.op.type){ case NOT: return "!"+evaluateExpression(expr.right); default: break; } return null; } /** * Method to write a literal expression * @param expr the expression to write * @return the string representation of the expression */ private String evaluateLiteralExpression(Literal expr){ return (expr.value.value).toString(); } /** * Method to write a bracketed expression * @param expr the expression to write * @return the string representation of the expression */ private String evaluateBracketedExpression(BracketedExpression expr){ return "("+evaluateExpression(expr.expr)+")"; } /** * Method to write an assignment expression * @param expr the expression to write */ private void evaluateAssignmentExpression(AssignmentExpression expr){ Token name=null; //Get the name of the variable being assigned to if(expr.variable instanceof Expression.Variable){ name = ((Expression.Variable)expr.variable).name; } else if(expr.variable instanceof Expression.ArrayVariable){ name = ((Expression.ArrayVariable)expr.variable).name; } //Check if the variable has been previously declared if(environment.checkVariable(name)){ //Check if the value being assigned is a literal or some other expression if(expr.value instanceof Expression.Literal){ //Strings are handled differently in C, so the string has to be copied into the variable if(((Expression.Literal)expr.value).type.equals("string")){ CCode.add("strcpy("+evaluateExpression(expr.variable)+","+evaluateExpression(expr.value)+");"); }else{ CCode.add(evaluateExpression(expr.variable)+"="+evaluateExpression(expr.value)+";"); } } else{ CCode.add(evaluateExpression(expr.variable)+"="+evaluateExpression(expr.value)+";"); } } } /** * Method to write an array variable * @param expr the expression to write * @return the string representation of the expression */ private String evaluateArrayVariable(ArrayVariable expr){ //Check the array has been defined if(environment.checkVariable(expr.name)){ String arrayString=""; arrayString+=expr.name.text; //Write each dimension value for(Expression position:expr.positions){ arrayString+="["; arrayString+=evaluateExpression(position); arrayString+="]"; } return arrayString; } return null; } /** * Method to write a variable expression * @param expr the expression to write * @return the string representation of the expression */ private String evaluateVariableExpression(Variable expr){ return expr.name.text; } /** * Method to write a function call * @param expr the expression to write * @return the string representation of the expression */ private String evaluateFunctionCall(FunctionCall expr){ String functioncall=""; functioncall+=expr.name.text+"("; boolean first=true; //Write each argument of the function call for(Expression arg:expr.arguments){ if(!first){ functioncall+=","; } functioncall+=evaluateExpression(arg); first=false; } functioncall+=")"; return functioncall; } }