diff options
author | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-12-05 03:27:18 +0000 |
---|---|---|
committer | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-12-05 03:27:18 +0000 |
commit | 9e6c89f1fa93287104381e02f0bbbdd6060a9382 (patch) | |
tree | 65a26fbbccb0172805b131b7100ffcabb7790da3 /src/Compiler/Translator.java | |
parent | 43909b350b9084ed33f121a15c5770224cbdc79f (diff) | |
download | esotericFORTRAN-9e6c89f1fa93287104381e02f0bbbdd6060a9382.tar.gz esotericFORTRAN-9e6c89f1fa93287104381e02f0bbbdd6060a9382.zip |
Added subroutines and comments for most files
Diffstat (limited to 'src/Compiler/Translator.java')
-rw-r--r-- | src/Compiler/Translator.java | 197 |
1 files changed, 182 insertions, 15 deletions
diff --git a/src/Compiler/Translator.java b/src/Compiler/Translator.java index e0bff23..d520b67 100644 --- a/src/Compiler/Translator.java +++ b/src/Compiler/Translator.java @@ -6,16 +6,25 @@ 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<String> 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<String> compileToC(List<Statement> statements, boolean printC){ + //Write basic include header files CCode.add("#include <stdio.h>"); CCode.add("#include <string.h>"); + //Try and write each statement, with a space between each try{ for (Statement statement: statements){ evaluateStatement(statement); @@ -25,6 +34,7 @@ public class Translator{ } + //Output the C code if desired if (printC) { for(String t:CCode){ System.out.println(t); @@ -34,7 +44,12 @@ public class Translator{ 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); @@ -78,40 +93,76 @@ public class Translator{ } } + /** + * 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 = stmt.returnType+" "+stmt.name.text+"("; + 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<stmt.arguments.size();i++){ if(!first){ functionString+=","; } - environment.defineVariable(evaluateExpression(stmt.arguments.get(i)), stmt.argumentTypes.get(i)); - functionString+=stmt.argumentTypes.get(i)+" "+evaluateExpression(stmt.arguments.get(i)); + String type = stmt.argumentTypes.get(i); + Expression arg = stmt.arguments.get(i); + + //Define each argument variable in the environment + if(type.equals("char*")){ + environment.defineVariable(evaluateExpression(arg), "string"); + }else{ + environment.defineVariable(evaluateExpression(arg), type); + } + + functionString+=type+" "+evaluateExpression(arg); first=false; } functionString+="){"; + + //Write function block CCode.add(functionString); evaluateStatement(stmt.block); CCode.add("}"); } + /** + * Method to write a return statement + * @param stmt statement to write + */ private void evalReturnStatement(ReturnStatement stmt){ CCode.add("return "+evaluateExpression(stmt.returnValue)+";"); - - } + /** + * Method to write a function declaration + * @param stmt statement to write + */ private void evalFunctionDeclaration(FunctionDeclaration stmt){ - - String functionString = stmt.returnType+" "+stmt.name.text+"("; + String functionString; + if(!(stmt.returnType==null)){ + functionString = stmt.returnType+" "+stmt.name.text+"("; + }else{ + functionString = "void "+stmt.name.text+"("; + } boolean first=true; + + //Write each argument data type for(int i=0;i<stmt.argumentTypes.size();i++){ if(!first){ functionString+=","; @@ -120,22 +171,42 @@ public class Translator{ first=false; } functionString+=");"; + CCode.add(functionString); } + /** + * Method to write an expression statement + * @param stmt statement to write + */ private void evalExpressionStatement(ExpressionStatement stmt){ - evaluateExpression(stmt.expr); + String value = evaluateExpression(stmt.expr); + CCode.add(value+";"); } + /** + * Method to write a string declaration statement + * @param stringdec statement to write + */ private void evalStringDeclaration(StringDeclaration stringdec){ + //Add variable to the environment environment.defineVariable(stringdec.name.text, "string"); + + //Get the size of the string int size = (int)((Expression.Literal)stringdec.length).value.value; + //Increase the size of the string by 1 to match C code correctly size++; CCode.add("char "+stringdec.name.text+"["+size+"];"); } + /** + * Method to write a variable declaration + * @param vardec statement to write + */ private void evalVariableDeclaration(VariableDeclaration vardec){ + //Add variable to the environment environment.defineVariable(vardec.name.text, vardec.type); + //Write correct data type if(vardec.type.equals("int")){ CCode.add("int "+vardec.name.text+";"); } else if(vardec.type.equals("real")){ @@ -143,8 +214,15 @@ public class Translator{ } } + /** + * Method to write an array declaration + * @param arraydec statement to write + */ private void evalArrayDeclaration(ArrayDeclaration arraydec){ + //Add variable to the environment environment.defineVariable(arraydec.name.text, arraydec.type); + + //Get the array data type String arrayString = ""; if(arraydec.type.equals("int")){ arrayString+="int "; @@ -152,6 +230,8 @@ public class Translator{ arrayString+="real "; } arrayString+=arraydec.name.text; + + //Write each dimension of the array for(Expression expr:arraydec.dimensions){ arrayString+="["; arrayString+=evaluateExpression(expr); @@ -163,23 +243,36 @@ public class Translator{ } + /** + * Method to write a block statement + * @param block statement to write + */ private void evalBlockStatement(BlockStatement block){ + //Write each statement in the block for(Statement stmt:block.statements){ evaluateStatement(stmt); } } + /** + * Method to write a print statement + * @param print statement to write + */ private void evalPrintStatement(PrintStatement print){ String types=""; String values=""; boolean first=true; + + //Write each expression in the print statement for(Expression expr:print.exprList){ + //Don't add a comma for the first value in the print statement if(!first){ values+=","; }else{ first=false; } String exprType=""; + //Get the data type for each expression if(expr instanceof Expression.Literal){ exprType=((Expression.Literal)expr).type; } @@ -189,6 +282,8 @@ public class Translator{ else if (expr instanceof Expression.ArrayVariable){ exprType=(String)environment.getVariable((((Expression.ArrayVariable)expr).name)); } + + //Set the correct data type for the print statement if (exprType.equals("int")){ types+="%d"; } else if (exprType.equals("double")){ @@ -196,16 +291,24 @@ public class Translator{ } else if (exprType.equals("string")){ types+="%s"; } + //Add the actual expression value values+=evaluateExpression(expr); } + //Add a line break at the end of the print statement text types+="\\n"; CCode.add("printf(\""+types+"\","+values+");"); } + /** + * Method to write an if statement + * @param ifstatement statement to write + */ private void evalIfStatement(IfStatement ifstatement){ - + //Write if statement block CCode.add("if("+evaluateExpression(ifstatement.condition)+"){"); evaluateStatement(ifstatement.ifBlock); + + //Write else block if needed if(!(ifstatement.elseBlock==null)){ CCode.add("}"); CCode.add("else {"); @@ -214,24 +317,43 @@ public class Translator{ CCode.add("}"); } + /** + * Method to write a do statement + * @param dostatement statement to write + */ private void evalDoStatement(DoStatement dostatement){ + //Form the sections of the for loop, assuming the step variable has not been defined String start = evaluateExpression(dostatement.variable)+"="+evaluateExpression(dostatement.start); String stop = evaluateExpression(dostatement.variable)+"<="+evaluateExpression(dostatement.stop); String step = evaluateExpression(dostatement.variable)+"++"; + + //Update step variable if needed if(!(dostatement.step==null)){ step = evaluateExpression(dostatement.variable)+"+="+evaluateExpression(dostatement.step); } + CCode.add("for("+start+";"+stop+";"+step+"){"); evaluateStatement(dostatement.codeBlock); CCode.add("}"); } + /** + * Method to write a do while loop + * @param dowhilestatement statement to write + */ private void evalDoWhileStatement(DoWhileStatement dowhilestatement){ CCode.add("while("+evaluateExpression(dowhilestatement.condition)+"){"); evaluateStatement(dowhilestatement.codeBlock); CCode.add("}"); } + /** + * Method to write the correct expression object to C + * Since an expression is not a full line, the string is returned + * Except for assignment expressions + * @param expression the expression to write + * @return the string representation of an expression + */ private String evaluateExpression(Expression expression){ switch(expression.getExpressionType()){ case "binary": @@ -243,6 +365,7 @@ public class Translator{ case "bracket": return evaluateBracketedExpression((BracketedExpression)expression); case "assign": + //Assignments are full lines, so no need to return the string evaluateAssignmentExpression((AssignmentExpression)expression); return ""; case "arrayvar": @@ -256,6 +379,11 @@ public class Translator{ } } + /** + * Method to write a binary expression + * @param expr the expression to write + * @return the string representation of the expression + */ private String evaluateBinaryExpression(Binary expr){ switch (expr.op.type){ case PLUS: @@ -288,6 +416,11 @@ public class Translator{ 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: @@ -298,24 +431,42 @@ public class Translator{ 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{ @@ -328,10 +479,17 @@ public class Translator{ } } + /** + * 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); @@ -342,14 +500,26 @@ public class Translator{ 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(Token arg:expr.arguments){ if(!first){ functioncall+=","; @@ -360,9 +530,6 @@ public class Translator{ functioncall+=")"; return functioncall; } - - - } |