diff options
author | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-10-09 23:12:42 +0100 |
---|---|---|
committer | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-10-09 23:12:42 +0100 |
commit | cb29252f1e0d29d555fb232f39d343930fc76105 (patch) | |
tree | 8b0d62d941475c319a7bceb7939334a70be5bc30 /code | |
parent | d9e2cc94e10fb5f9d870a0f3e66afd1ad66c470c (diff) | |
download | esotericFORTRAN-cb29252f1e0d29d555fb232f39d343930fc76105.tar.gz esotericFORTRAN-cb29252f1e0d29d555fb232f39d343930fc76105.zip |
Added basic lexical analysis
Diffstat (limited to 'code')
-rw-r--r-- | code/Interpreter/Interpreter.java | 44 | ||||
-rw-r--r-- | code/Interpreter/Token.java | 23 | ||||
-rw-r--r-- | code/Interpreter/TokenScanner.java | 132 | ||||
-rw-r--r-- | code/Interpreter/TokenType.java | 11 |
4 files changed, 210 insertions, 0 deletions
diff --git a/code/Interpreter/Interpreter.java b/code/Interpreter/Interpreter.java new file mode 100644 index 0000000..17f2ccf --- /dev/null +++ b/code/Interpreter/Interpreter.java @@ -0,0 +1,44 @@ +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 Interpreter { + 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); + System.out.print("Code: "); + String sourceCode = input.nextLine(); + runInterpreter(sourceCode); + 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); + } + } + + private static void runInterpreter(String sourceCode){ + TokenScanner scanner = new TokenScanner(); + List<Token> tokens = scanner.extractTokens(sourceCode); + for (Token token : tokens) { + System.out.println(token); + } + } +} diff --git a/code/Interpreter/Token.java b/code/Interpreter/Token.java new file mode 100644 index 0000000..b1cf542 --- /dev/null +++ b/code/Interpreter/Token.java @@ -0,0 +1,23 @@ +package Interpreter; + +public class Token { + + + //Stores the token type, the actual text and the runtime object + 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/Interpreter/TokenScanner.java b/code/Interpreter/TokenScanner.java new file mode 100644 index 0000000..87f1e4b --- /dev/null +++ b/code/Interpreter/TokenScanner.java @@ -0,0 +1,132 @@ +package Interpreter; + +import java.util.ArrayList; +import java.util.List; + +public class TokenScanner { + private String sourceCode; + List<Token> tokens = new ArrayList<>(); + private int tokenStart=0; + private int currentLoc=0; + + //Extract tokens from the source code by reading character by character + List<Token> extractTokens(String sourceCode){ + this.sourceCode=sourceCode; + while (!checkEOF()){ + tokenStart=currentLoc; + readToken(); + } + return tokens; + } + + //Extract a single token + private void readToken(){ + char checkChar = sourceCode.charAt(currentLoc); + switch(checkChar){ + 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; + + //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.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))); + } + } + 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'; + } +} diff --git a/code/Interpreter/TokenType.java b/code/Interpreter/TokenType.java new file mode 100644 index 0000000..26ffb15 --- /dev/null +++ b/code/Interpreter/TokenType.java @@ -0,0 +1,11 @@ +package Interpreter; + +enum TokenType { + EQUALS, LEFT_PAREN, RIGHT_PAREN, + PLUS, MINUS, SLASH, STAR, + + EQUALITY, GREATER, LESS, + GREATER_EQUAL, LESS_EQUAL, + + NUMBER +} |