summaryrefslogtreecommitdiffstats
path: root/src/Compiler/Translator.java
diff options
context:
space:
mode:
authorAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-12-05 03:27:18 +0000
committerAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-12-05 03:27:18 +0000
commit9e6c89f1fa93287104381e02f0bbbdd6060a9382 (patch)
tree65a26fbbccb0172805b131b7100ffcabb7790da3 /src/Compiler/Translator.java
parent43909b350b9084ed33f121a15c5770224cbdc79f (diff)
downloadesotericFORTRAN-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.java197
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;
}
-
-
-
}