diff options
author | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-11-27 19:37:41 +0000 |
---|---|---|
committer | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-11-27 19:37:41 +0000 |
commit | 8badb0fab61a23dd81466c3f5f8aadd77bf952e3 (patch) | |
tree | 41a7e51e700ddee1a4e66aebfd3edaea29b60203 | |
parent | ac425713cfd5a4fac7ce5b607d722eeb9954ba10 (diff) | |
download | esotericFORTRAN-8badb0fab61a23dd81466c3f5f8aadd77bf952e3.tar.gz esotericFORTRAN-8badb0fab61a23dd81466c3f5f8aadd77bf952e3.zip |
Added basic support for arrays
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/Compiler/Expression.java | 27 | ||||
-rw-r--r-- | src/Compiler/Parser.java | 52 | ||||
-rw-r--r-- | src/Compiler/Statement.java | 32 | ||||
-rw-r--r-- | src/Compiler/TokenScanner.java | 1 | ||||
-rw-r--r-- | src/Compiler/TokenType.java | 2 | ||||
-rw-r--r-- | src/Compiler/Translator.java | 57 | ||||
-rw-r--r-- | src/example.txt | 20 |
8 files changed, 151 insertions, 41 deletions
@@ -101,3 +101,4 @@ report/* !report/*.bib !report/*.pdf !report/*images +src/.vscode/launch.json diff --git a/src/Compiler/Expression.java b/src/Compiler/Expression.java index d331f24..8bdf378 100644 --- a/src/Compiler/Expression.java +++ b/src/Compiler/Expression.java @@ -1,5 +1,7 @@ package Compiler; +import java.util.List; + abstract class Expression { static class Binary extends Expression{ @@ -70,11 +72,11 @@ abstract class Expression { } static class AssignmentExpression extends Expression{ - final Token name; + final Expression variable; final Expression value; - AssignmentExpression(Token name,Expression value){ - this.name=name; + AssignmentExpression(Expression variable,Expression value){ + this.variable=variable; this.value=value; } @@ -82,8 +84,7 @@ abstract class Expression { @Override public String getExpressionType() { return "assign"; - } - + } } static class Variable extends Expression{ @@ -99,5 +100,21 @@ abstract class Expression { final Token name; } + + static class ArrayVariable extends Expression{ + + ArrayVariable(Token name,List<Expression> positions){ + this.name=name; + this.positions=positions; + + } + @Override + public String getExpressionType() { + return "arrayvar"; + } + final Token name; + final List<Expression> positions; + + } public abstract String getExpressionType(); } diff --git a/src/Compiler/Parser.java b/src/Compiler/Parser.java index d0556e4..eba3513 100644 --- a/src/Compiler/Parser.java +++ b/src/Compiler/Parser.java @@ -3,7 +3,6 @@ package Compiler; import java.util.ArrayList; import java.util.List; -import Compiler.Statement.BlockStatement; public class Parser { private final List<Token> tokens; @@ -44,11 +43,17 @@ public class Parser { //Clean up and reduce code mess private Statement declaration(){ if (matchAndAdvance(TokenType.INT)){ + if(matchAndAdvance(TokenType.DIMENSION)){ + return arrayDeclaration("int"); + } matchOrError(TokenType.DEFINE, ":: Required for variable definition"); matchOrError(TokenType.IDENTIFIER,"Expected variable name."); Token varName = getPreviousToken(); return new Statement.VariableDeclaration(varName,"int"); } else if (matchAndAdvance(TokenType.REAL)){ + if(matchAndAdvance(TokenType.DIMENSION)){ + return arrayDeclaration("real"); + } matchOrError(TokenType.DEFINE, ":: Required for variable definition"); matchOrError(TokenType.IDENTIFIER,"Expected variable name."); Token varName = getPreviousToken(); @@ -79,7 +84,23 @@ public class Parser { return null; } - private BlockStatement blockStatement(){ + private Statement arrayDeclaration(String type){ + matchOrError(TokenType.LEFT_PAREN,"Expected ')'"); + List<Expression> dimensions = new ArrayList<>(); + Expression dimension = expression(); + dimensions.add(dimension); + while(matchAndAdvance(TokenType.COMMA)){ + dimension = expression(); + dimensions.add(dimension); + } + matchOrError(TokenType.RIGHT_PAREN, "Expected ')'"); + matchOrError(TokenType.DEFINE, ":: Required for variable definition"); + matchOrError(TokenType.IDENTIFIER,"Expected variable name."); + Token varName = getPreviousToken(); + return new Statement.ArrayDeclaration(varName, type, dimensions); + } + + private Statement blockStatement(){ List<Statement> statements = new ArrayList<>(); while(!matchAndAdvance(TokenType.END)&&!checkToken(TokenType.ELSE)){ if(checkEOF()){ @@ -107,8 +128,8 @@ public class Parser { private Statement ifStatement(){ Expression condition = expression(); if(matchOrError(TokenType.THEN, "then expected after if statement")){ - Statement.BlockStatement ifBlock = blockStatement(); - Statement.BlockStatement elseBlock=null; + Statement ifBlock = blockStatement(); + Statement elseBlock=null; if(matchAndAdvance(TokenType.ELSE)){ elseBlock=blockStatement(); @@ -133,7 +154,7 @@ public class Parser { if(matchAndAdvance(TokenType.COMMA)){ step = expression(); } - Statement.BlockStatement codeBlock = blockStatement(); + Statement codeBlock = blockStatement(); matchOrError(TokenType.DO, "Do statements end with do"); return new Statement.DoStatement(variable, start, stop, step,codeBlock); @@ -143,7 +164,7 @@ public class Parser { matchOrError(TokenType.LEFT_PAREN, " missing '(' for do statement condition"); Expression condition = expression(); matchOrError(TokenType.RIGHT_PAREN, " missing ')' for do condition"); - Statement.BlockStatement codeBlock = blockStatement(); + Statement codeBlock = blockStatement(); matchOrError(TokenType.DO, "Do while statements end with do"); return new Statement.DoWhileStatement(condition,codeBlock); } @@ -157,11 +178,7 @@ public class Parser { Expression variable = expression(); if (matchAndAdvance(TokenType.EQUALS)){ Expression assignedvalue = expression(); - - if (variable instanceof Expression.Variable){ - return new Expression.AssignmentExpression(((Expression.Variable)variable).name,assignedvalue); - } - throw error(getCurrentToken(),"Left of assignment must be a variable"); + return new Expression.AssignmentExpression(variable,assignedvalue); } return variable; } @@ -240,7 +257,18 @@ public class Parser { } if (matchAndAdvance(TokenType.IDENTIFIER)) { - + Token name= getPreviousToken(); + if(matchAndAdvance(TokenType.LEFT_PAREN)){ + List<Expression> positions = new ArrayList<>(); + Expression position = expression(); + positions.add(position); + while(matchAndAdvance(TokenType.COMMA)){ + position = expression(); + positions.add(position); + } + matchOrError(TokenType.RIGHT_PAREN,"Expected ')'"); + return new Expression.ArrayVariable(name, positions); + } return new Expression.Variable(getPreviousToken()); } diff --git a/src/Compiler/Statement.java b/src/Compiler/Statement.java index a3c0960..a4fbff7 100644 --- a/src/Compiler/Statement.java +++ b/src/Compiler/Statement.java @@ -33,15 +33,15 @@ abstract class Statement { } static class IfStatement extends Statement{ - IfStatement(Expression condition, BlockStatement ifBlock,BlockStatement elseBlock){ + IfStatement(Expression condition, Statement ifBlock,Statement elseBlock){ this.condition=condition; this.ifBlock=ifBlock; this.elseBlock=elseBlock; } final Expression condition; - final BlockStatement ifBlock; - final BlockStatement elseBlock; + final Statement ifBlock; + final Statement elseBlock; @Override public String getStatmentType() { @@ -50,7 +50,7 @@ abstract class Statement { } static class DoStatement extends Statement{ - DoStatement(Expression variable, Expression start,Expression stop,Expression step,BlockStatement codeBlock){ + DoStatement(Expression variable, Expression start,Expression stop,Expression step,Statement codeBlock){ this.variable=variable; this.start=start; this.stop=stop; @@ -63,7 +63,7 @@ abstract class Statement { final Expression start; final Expression stop; final Expression step; - final BlockStatement codeBlock; + final Statement codeBlock; @Override public String getStatmentType() { @@ -72,14 +72,14 @@ abstract class Statement { } static class DoWhileStatement extends Statement{ - DoWhileStatement(Expression condition,BlockStatement codeBlock){ + DoWhileStatement(Expression condition,Statement codeBlock){ this.condition=condition; this.codeBlock=codeBlock; } final Expression condition; - final BlockStatement codeBlock; + final Statement codeBlock; @Override public String getStatmentType() { @@ -122,6 +122,24 @@ abstract class Statement { } + static class ArrayDeclaration extends Statement{ + ArrayDeclaration(Token name,String type,List<Expression> dimensions){ + this.name=name; + this.dimensions=dimensions; + this.type=type; + } + + final String type; + final Token name; + final List<Expression> dimensions; + + @Override + public String getStatmentType() { + return "arrayDec"; + } + + } + static class PrintStatement extends Statement{ PrintStatement(List<Expression> exprList){ this.exprList=exprList; diff --git a/src/Compiler/TokenScanner.java b/src/Compiler/TokenScanner.java index 5f55119..aed5f38 100644 --- a/src/Compiler/TokenScanner.java +++ b/src/Compiler/TokenScanner.java @@ -228,5 +228,6 @@ public class TokenScanner { keywords.put("else", TokenType.ELSE); keywords.put("do", TokenType.DO); keywords.put("while", TokenType.WHILE); + keywords.put("dimension", TokenType.DIMENSION); } } diff --git a/src/Compiler/TokenType.java b/src/Compiler/TokenType.java index a82d169..bc82cde 100644 --- a/src/Compiler/TokenType.java +++ b/src/Compiler/TokenType.java @@ -12,7 +12,7 @@ public enum TokenType { NUMBER,IDENTIFIER,STRING, - INT,REAL,PRINT,ENDPRINT,IF,THEN,END,ELSE,LEN,DO,WHILE,AND,OR,NOT, + INT,REAL,PRINT,ENDPRINT,IF,THEN,END,ELSE,LEN,DO,WHILE,AND,OR,NOT,DIMENSION, EOF } diff --git a/src/Compiler/Translator.java b/src/Compiler/Translator.java index c40c6b5..a79242d 100644 --- a/src/Compiler/Translator.java +++ b/src/Compiler/Translator.java @@ -46,6 +46,9 @@ public class Translator{ case "stringDec": evalStringDeclaration((StringDeclaration)statement); break; + case "arrayDec": + evalArrayDeclaration((ArrayDeclaration)statement); + break; case "block": evalBlockStatement((BlockStatement)statement); break; @@ -83,6 +86,26 @@ public class Translator{ } } + 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); @@ -106,6 +129,9 @@ public class Translator{ 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")){ @@ -162,6 +188,8 @@ public class Translator{ case "assign": evaluateAssignmentExpression((AssignmentExpression)expression); return ""; + case "arrayvar": + return evaluateArrayVariable((ArrayVariable)expression); case "var": return evaluateVariableExpression((Variable)expression); default: @@ -220,18 +248,39 @@ public class Translator{ } private void evaluateAssignmentExpression(AssignmentExpression expr){ - if(environment.checkVariable(expr.name)){ + 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("+expr.name.text+","+evaluateExpression(expr.value)+");"); + CCode.add("strcpy("+evaluateExpression(expr.variable)+","+evaluateExpression(expr.value)+");"); }else{ - CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";"); + CCode.add(evaluateExpression(expr.variable)+"="+evaluateExpression(expr.value)+";"); } } else{ - CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";"); + 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){ diff --git a/src/example.txt b/src/example.txt index 55236c1..22a2bfb 100644 --- a/src/example.txt +++ b/src/example.txt @@ -1,12 +1,8 @@ -int::n -int::a -int::b -int::temp -a=0 -b=2 -if (a==0.and.b==1) then -print*,"true" -else -print*,"false" -end if - +int dimension(5)::test +int::i +do i=0,4 +test(i)=i +end do +do i=0,4 +print*,test(i) +end do
\ No newline at end of file |