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/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 ++
 15 files changed, 962 insertions(+)
 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
(limited to 'code/Interpreter2')
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
+      
+      
+      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
+}
-- 
cgit v1.2.3