summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-11-22 16:30:45 +0000
committerAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-11-22 16:30:45 +0000
commit8e368b67de60442c483bd9def7036e52562ccc81 (patch)
tree947d775285ad2df464177df8ec9e1d63e99cae0d
parentab5584190b83a8cda9cbb3469ce841dbaa3aa38a (diff)
downloadesotericFORTRAN-8e368b67de60442c483bd9def7036e52562ccc81.tar.gz
esotericFORTRAN-8e368b67de60442c483bd9def7036e52562ccc81.zip
Improved error handing and added logical statements
-rw-r--r--report/esoteric_project_report.pdfbin297672 -> 198596 bytes
-rw-r--r--report/esoteric_project_report.tex22
-rw-r--r--src/Compiler/Environment.java19
-rw-r--r--src/Compiler/ExecuteC.java2
-rw-r--r--src/Compiler/Expression.java17
-rw-r--r--src/Compiler/Language.java12
-rw-r--r--src/Compiler/Parser.java89
-rw-r--r--src/Compiler/Token.java4
-rw-r--r--src/Compiler/TokenScanner.java35
-rw-r--r--src/Compiler/TokenType.java2
-rw-r--r--src/Compiler/Translator.java49
-rw-r--r--src/example.txt19
12 files changed, 184 insertions, 86 deletions
diff --git a/report/esoteric_project_report.pdf b/report/esoteric_project_report.pdf
index bc2872e..445fde8 100644
--- a/report/esoteric_project_report.pdf
+++ b/report/esoteric_project_report.pdf
Binary files differ
diff --git a/report/esoteric_project_report.tex b/report/esoteric_project_report.tex
index d4b2b78..3da6800 100644
--- a/report/esoteric_project_report.tex
+++ b/report/esoteric_project_report.tex
@@ -173,16 +173,28 @@ asdf
& $<$expr-Statement$>$ $|$\\
& $<$print-Statement$>$ $|$ \\
& $<$if-Statement$>$ \\
+ & $<$do-Statement$>$ \\
+ & $<$do-while-Statement$>$ \\
+ \hline
+ $<$block$>$::=& $<$statement$>$* "end"\\
\hline
$<$declaration$>$ ::= & "character (len = "$<$number$>$")::"$<$identifier$>$ $|$ \\
& "int::"$<$identifier$>$ \\
& "real::"$<$identifier$>$ \\
\hline
- $<$print-Statement$>$ ::= & "print *" (","$<$expression$>$)* "endprint" \\
+ $<$print-Statement$>$ ::= & "print *" (","$<$expression$>$)* \\
+ \hline
+ $<$if-Statement$>$ ::= & "if ("$<$expression$>$") then" $<$block$>$ \\
+ & ("else" $<$block$>$)?\\
+ & if"\\
+ \hline
+ $<$do-Statement$>$ ::= & "do" $<$identifier$>$ "=" $<$number$>$","$<$number$>$(","$<$number$>$)?\\
+ &$<$block$>$ \\
+ & "do"\\
\hline
- $<$if-Statement$>$ ::= & "if ("$<$expression$>$") then" $<$statement$>$* \\
- & ("else" $<$statement$>$*)?\\
- & "endif"\\
+ $<$do-while-Statement$>$ ::= & "do while ("$<$expression$>$")"\\
+ & $<$block$>$ \\
+ & "do"\\
\hline
$<$expr-statement$>$ ::= & $<$expression$>$\\
\hline
@@ -194,7 +206,7 @@ asdf
$<$equality$>$ ::= & $<$comparison$>$"=="$<$comparison$>$$|$\\
& $<$comparison$>$$|$\\
\hline
- $<$comparison$>$ ::= & $<$term$>$("$>$"$|$"$<$")$<$term$>$$|$\\
+ $<$comparison$>$ ::= & $<$term$>$("$>$"$|$"$<$"$|$"$>=$"$|$"$>=$")$<$term$>$$|$\\
& $<$term$>$$|$\\
\hline
$<$term$>$ ::= & $<$factor$>$("+"$|$"-")$<$factor$>$$|$\\
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 035813a..d579c82 100644
--- a/src/Compiler/ExecuteC.java
+++ b/src/Compiler/ExecuteC.java
@@ -18,7 +18,7 @@ public class ExecuteC {
System.out.println(output);
}
else{
- Language.displayError("Runtime Error");
+ Language.displayError(0,"Runtime Error");
}
}
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 bb7e235..9d2f3f0 100644
--- a/src/Compiler/Language.java
+++ b/src/Compiler/Language.java
@@ -63,11 +63,17 @@ public class Language {
cExecutor.compileAndExecuteC(code, outName);
}
-
//Basic error reporting
- static void displayError(String message){
+ static void displayError(int line,String message){
+ hadError=true;
+ 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");
+ 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 50430f2..e259c70 100644
--- a/src/Compiler/Translator.java
+++ b/src/Compiler/Translator.java
@@ -26,10 +26,9 @@ public class Translator{
}
CCode.add("}");
- for(String t:CCode){
- System.out.println(t);
- }
- System.out.println("");
+ //for(String t:CCode){
+ // System.out.println(t);
+ //}
return CCode;
}
@@ -102,7 +101,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";
@@ -151,6 +150,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":
@@ -180,8 +181,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;
}
@@ -193,18 +213,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
+