From 8badb0fab61a23dd81466c3f5f8aadd77bf952e3 Mon Sep 17 00:00:00 2001
From: AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>
Date: Sat, 27 Nov 2021 19:37:41 +0000
Subject: Added basic support for arrays

---
 src/Compiler/Expression.java   | 27 ++++++++++++++++----
 src/Compiler/Parser.java       | 52 +++++++++++++++++++++++++++++---------
 src/Compiler/Statement.java    | 32 ++++++++++++++++++------
 src/Compiler/TokenScanner.java |  1 +
 src/Compiler/TokenType.java    |  2 +-
 src/Compiler/Translator.java   | 57 +++++++++++++++++++++++++++++++++++++++---
 src/example.txt                | 20 ++++++---------
 7 files changed, 150 insertions(+), 41 deletions(-)

(limited to 'src')

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{
@@ -98,6 +99,22 @@ 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
-- 
cgit v1.2.3