diff options
| author | jwansek <eddie.atten.ea29@gmail.com> | 2021-11-22 18:46:42 +0000 | 
|---|---|---|
| committer | jwansek <eddie.atten.ea29@gmail.com> | 2021-11-22 18:46:42 +0000 | 
| commit | de5022e778c12a8b91b905473f2f74bf7172eac3 (patch) | |
| tree | 4f16f1cb0b6b75c0e8975bb77f432071684e57ed /src | |
| parent | 6557b7b080abab676cc15774bb4b4428e776cd03 (diff) | |
| parent | 424ac34886895756525fbf5ddd704976e2e7d7dc (diff) | |
| download | esotericFORTRAN-de5022e778c12a8b91b905473f2f74bf7172eac3.tar.gz esotericFORTRAN-de5022e778c12a8b91b905473f2f74bf7172eac3.zip | |
Merge branch 'main' of https://github.com/AlfieEagleton/EsotericProject into argparse
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compiler/Environment.java | 19 | ||||
| -rw-r--r-- | src/Compiler/ExecuteC.java | 2 | ||||
| -rw-r--r-- | src/Compiler/Expression.java | 17 | ||||
| -rw-r--r-- | src/Compiler/Language.java | 11 | ||||
| -rw-r--r-- | src/Compiler/Parser.java | 89 | ||||
| -rw-r--r-- | src/Compiler/Token.java | 4 | ||||
| -rw-r--r-- | src/Compiler/TokenScanner.java | 35 | ||||
| -rw-r--r-- | src/Compiler/TokenType.java | 2 | ||||
| -rw-r--r-- | src/Compiler/Translator.java | 42 | ||||
| -rw-r--r-- | src/example.txt | 19 | 
10 files changed, 164 insertions, 76 deletions
| diff --git a/src/Compiler/Environment.java b/src/Compiler/Environment.java index 3ccf425..1bb0e88 100644 --- a/src/Compiler/Environment.java +++ b/src/Compiler/Environment.java @@ -12,21 +12,20 @@ public class Environment {      }      //Get a variable if it is defined, or report an error -    public Object getVariable(String name){ -        if(variableMap.containsKey(name)){ -            return variableMap.get(name); +    public Object getVariable(Token token){ +        if(variableMap.containsKey(token.text)){ +            return variableMap.get(token.text);          } -        Language.displayError("Undefined Variable"); +        Language.displayError(token,"Undefined Variable");          throw new Error();      } -    //Assign a value to an existing variable -    public void assignVariable(String name,Object value){ -        if(variableMap.containsKey(name)){ -            variableMap.put(name, value); -            return; +    //Get a variable if it is defined, or report an error +    public Boolean checkVariable(Token token){ +        if(variableMap.containsKey(token.text)){ +            return true;          } -        Language.displayError("Variable undefined"); +        Language.displayError(token,"Undefined Variable");          throw new Error();      }  } diff --git a/src/Compiler/ExecuteC.java b/src/Compiler/ExecuteC.java index dd26e3c..fbc7ade 100644 --- a/src/Compiler/ExecuteC.java +++ b/src/Compiler/ExecuteC.java @@ -40,7 +40,7 @@ public class ExecuteC {                  System.out.println(output);              }          } else { -            Language.displayError("Runtime Error"); +            Language.displayError(0, "Runtime Error");          }          if (!leaveCFile) {              cProgram.delete(); diff --git a/src/Compiler/Expression.java b/src/Compiler/Expression.java index 7605c8b..d331f24 100644 --- a/src/Compiler/Expression.java +++ b/src/Compiler/Expression.java @@ -20,6 +20,23 @@ abstract class Expression {      } +    static class Singular extends Expression{ + +        final Expression right; +        final Token op; + +        Singular(Token op, Expression right){ +            this.op=op; +            this.right = right; +        } + +        @Override +        public String getExpressionType() { +            return "singular"; +        } + +    } +      static class Literal extends Expression{          final Token value;          final String type; diff --git a/src/Compiler/Language.java b/src/Compiler/Language.java index 7326d10..1d95555 100644 --- a/src/Compiler/Language.java +++ b/src/Compiler/Language.java @@ -113,9 +113,16 @@ public class Language {      }      //Basic error reporting -    static void displayError(String message){ +    static void displayError(int line,String message){          hadError=true; -        System.out.println("An error was encountered"); +        System.out.println("An error was encountered on line: "+line); +        System.out.println(message); +    } +    //Basic error reporting +    static void displayError(Token token,String message){ +        hadError=true; +        System.out.println("An error was encountered on line: "+token.line); +        System.out.println("ERROR: "+token.text);          System.out.println(message);      } diff --git a/src/Compiler/Parser.java b/src/Compiler/Parser.java index 8bb8951..d0556e4 100644 --- a/src/Compiler/Parser.java +++ b/src/Compiler/Parser.java @@ -17,7 +17,7 @@ public class Parser {          List<Statement> statements =  new ArrayList<>();          try{              while (!checkEOF()){ -                statements.add(declaration()); +                statements.add(statement());              }          }catch (Error e){              return null; @@ -26,6 +26,20 @@ public class Parser {      } +    private Statement statement(){ +        if(checkToken(TokenType.INT)||checkToken(TokenType.REAL)||checkToken(TokenType.STRING)){ +            return declaration(); +        } +        else if (matchAndAdvance(TokenType.PRINT)){ +            return printStatement(); +        }else if (matchAndAdvance(TokenType.IF)){ +            return ifStatement(); +        }else if (matchAndAdvance(TokenType.DO)){ +            return doStatement(); +        } +        return expressionStatement(); +    } +      //Clean up and reduce code mess      private Statement declaration(){ @@ -47,13 +61,13 @@ public class Parser {              matchOrError(TokenType.EQUALS, "Length of string must be defined");              Expression length = expression();              if(!(length instanceof Expression.Literal)){ -                throw error("String length must be a number"); +                throw error(getCurrentToken(),"String length must be a number");              }              if(!((Expression.Literal)length).type.equals("int")){ -                throw error("String length must be a integer");  +                throw error(getCurrentToken(),"String length must be a integer");               }              if((int)((Expression.Literal)length).value.value<1){ -                throw error("String length must be greater then 0");  +                throw error(getCurrentToken(),"String length must be greater then 0");               }              matchOrError(TokenType.RIGHT_PAREN, "Length of string must be defined"); @@ -62,30 +76,16 @@ public class Parser {              Token varName = getPreviousToken();              return new Statement.StringDeclaration(varName,length);          } -         -        return statement(); -    } - -    private Statement statement(){ -        if (matchAndAdvance(TokenType.PRINT)){ -            return printStatement(); -        }else if (matchAndAdvance(TokenType.IF)){ -            Statement statement = ifStatement(); -            return statement; -        }else if (matchAndAdvance(TokenType.DO)){ -            Statement statement = doStatement(); -            return statement; -        } -        return expressionStatement(); +        return null;      }      private BlockStatement blockStatement(){          List<Statement> statements = new ArrayList<>();          while(!matchAndAdvance(TokenType.END)&&!checkToken(TokenType.ELSE)){              if(checkEOF()){ -                throw error("end missing from block"); +                throw error(getCurrentToken(),"end missing from block");              } -            statements.add(declaration()); +            statements.add(statement());          }          return new Statement.BlockStatement(statements);      } @@ -93,11 +93,10 @@ public class Parser {      private Statement printStatement(){          matchOrError(TokenType.STAR, "Syntax, print *, item1, item2...");          List<Expression> exprList = new ArrayList<>(); -        while(!matchAndAdvance(TokenType.ENDPRINT)){ +        while(matchAndAdvance(TokenType.COMMA)){              if(checkEOF()){ -                throw error("Missing close parentheses"); +                throw error(getCurrentToken(),"reached end of file");              } -            matchOrError(TokenType.COMMA, "Print items must be seperated by ,");              Expression expr = expression();              exprList.add(expr);          } @@ -141,9 +140,9 @@ public class Parser {      }      private Statement whileStatement(){ -        matchOrError(TokenType.LEFT_PAREN, " missing '("); +        matchOrError(TokenType.LEFT_PAREN, " missing '(' for do statement condition");          Expression condition = expression(); -        matchOrError(TokenType.RIGHT_PAREN, " missing ')"); +        matchOrError(TokenType.RIGHT_PAREN, " missing ')' for do  condition");          Statement.BlockStatement codeBlock = blockStatement();          matchOrError(TokenType.DO, "Do while statements end with do");          return new Statement.DoWhileStatement(condition,codeBlock); @@ -162,7 +161,7 @@ public class Parser {              if (variable instanceof Expression.Variable){                  return new Expression.AssignmentExpression(((Expression.Variable)variable).name,assignedvalue);              } -            throw error("Incorrect assignment operation"); +            throw error(getCurrentToken(),"Left of assignment must be a variable");          }          return variable;      } @@ -173,9 +172,25 @@ public class Parser {      }      private Expression equality(){ -        Expression createdExpression = comparison(); +        Expression createdExpression = logical();          while (matchAndAdvance(TokenType.EQUALITY)){              Token op = getPreviousToken(); +            Expression right = logical(); +            createdExpression = new Expression.Binary(createdExpression, op, right); +        } +        return createdExpression; +    } + +    private Expression logical(){ +        if(matchAndAdvance(TokenType.NOT)){ +            Token op = getPreviousToken(); +            Expression right = comparison(); +            Expression createdExpression = new Expression.Singular(op, right); +            return createdExpression; +        } +        Expression createdExpression = comparison(); +        while (matchAndAdvance(TokenType.AND)||matchAndAdvance(TokenType.OR)){ +            Token op = getPreviousToken();              Expression right = comparison();              createdExpression = new Expression.Binary(createdExpression, op, right);          } @@ -184,7 +199,7 @@ public class Parser {      private Expression comparison(){          Expression createdExpression = term(); -        while (matchAndAdvance(TokenType.GREATER)||matchAndAdvance(TokenType.LESS)){ +        while (matchAndAdvance(TokenType.GREATER)||matchAndAdvance(TokenType.LESS)||matchAndAdvance(TokenType.GREATER_EQUAL)||matchAndAdvance(TokenType.LESS_EQUAL)){              Token op = getPreviousToken();              Expression right = term();              createdExpression = new Expression.Binary(createdExpression, op, right); @@ -231,14 +246,10 @@ public class Parser {          if (matchAndAdvance(TokenType.LEFT_PAREN)){              Expression expr = expression(); -            if (matchAndAdvance(TokenType.RIGHT_PAREN)){ -                return new Expression.BracketedExpression(expr); -            } -            else{ -                throw error("Expected ')"); -            } +            matchOrError(TokenType.RIGHT_PAREN,"Expected ')'"); +            return new Expression.BracketedExpression(expr);          } -        throw error("Expected Expression"); +        throw error(getCurrentToken(),"Unknown syntax error");      }      private void advanceToken(){ @@ -259,7 +270,7 @@ public class Parser {          if (matchAndAdvance(type)){              return true;          } -        throw error(errorMessage); +        throw error(getCurrentToken(),errorMessage);      }      private boolean checkToken(TokenType type){ @@ -279,8 +290,8 @@ public class Parser {          return tokens.get(currentToken - 1);      } -    private Error error(String message){ -        Language.displayError(message); +    private Error error(Token token, String message){ +        Language.displayError(token ,message);          return new Error();      } diff --git a/src/Compiler/Token.java b/src/Compiler/Token.java index 4608a3d..0af2c34 100644 --- a/src/Compiler/Token.java +++ b/src/Compiler/Token.java @@ -7,12 +7,14 @@ public class Token {      public final TokenType type;      final String text;      final Object value; +    final int line; -    Token(TokenType type, String text, Object value){ +    Token(TokenType type, String text, Object value,int line){          this.type=type;          this.text=text;          this.value=value; +        this.line=line;      } diff --git a/src/Compiler/TokenScanner.java b/src/Compiler/TokenScanner.java index 49500c5..5f55119 100644 --- a/src/Compiler/TokenScanner.java +++ b/src/Compiler/TokenScanner.java @@ -10,6 +10,7 @@ public class TokenScanner {      List<Token> tokens = new ArrayList<>();      private int tokenStart=0;      private int currentLoc=0; +    private int line=0;      //Extract tokens from the source code by reading character by character      List<Token> extractTokens(String sourceCode){ @@ -18,7 +19,7 @@ public class TokenScanner {              tokenStart=currentLoc;              readToken();          } -        tokens.add(new Token(TokenType.EOF, "", null)); +        tokens.add(new Token(TokenType.EOF, "", null,line));          return tokens;      } @@ -28,7 +29,9 @@ public class TokenScanner {          switch(checkChar){              case ' ':break; -            case '\n':break; +            case '\n': +                line++; +                break;              case '\r':break;              case '\t':                  break; @@ -81,12 +84,34 @@ public class TokenScanner {                      currentLoc++;                  }                  if(checkEOF()){ -                    Language.displayError("Strings must end with \""); +                    Language.displayError(line, "Strings must end with a closing \"");                      break;                  }                  currentLoc++;                  createToken(TokenType.STRING, sourceCode.substring(tokenStart, currentLoc+1));                  break; +            case '.': +                if(checkIsAlpha(lookAhead())) +                    while (checkIsAlpha(lookAhead())){ +                        currentLoc++; +                    }  +                    String logical = sourceCode.substring(tokenStart+1, currentLoc+1); +                    if (checkNextChar('.')){ +                        if (logical.equals("and")){ +                            createTokenNull(TokenType.AND); +                            break; +                        } else if(logical.equals("or")){ +                            createTokenNull(TokenType.OR); +                            break; +                        } else if(logical.equals("not")){ +                            createTokenNull(TokenType.NOT); +                            break; +                        } else{ +                            Language.displayError(line, "Expected logical expression"); +                        } +                    } else { +                        Language.displayError(line, "Expected '.' after logical expression"); +                    }              default:                  //Check for numer @@ -122,7 +147,7 @@ public class TokenScanner {                      }                  } else { -                    Language.displayError("Unexpected Character"); +                    Language.displayError(line,"Unexpected Character");                  }          }          currentLoc++; @@ -142,7 +167,7 @@ public class TokenScanner {      //Create token      private void createToken(TokenType type, Object value){          String tokenText = sourceCode.substring(tokenStart, currentLoc+1); -        tokens.add(new Token(type, tokenText, value)); +        tokens.add(new Token(type, tokenText, value, line));      }      //Check if the next char matches a given char diff --git a/src/Compiler/TokenType.java b/src/Compiler/TokenType.java index 82776f9..a82d169 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, +    INT,REAL,PRINT,ENDPRINT,IF,THEN,END,ELSE,LEN,DO,WHILE,AND,OR,NOT,      EOF  } diff --git a/src/Compiler/Translator.java b/src/Compiler/Translator.java index ee43905..c40c6b5 100644 --- a/src/Compiler/Translator.java +++ b/src/Compiler/Translator.java @@ -104,7 +104,7 @@ public class Translator{                  exprType=((Expression.Literal)expr).type;              }              else if (expr instanceof Expression.Variable){ -                exprType=(String)environment.getVariable((((Expression.Variable)expr).name).text); +                exprType=(String)environment.getVariable((((Expression.Variable)expr).name));              }              if (exprType.equals("int")){                  types+="%d"; @@ -153,6 +153,8 @@ public class Translator{          switch(expression.getExpressionType()){              case "binary":                  return evaluateBinaryExpression((Binary)expression); +            case "singular": +                return evaluateSingularExpression((Singular)expression);              case "literal":                  return evaluateLiteralExpression((Literal)expression);              case "bracket": @@ -182,8 +184,27 @@ public class Translator{                  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;          } @@ -195,18 +216,21 @@ public class Translator{      }      private String evaluateBracketedExpression(BracketedExpression expr){ -        return evaluateExpression(expr.expr); +        return "("+evaluateExpression(expr.expr)+")";      }      private void evaluateAssignmentExpression(AssignmentExpression expr){ -        if(expr.value instanceof Expression.Literal){ -            if(((Expression.Literal)expr.value).type.equals("string")){ -                CCode.add("strcpy("+expr.name.text+","+evaluateExpression(expr.value)+");"); +        if(environment.checkVariable(expr.name)){ +            if(expr.value instanceof Expression.Literal){ +                if(((Expression.Literal)expr.value).type.equals("string")){ +                    CCode.add("strcpy("+expr.name.text+","+evaluateExpression(expr.value)+");"); +                }else{ +                    CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";"); +                } +            } +            else{ +                CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";");              } -            CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";"); -        } -        else{ -            CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";");          }      } diff --git a/src/example.txt b/src/example.txt index bbc8973..55236c1 100644 --- a/src/example.txt +++ b/src/example.txt @@ -1,9 +1,12 @@ -int::nfact  int::n -nfact=1 -n=1 -do while(n<10) -nfact=nfact*n -n=n+1 -print*,n," ", nfact endprint -end do
\ No newline at end of file +int::a +int::b +int::temp +a=0 +b=2 +if (a==0.and.b==1) then +print*,"true" +else +print*,"false" +end if + | 
