From 85345d7d80eeb950ab64633ae1cb1f1c5dc87269 Mon Sep 17 00:00:00 2001 From: Alfie Eagleton <67986414+TheAlfanator@users.noreply.github.com> Date: Wed, 3 Nov 2021 16:56:38 +0000 Subject: New Project Working + Report --- code/.idea/.name | 1 + code/.idea/misc.xml | 6 + code/.idea/modules.xml | 8 + code/.idea/vcs.xml | 6 + code/.idea/workspace.xml | 33 ++++ code/Interpreter/.idea/misc.xml | 6 + code/Interpreter/.idea/modules.xml | 8 + code/Interpreter/.idea/uiDesigner.xml | 124 ++++++++++++++ code/Interpreter/.idea/vcs.xml | 6 + code/Interpreter/.idea/workspace.xml | 100 ++++++++++++ code/Interpreter/Interpreter/.idea/misc.xml | 6 + code/Interpreter/Interpreter/.idea/modules.xml | 8 + code/Interpreter/Interpreter/.idea/uiDesigner.xml | 124 ++++++++++++++ code/Interpreter/Interpreter/.idea/vcs.xml | 6 + code/Interpreter/Interpreter/.idea/workspace.xml | 34 ++++ .../Interpreter/Interpreter/Interpreter.iml | 11 ++ code/Interpreter2.iml | 11 ++ code/Interpreter2/.idea/misc.xml | 6 + code/Interpreter2/.idea/modules.xml | 8 + code/Interpreter2/.idea/uiDesigner.xml | 124 ++++++++++++++ code/Interpreter2/.idea/vcs.xml | 6 + code/Interpreter2/.idea/workspace.xml | 52 ++++++ code/Interpreter2/Interpreter2.iml | 11 ++ code/Interpreter2/src/Interpreter/Environment.java | 30 ++++ code/Interpreter2/src/Interpreter/Expression.java | 84 ++++++++++ code/Interpreter2/src/Interpreter/Interpreter.java | 131 +++++++++++++++ code/Interpreter2/src/Interpreter/Language.java | 63 ++++++++ code/Interpreter2/src/Interpreter/Parser.java | 179 +++++++++++++++++++++ code/Interpreter2/src/Interpreter/Statement.java | 49 ++++++ code/Interpreter2/src/Interpreter/Token.java | 23 +++ .../Interpreter2/src/Interpreter/TokenScanner.java | 179 +++++++++++++++++++++ code/Interpreter2/src/Interpreter/TokenType.java | 17 ++ report/esoteric_project_report.pdf | Bin 189988 -> 211738 bytes report/esoteric_project_report.tex | 30 ++++ 34 files changed, 1490 insertions(+) create mode 100644 code/.idea/.name create mode 100644 code/.idea/misc.xml create mode 100644 code/.idea/modules.xml create mode 100644 code/.idea/vcs.xml create mode 100644 code/.idea/workspace.xml create mode 100644 code/Interpreter/.idea/misc.xml create mode 100644 code/Interpreter/.idea/modules.xml create mode 100644 code/Interpreter/.idea/uiDesigner.xml create mode 100644 code/Interpreter/.idea/vcs.xml create mode 100644 code/Interpreter/.idea/workspace.xml create mode 100644 code/Interpreter/Interpreter/.idea/misc.xml create mode 100644 code/Interpreter/Interpreter/.idea/modules.xml create mode 100644 code/Interpreter/Interpreter/.idea/uiDesigner.xml create mode 100644 code/Interpreter/Interpreter/.idea/vcs.xml create mode 100644 code/Interpreter/Interpreter/.idea/workspace.xml create mode 100644 code/Interpreter/Interpreter/Interpreter/Interpreter.iml create mode 100644 code/Interpreter2.iml create mode 100644 code/Interpreter2/.idea/misc.xml create mode 100644 code/Interpreter2/.idea/modules.xml create mode 100644 code/Interpreter2/.idea/uiDesigner.xml create mode 100644 code/Interpreter2/.idea/vcs.xml create mode 100644 code/Interpreter2/.idea/workspace.xml create mode 100644 code/Interpreter2/Interpreter2.iml create mode 100644 code/Interpreter2/src/Interpreter/Environment.java create mode 100644 code/Interpreter2/src/Interpreter/Expression.java create mode 100644 code/Interpreter2/src/Interpreter/Interpreter.java create mode 100644 code/Interpreter2/src/Interpreter/Language.java create mode 100644 code/Interpreter2/src/Interpreter/Parser.java create mode 100644 code/Interpreter2/src/Interpreter/Statement.java create mode 100644 code/Interpreter2/src/Interpreter/Token.java create mode 100644 code/Interpreter2/src/Interpreter/TokenScanner.java create mode 100644 code/Interpreter2/src/Interpreter/TokenType.java diff --git a/code/.idea/.name b/code/.idea/.name new file mode 100644 index 0000000..5c3a976 --- /dev/null +++ b/code/.idea/.name @@ -0,0 +1 @@ +Interpreter2 \ No newline at end of file diff --git a/code/.idea/misc.xml b/code/.idea/misc.xml new file mode 100644 index 0000000..b1001d2 --- /dev/null +++ b/code/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/.idea/modules.xml b/code/.idea/modules.xml new file mode 100644 index 0000000..944dd7c --- /dev/null +++ b/code/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/.idea/vcs.xml b/code/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/code/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/.idea/workspace.xml b/code/.idea/workspace.xml new file mode 100644 index 0000000..7952f3a --- /dev/null +++ b/code/.idea/workspace.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + 1635958020139 + + + + \ No newline at end of file diff --git a/code/Interpreter/.idea/misc.xml b/code/Interpreter/.idea/misc.xml new file mode 100644 index 0000000..06e4882 --- /dev/null +++ b/code/Interpreter/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter/.idea/modules.xml b/code/Interpreter/.idea/modules.xml new file mode 100644 index 0000000..b0b7e77 --- /dev/null +++ b/code/Interpreter/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter/.idea/uiDesigner.xml b/code/Interpreter/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/code/Interpreter/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter/.idea/vcs.xml b/code/Interpreter/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/code/Interpreter/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter/.idea/workspace.xml b/code/Interpreter/.idea/workspace.xml new file mode 100644 index 0000000..bd535b9 --- /dev/null +++ b/code/Interpreter/.idea/workspace.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1635957051799 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/.idea/misc.xml b/code/Interpreter/Interpreter/.idea/misc.xml new file mode 100644 index 0000000..40674af --- /dev/null +++ b/code/Interpreter/Interpreter/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/.idea/modules.xml b/code/Interpreter/Interpreter/.idea/modules.xml new file mode 100644 index 0000000..bbaf613 --- /dev/null +++ b/code/Interpreter/Interpreter/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/.idea/uiDesigner.xml b/code/Interpreter/Interpreter/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/code/Interpreter/Interpreter/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/.idea/vcs.xml b/code/Interpreter/Interpreter/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/code/Interpreter/Interpreter/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/.idea/workspace.xml b/code/Interpreter/Interpreter/.idea/workspace.xml new file mode 100644 index 0000000..c4f325d --- /dev/null +++ b/code/Interpreter/Interpreter/.idea/workspace.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + 1635957051799 + + + + \ No newline at end of file diff --git a/code/Interpreter/Interpreter/Interpreter/Interpreter.iml b/code/Interpreter/Interpreter/Interpreter/Interpreter.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/code/Interpreter/Interpreter/Interpreter/Interpreter.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2.iml b/code/Interpreter2.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/code/Interpreter2.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/.idea/misc.xml b/code/Interpreter2/.idea/misc.xml new file mode 100644 index 0000000..b1001d2 --- /dev/null +++ b/code/Interpreter2/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/.idea/modules.xml b/code/Interpreter2/.idea/modules.xml new file mode 100644 index 0000000..944dd7c --- /dev/null +++ b/code/Interpreter2/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/.idea/uiDesigner.xml b/code/Interpreter2/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/code/Interpreter2/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/.idea/vcs.xml b/code/Interpreter2/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/code/Interpreter2/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/.idea/workspace.xml b/code/Interpreter2/.idea/workspace.xml new file mode 100644 index 0000000..4198910 --- /dev/null +++ b/code/Interpreter2/.idea/workspace.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + 1635958069096 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/Interpreter2.iml b/code/Interpreter2/Interpreter2.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/code/Interpreter2/Interpreter2.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/code/Interpreter2/src/Interpreter/Environment.java b/code/Interpreter2/src/Interpreter/Environment.java new file mode 100644 index 0000000..d191bde --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Environment.java @@ -0,0 +1,30 @@ +package Interpreter; + +import java.util.HashMap; +import java.util.Map; + +public class Environment { + private final Map variableMap = new HashMap<>(); + + //Maybe check if variable is already defined? + public void defineVariable(String name,Object value){ + variableMap.put(name, value); + } + + public Object getVariable(String name){ + if(variableMap.containsKey(name)){ + return variableMap.get(name); + } + Language.displayError("Undefined Variable"); + throw new Error(); + } + + public void assignVariable(String name,Object value){ + if(variableMap.containsKey(name)){ + variableMap.put(name, value); + return; + } + Language.displayError("Variable undefined"); + throw new Error(); + } +} diff --git a/code/Interpreter2/src/Interpreter/Expression.java b/code/Interpreter2/src/Interpreter/Expression.java new file mode 100644 index 0000000..85ade48 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Expression.java @@ -0,0 +1,84 @@ +package Interpreter; + +abstract class Expression { + static class Binary extends Expression{ + + final Expression left; + final Expression right; + final Token op; + + Binary(Expression left, Token op, Expression right){ + this.left=left; + this.op=op; + this.right = right; + } + + @Override + public String getExpressionType() { + return "binary"; + } + + } + + static class Literal extends Expression{ + final Token value; + + Literal(Token value){ + this.value=value; + } + + + @Override + public String getExpressionType() { + return "literal"; + } + + } + + static class BracketedExpression extends Expression{ + final Expression expr; + + BracketedExpression(Expression expr){ + this.expr=expr; + } + + @Override + public String getExpressionType() { + return "bracket"; + } + + + } + + static class AssignmentExpression extends Expression{ + final Token name; + final Expression value; + + AssignmentExpression(Token name,Expression value){ + this.name=name; + this.value=value; + } + + + @Override + public String getExpressionType() { + return "assign"; + } + + } + + static class Variable extends Expression{ + + Variable(Token name){ + this.name=name; + + } + @Override + public String getExpressionType() { + return "var"; + } + final Token name; + + } + public abstract String getExpressionType(); +} diff --git a/code/Interpreter2/src/Interpreter/Interpreter.java b/code/Interpreter2/src/Interpreter/Interpreter.java new file mode 100644 index 0000000..65cdeb4 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Interpreter.java @@ -0,0 +1,131 @@ +package Interpreter; + +import java.util.List; + +import Interpreter.Expression.*; +import Interpreter.Statement.ExpressionStatement; +import Interpreter.Statement.PrintStatement; +import Interpreter.Statement.VariableDeclaration; + +public class Interpreter { + + private Environment environment = new Environment(); + + void interpret(List statements){ + try{ + for (Statement statement: statements){ + evaluateStatement(statement); + } + } catch (Error e){ + + } + } + + private Object evaluateStatement(Statement statement){ + switch(statement.getStatmentType()){ + case "exprStmt": + return evalExpressionStatement((ExpressionStatement)statement); + case "vardec": + return evalVariableDeclaration((VariableDeclaration)statement); + case "print": + return evalPrintStatement((PrintStatement)statement); + default: + return null; + } + } + private Object evalExpressionStatement(ExpressionStatement stmt){ + return evaluateExpression(stmt.expr); + } + + private Object evalVariableDeclaration(VariableDeclaration vardec){ + environment.defineVariable(vardec.name.text, null); + return null; + } + + private Object evalPrintStatement(PrintStatement print){ + System.out.println(evaluateExpression(print.expr)); + return null; + } + + private Object evaluateExpression(Expression expression){ + switch(expression.getExpressionType()){ + case "binary": + return evaluateBinaryExpression((Binary)expression); + case "literal": + return evaluateLiteralExpression((Literal)expression); + case "bracket": + return evaluateBracketedExpression((BracketedExpression)expression); + case "assign": + return evaluateAssignmentExpression((AssignmentExpression)expression); + case "var": + return evaluateVariableExpression((Variable)expression); + default: + return null; + } + } + + private Object evaluateBinaryExpression(Binary expr){ + Object leftEval = evaluateExpression(expr.left); + Object rightEval = evaluateExpression(expr.right); + switch (expr.op.type){ + case PLUS: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval + (double)rightEval; + } + case STAR: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval * (double)rightEval; + } + case MINUS: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval - (double)rightEval; + } + case SLASH: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval / (double)rightEval; + } + + case GREATER: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval > (double)rightEval; + } + case LESS: + if (checkOperandsNum(leftEval, leftEval)){ + return (double)leftEval < (double)rightEval; + } + + case EQUALITY: + return leftEval.equals(rightEval); + default: + break; + } + return null; + } + + private Object evaluateLiteralExpression(Literal expr){ + return expr.value.value; + } + + private Object evaluateBracketedExpression(BracketedExpression expr){ + return evaluateExpression(expr.expr); + } + + private Object evaluateAssignmentExpression(AssignmentExpression expr){ + Object assignedValue = evaluateExpression(expr.value); + environment.assignVariable(expr.name.text, assignedValue); + return null; + } + + private Object evaluateVariableExpression(Variable expr){ + return environment.getVariable(expr.name.text); + } + + private boolean checkOperandsNum(Object left, Object right){ + if (left instanceof Double && right instanceof Double){ + return true; + } else { + Language.displayError("Operands must be numbers"); + throw new Error(); + } + } +} diff --git a/code/Interpreter2/src/Interpreter/Language.java b/code/Interpreter2/src/Interpreter/Language.java new file mode 100644 index 0000000..80aa1e3 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Language.java @@ -0,0 +1,63 @@ +package Interpreter; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.Scanner; + +//Base class for the interpreter +public class Language { + static boolean hadError = false; + public static void main(String[] args){ + + //Allow users to input a single line of code + //Still needs some work to re-ask for input after each line + if (args.length < 1){ + Scanner input = new Scanner(System.in); + String sourceCode = "1"; + while (sourceCode!=""){ + System.out.print("Code: "); + sourceCode = input.nextLine(); + runInterpreter(sourceCode); + hadError=false; + } + input.close(); + + //Allow users to provide a path to a file as an argument + } else if (args.length==1){ + try { + String sourcecode = Files.readString(Paths.get(args[0])); //Maybe should set charset here + runInterpreter(sourcecode); + } catch (IOException exception){ + System.out.println("File not found"); + } + + } else { + System.out.println("Error, argument should be file path"); + System.exit(64); + } + } + + //Extract and print each token + private static void runInterpreter(String sourceCode){ + TokenScanner scanner = new TokenScanner(); + List tokens = scanner.extractTokens(sourceCode); + //for (Token token : tokens) { + // System.out.println(token); + //} + if (hadError) return; + //Parse into AST + Parser parser = new Parser(tokens); + List ast = parser.parse(); + if (hadError) return; + Interpreter interpreter = new Interpreter(); + interpreter.interpret(ast); + } + + static void displayError(String message){ + hadError=true; + System.out.println("An error was encountered"); + System.out.println(message); + } +} diff --git a/code/Interpreter2/src/Interpreter/Parser.java b/code/Interpreter2/src/Interpreter/Parser.java new file mode 100644 index 0000000..6b55299 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Parser.java @@ -0,0 +1,179 @@ +package Interpreter; + +import java.util.ArrayList; +import java.util.List; + +public class Parser { + private final List tokens; + private int currentToken = 0; + + Parser(List tokens){ + this.tokens=tokens; + } + + List parse(){ + List statements = new ArrayList<>(); + while (!checkEOF()){ + statements.add(declaration()); + } + return statements; + + } + + private Statement declaration(){ + try{ + if (matchAndAdvance(TokenType.VAR)){ + if (matchOrError(TokenType.DEFINE, ":: Required for variable definition")){ + if (matchOrError(TokenType.IDENTIFIER,"Expected variable name.")){ + Token varName = getPreviousToken(); + return new Statement.VariableDeclaration(varName); + } + } + } + return statement(); + } catch (Error e){ + currentToken++; + return null; + } + } + + private Statement statement(){ + if (matchAndAdvance(TokenType.PRINT)){ + Expression expression = expression(); + return new Statement.PrintStatement(expression); + } + return expressionStatement(); + } + + + + private Statement expressionStatement(){ + Expression expression = assignment(); + return new Statement.ExpressionStatement(expression); + } + + private Expression assignment(){ + 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("Incorrect assignment operation"); + } + return variable; + } + + private Expression expression(){ + Expression createdExpression = equality(); + return createdExpression; + } + + private Expression equality(){ + Expression createdExpression = comparison(); + while (matchAndAdvance(TokenType.EQUALITY)){ + Token op = getPreviousToken(); + Expression right = comparison(); + createdExpression = new Expression.Binary(createdExpression, op, right); + } + return createdExpression; + } + + private Expression comparison(){ + Expression createdExpression = term(); + while (matchAndAdvance(TokenType.GREATER)||matchAndAdvance(TokenType.LESS)){ + Token op = getPreviousToken(); + Expression right = term(); + createdExpression = new Expression.Binary(createdExpression, op, right); + } + return createdExpression; + } + + private Expression term(){ + Expression createdExpression = factor(); + while (matchAndAdvance(TokenType.PLUS)||matchAndAdvance(TokenType.MINUS)){ + Token op = getPreviousToken(); + Expression right = factor(); + createdExpression = new Expression.Binary(createdExpression, op, right); + } + return createdExpression; + } + + private Expression factor(){ + Expression createdExpression = primary(); + while (matchAndAdvance(TokenType.STAR)||matchAndAdvance(TokenType.SLASH)){ + Token op = getPreviousToken(); + Expression right = primary(); + createdExpression = new Expression.Binary(createdExpression, op, right); + } + return createdExpression; + } + + private Expression primary(){ + if (matchAndAdvance(TokenType.NUMBER)){ + return new Expression.Literal(getPreviousToken()); + } + + if (matchAndAdvance(TokenType.IDENTIFIER)) { + + return new Expression.Variable(getPreviousToken()); + } + + if (matchAndAdvance(TokenType.LEFT_PAREN)){ + Expression expr = expression(); + if (matchAndAdvance(TokenType.RIGHT_PAREN)){ + return new Expression.BracketedExpression(expr); + } + else{ + throw error("Expected ')"); + } + } + throw error("Expected Expression"); + } + + private void advanceToken(){ + if (!checkEOF()) { + currentToken++; + }; + } + + private boolean matchAndAdvance(TokenType type){ + if (checkToken(type)) { + advanceToken(); + return true; + } + return false; + } + + private boolean matchOrError(TokenType type,String errorMessage){ + if (matchAndAdvance(type)){ + return true; + } + throw error(errorMessage); + } + + private boolean checkToken(TokenType type){ + if (checkEOF()) return false; + return getCurrentToken().type == type; + } + + private boolean checkEOF(){ + return tokens.get(currentToken).type==TokenType.EOF; + } + + private Token getCurrentToken(){ + return tokens.get(currentToken); + } + + private Token getPreviousToken(){ + return tokens.get(currentToken - 1); + } + + private Error error(String message){ + Language.displayError(message); + return new Error(); + } + + +} diff --git a/code/Interpreter2/src/Interpreter/Statement.java b/code/Interpreter2/src/Interpreter/Statement.java new file mode 100644 index 0000000..5a9aef7 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Statement.java @@ -0,0 +1,49 @@ +package Interpreter; + +abstract class Statement { + + static class ExpressionStatement extends Statement{ + ExpressionStatement(Expression expr){ + this.expr = expr; + } + + + final Expression expr; + + @Override + public String getStatmentType() { + return "exprStmt"; + } + } + + + static class VariableDeclaration extends Statement{ + VariableDeclaration(Token name){ + this.name=name; + } + + + final Token name; + + @Override + public String getStatmentType() { + return "vardec"; + } + + } + + static class PrintStatement extends Statement{ + PrintStatement(Expression expr){ + this.expr=expr; + } + final Expression expr; + + @Override + public String getStatmentType() { + return "print"; + } + } + + + public abstract String getStatmentType(); +} diff --git a/code/Interpreter2/src/Interpreter/Token.java b/code/Interpreter2/src/Interpreter/Token.java new file mode 100644 index 0000000..0129b78 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/Token.java @@ -0,0 +1,23 @@ +package Interpreter; + +public class Token { + + + //Stores the token type, the actual text and the runtime object + public final TokenType type; + final String text; + final Object value; + + + Token(TokenType type, String text, Object value){ + this.type=type; + this.text=text; + this.value=value; + + } + + @Override + public String toString() { + return type + " " + text + " " + value; + } +} diff --git a/code/Interpreter2/src/Interpreter/TokenScanner.java b/code/Interpreter2/src/Interpreter/TokenScanner.java new file mode 100644 index 0000000..c9249a4 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/TokenScanner.java @@ -0,0 +1,179 @@ +package Interpreter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TokenScanner { + private String sourceCode; + List tokens = new ArrayList<>(); + private int tokenStart=0; + private int currentLoc=0; + + //Extract tokens from the source code by reading character by character + List extractTokens(String sourceCode){ + this.sourceCode=sourceCode; + while (!checkEOF()){ + tokenStart=currentLoc; + readToken(); + } + tokens.add(new Token(TokenType.EOF, "", null)); + return tokens; + } + + //Extract a single token + private void readToken(){ + char checkChar = sourceCode.charAt(currentLoc); + switch(checkChar){ + + case ' ':break; + case '\n':break; + case '\r':break; + case '\t': + break; + + case '(': createTokenNull(TokenType.LEFT_PAREN); break; + case ')': createTokenNull(TokenType.RIGHT_PAREN); break; + case '+': createTokenNull(TokenType.PLUS); break; + case '-': createTokenNull(TokenType.MINUS); break; + case '*': createTokenNull(TokenType.STAR); break; + case '/': createTokenNull(TokenType.SLASH); break; + case ';': createTokenNull(TokenType.SEMI_COLON); break; + + //Some tokens are multiple characters long (==, <=) etc + //so need to check next char as well + case '=': + if (checkNextChar('=')){ + createTokenNull(TokenType.EQUALITY); + break; + } else { + createTokenNull(TokenType.EQUALS); + break; + } + case ':': + if (checkNextChar(':')){ + createTokenNull(TokenType.DEFINE); + break; + } else { + createTokenNull(TokenType.COLON); + break; + } + case '<': + if (checkNextChar('=')){ + createTokenNull(TokenType.LESS_EQUAL); + break; + } else { + createTokenNull(TokenType.LESS); + break; + } + case '>': + if (checkNextChar('=')){ + createTokenNull(TokenType.GREATER_EQUAL); + break; + } else { + createTokenNull(TokenType.GREATER); + break; + } + default: + + //Check for numer + if (checkIsDigit(checkChar)){ + while (checkIsDigit(lookAhead())){ + currentLoc++; + } + //Check if number contains a decimal point + if (lookAhead()=='.' && checkIsDigit(lookTwoAhead())){ + currentLoc++; + while (checkIsDigit(lookAhead())){ + currentLoc++; + } + } + createToken(TokenType.NUMBER, Double.parseDouble(sourceCode.substring(tokenStart, currentLoc+1))); + } + else if (checkIsAlpha(checkChar)){ + while (checkIsAlpha(lookAhead())){ + currentLoc++; + } + String text = sourceCode.substring(tokenStart, currentLoc+1); + TokenType type = keywords.get(text); + if(type == null){ + createToken(TokenType.IDENTIFIER, text); + } else{ + createToken(type, text); + } + + } else { + Language.displayError("Unexpected Character"); + } + } + currentLoc++; + + } + + //Test for end of file + private boolean checkEOF(){ + return currentLoc>=sourceCode.length(); + } + + //Create a token without a value + private void createTokenNull(TokenType type){ + createToken(type, null); + } + + //Create token + private void createToken(TokenType type, Object value){ + String tokenText = sourceCode.substring(tokenStart, currentLoc+1); + tokens.add(new Token(type, tokenText, value)); + } + + //Check if the next char matches a given char + private boolean checkNextChar(char matchChar){ + if (checkEOF()){ + return false; + } + if (sourceCode.charAt(currentLoc+1)==matchChar){ + currentLoc++; + return true; + } + return false; + } + + //Look at the next char in the source code + private char lookAhead(){ + if (currentLoc+1>=sourceCode.length()){ + return ' '; + + } else { + return sourceCode.charAt(currentLoc+1); + } + } + + //Look 2 chars ahead in the source code + private char lookTwoAhead(){ + if (currentLoc+2>=sourceCode.length()){ + return ' '; + + } else { + return sourceCode.charAt(currentLoc+2); + } + } + + //Check if a given char is a digit + private boolean checkIsDigit(char checkChar){ + return checkChar>='0' && checkChar<='9'; + } + + private boolean checkIsAlpha(char checkChar){ + return ('a'<=checkChar && checkChar<='z')|| + ('A'<=checkChar && checkChar<='Z'); + } + + private static final Map keywords; + + static { + keywords = new HashMap<>(); + keywords.put("var", TokenType.VAR); + keywords.put("print", TokenType.PRINT); + } +} diff --git a/code/Interpreter2/src/Interpreter/TokenType.java b/code/Interpreter2/src/Interpreter/TokenType.java new file mode 100644 index 0000000..756fab6 --- /dev/null +++ b/code/Interpreter2/src/Interpreter/TokenType.java @@ -0,0 +1,17 @@ +package Interpreter; + +public enum TokenType { + EQUALS, LEFT_PAREN, RIGHT_PAREN, + PLUS, MINUS, SLASH, STAR, SEMI_COLON, + COLON, + + EQUALITY, GREATER, LESS, + GREATER_EQUAL, LESS_EQUAL, + DEFINE, + + NUMBER,IDENTIFIER, + + VAR,PRINT, + + EOF +} diff --git a/report/esoteric_project_report.pdf b/report/esoteric_project_report.pdf index b241efe..1261091 100644 Binary files a/report/esoteric_project_report.pdf and b/report/esoteric_project_report.pdf differ diff --git a/report/esoteric_project_report.tex b/report/esoteric_project_report.tex index 788226a..a6f0079 100644 --- a/report/esoteric_project_report.tex +++ b/report/esoteric_project_report.tex @@ -208,6 +208,36 @@ asdf \end{center} \end{table} +\clearpage +\chapter{BNF form} + +\begin{table}[h!] + \begin{center} + + \begin{tabular}{|l|r|} + \hline + \textbf{Abbreviation} & \textbf{Term}\\ + \hline + $<$statement$>$ ::= & $<$assignment$>$ $|$ \\ + & IF $|$ \\ + & WHILE \\ + \hline + IF ::= & IF $<$expression$>$ THEN $<$statement$>$ END IF $|$\\ + & IF $<$expression$>$ THEN $<$statement$>$ ELSE $<$statement$>$ END IF \\ + \hline + DO ::= & DO $<$expression$>$ $<$expression$>$ = $<$expression$>$, \\ + & $<$expression$>$ $<$statement$>$ continue $|$\\ + & DO $<$expression$>$ $<$expression$>$ = $<$expression$>$, \\ + & $<$expression$>$, $<$expression$>$ $<$statement$>$ continue \\ + \hline + + + \end{tabular} + \label{tab:table1} + \caption{Grammar table for Fortran} + \end{center} +\end{table} + \chapter{Methodology}\label{MethLab} Describe here various methods that will be used in your project. Use different sections for distinctly different subjects and use subsections for specific details on the same subject. Only use subsubsections or paragraphs (which are not numbered) if you believe this is really necessary. Since implementation will happen in sprints, this section may need several updates with parts being added and deleted across the project. -- cgit v1.2.3