package Compiler; import java.util.ArrayList; import java.util.List; import Compiler.Expression.*; import Compiler.Statement.*; public class Translator{ List CCode = new ArrayList<>(); private Environment environment = new Environment(); public List compileToC(List statements, boolean printC){ CCode.add("#include "); CCode.add("#include "); CCode.add("int main(){"); try{ for (Statement statement: statements){ evaluateStatement(statement); } } catch (Error e){ } CCode.add("}"); if (printC) { for(String t:CCode){ System.out.println(t); } System.out.println(""); } return CCode; } private void evaluateStatement(Statement statement){ switch(statement.getStatmentType()){ 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; } } private void evalExpressionStatement(ExpressionStatement stmt){ evaluateExpression(stmt.expr); } private void evalStringDeclaration(StringDeclaration stringdec){ environment.defineVariable(stringdec.name.text, "string"); int size = (int)((Expression.Literal)stringdec.length).value.value; size++; CCode.add("char "+stringdec.name.text+"["+size+"];"); } private void evalVariableDeclaration(VariableDeclaration vardec){ environment.defineVariable(vardec.name.text, vardec.type); if(vardec.type.equals("int")){ CCode.add("int "+vardec.name.text+";"); } else if(vardec.type.equals("real")){ CCode.add("float "+vardec.name.text+";"); } } private void evalArrayDeclaration(ArrayDeclaration arraydec){ environment.defineVariable(arraydec.name.text, arraydec.type); String arrayString = ""; if(arraydec.type.equals("int")){ arrayString+="int "; } else if(arraydec.type.equals("real")){ arrayString+="real "; } arrayString+=arraydec.name.text; for(Expression expr:arraydec.dimensions){ arrayString+="["; arrayString+=evaluateExpression(expr); arrayString+="]"; } arrayString+=";"; CCode.add(arrayString); } private void evalBlockStatement(BlockStatement block){ for(Statement stmt:block.statements){ evaluateStatement(stmt); } } private void evalPrintStatement(PrintStatement print){ String types=""; String values=""; boolean first=true; for(Expression expr:print.exprList){ if(!first){ values+=","; }else{ first=false; } String exprType=""; if(expr instanceof Expression.Literal){ exprType=((Expression.Literal)expr).type; } else if (expr instanceof Expression.Variable){ exprType=(String)environment.getVariable((((Expression.Variable)expr).name)); } else if (expr instanceof Expression.ArrayVariable){ exprType=(String)environment.getVariable((((Expression.ArrayVariable)expr).name)); } if (exprType.equals("int")){ types+="%d"; } else if (exprType.equals("double")){ types+="%f"; } else if (exprType.equals("string")){ types+="%s"; } values+=evaluateExpression(expr); } types+="\\n"; CCode.add("printf(\""+types+"\","+values+");"); } private void evalIfStatement(IfStatement ifstatement){ CCode.add("if("+evaluateExpression(ifstatement.condition)+"){"); evaluateStatement(ifstatement.ifBlock); if(!(ifstatement.elseBlock==null)){ CCode.add("}"); CCode.add("else {"); evaluateStatement(ifstatement.elseBlock); } CCode.add("}"); } private void evalDoStatement(DoStatement dostatement){ String start = evaluateExpression(dostatement.variable)+"="+evaluateExpression(dostatement.start); String stop = evaluateExpression(dostatement.variable)+"<="+evaluateExpression(dostatement.stop); String step = evaluateExpression(dostatement.variable)+"++"; if(!(dostatement.step==null)){ step = evaluateExpression(dostatement.variable)+"+="+evaluateExpression(dostatement.step); } CCode.add("for("+start+";"+stop+";"+step+"){"); evaluateStatement(dostatement.codeBlock); CCode.add("}"); } private void evalDoWhileStatement(DoWhileStatement dowhilestatement){ CCode.add("while("+evaluateExpression(dowhilestatement.condition)+"){"); evaluateStatement(dowhilestatement.codeBlock); CCode.add("}"); } private String evaluateExpression(Expression expression){ switch(expression.getExpressionType()){ case "binary": return evaluateBinaryExpression((Binary)expression); case "singular": return evaluateSingularExpression((Singular)expression); case "literal": return evaluateLiteralExpression((Literal)expression); case "bracket": return evaluateBracketedExpression((BracketedExpression)expression); case "assign": evaluateAssignmentExpression((AssignmentExpression)expression); return ""; case "arrayvar": return evaluateArrayVariable((ArrayVariable)expression); case "var": return evaluateVariableExpression((Variable)expression); default: return null; } } private String evaluateBinaryExpression(Binary expr){ switch (expr.op.type){ case PLUS: //return "leftEval+rightEval" return evaluateExpression(expr.left)+"+"+evaluateExpression(expr.right); case STAR: return evaluateExpression(expr.left)+"*"+evaluateExpression(expr.right); case MINUS: return evaluateExpression(expr.left)+"-"+evaluateExpression(expr.right); case SLASH: return evaluateExpression(expr.left)+"/"+evaluateExpression(expr.right); case GREATER: return evaluateExpression(expr.left)+">"+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); default: break; } return null; } private String evaluateSingularExpression(Singular expr){ switch (expr.op.type){ case NOT: return "!"+evaluateExpression(expr.right); default: break; } return null; } private String evaluateLiteralExpression(Literal expr){ return (expr.value.value).toString(); } private String evaluateBracketedExpression(BracketedExpression expr){ return "("+evaluateExpression(expr.expr)+")"; } private void evaluateAssignmentExpression(AssignmentExpression expr){ Token name=null; 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; } if(environment.checkVariable(name)){ if(expr.value instanceof Expression.Literal){ 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)+";"); } } } private String evaluateArrayVariable(ArrayVariable expr){ if(environment.checkVariable(expr.name)){ String arrayString=""; arrayString+=expr.name.text; for(Expression position:expr.positions){ arrayString+="["; arrayString+=evaluateExpression(position); arrayString+="]"; } return arrayString; } return null; } private String evaluateVariableExpression(Variable expr){ return expr.name.text; } }