summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-12-08 04:37:18 +0000
committerAidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>2021-12-08 04:37:18 +0000
commit0d32b01fde73224469b8bb5971ebdaacd9bfa32c (patch)
treea6ff8bd4dbbf144cb112d24785b525ce2b59fb8a /src
parent5c4d41c63af3ef064090336a14efe91931051e7e (diff)
downloadesotericFORTRAN-0d32b01fde73224469b8bb5971ebdaacd9bfa32c.tar.gz
esotericFORTRAN-0d32b01fde73224469b8bb5971ebdaacd9bfa32c.zip
Fixed bug with function return and added recursive example
Diffstat (limited to 'src')
-rw-r--r--src/.vscode/launch.json2
-rw-r--r--src/Compiler/Parser.java72
-rw-r--r--src/examples/recursive.ft14
3 files changed, 48 insertions, 40 deletions
diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json
index bc86f64..1008b15 100644
--- a/src/.vscode/launch.json
+++ b/src/.vscode/launch.json
@@ -23,7 +23,7 @@
"request": "launch",
"mainClass": "Compiler.Language",
"projectName": "src_1da2a030",
- "args": "examples/example.ft -c -e"
+ "args": "examples/recursive.ft -c -e"
}
]
} \ No newline at end of file
diff --git a/src/Compiler/Parser.java b/src/Compiler/Parser.java
index c7b0165..0ac91d6 100644
--- a/src/Compiler/Parser.java
+++ b/src/Compiler/Parser.java
@@ -13,6 +13,7 @@ public class Parser {
private int currentToken = 0;
private final Map<String,String> definedVars = new HashMap<>();
List<Statement> statements = new ArrayList<>();
+ private boolean foundReturn;
/**
* Constructor of a parser object
@@ -48,7 +49,7 @@ public class Parser {
if(matchAndAdvance(TokenType.PROGRAM)){
matchOrError(TokenType.IDENTIFIER, "Expected program name");
Token programname = getPreviousToken();
- Statement block = blockStatement(false);
+ Statement block = blockStatement();
matchOrError(TokenType.PROGRAM,"Programs must end in 'program'");
matchOrError(TokenType.IDENTIFIER,"Expected program name");
@@ -80,7 +81,7 @@ public class Parser {
//Add function name to the list of defined values
definedVars.put(name.text, "function");
- matchOrError(TokenType.LEFT_PAREN, "Expected '(");
+ matchOrError(TokenType.LEFT_PAREN, "Expected '(' in function definition");
List<Expression> arguments=new ArrayList<>();
List<String> types = new ArrayList<>();
@@ -96,11 +97,13 @@ public class Parser {
}
arguments.add(expression());
} while(matchAndAdvance(TokenType.COMMA));
- matchOrError(TokenType.RIGHT_PAREN, "Expected ')'");
+ matchOrError(TokenType.RIGHT_PAREN, "Expected ')' in function definition");
+ }
+ foundReturn=false;
+ Statement block = blockStatement();
+ if(isfunction&&!foundReturn){
+ throw error(name, "Function must contain a return statement");
}
-
- Statement block = blockStatement(isfunction);
-
//Add the function declaration to the start of the list of statements
statements.add(0,new Statement.FunctionDeclaration(name,types,returntype));
return new Statement.Function(name,block,arguments,types,returntype);
@@ -225,7 +228,7 @@ public class Parser {
* @return A statement representing the array declaration
*/
private Statement arrayDeclaration(String type){
- matchOrError(TokenType.LEFT_PAREN,"Expected ')'");
+ matchOrError(TokenType.LEFT_PAREN,"Expected ')' for array definition");
//Extract the size of the array
List<Expression> dimensions = new ArrayList<>();
@@ -236,9 +239,9 @@ public class Parser {
dimensions.add(dimension);
} while(matchAndAdvance(TokenType.COMMA));
- matchOrError(TokenType.RIGHT_PAREN, "Expected ')'");
- matchOrError(TokenType.DEFINE, ":: Required for variable definition");
- matchOrError(TokenType.IDENTIFIER,"Expected variable name.");
+ matchOrError(TokenType.RIGHT_PAREN, "Expected ')' for array definition");
+ matchOrError(TokenType.DEFINE, ":: Required for array definition");
+ matchOrError(TokenType.IDENTIFIER,"Expected array name.");
Token varName = getPreviousToken();
//Ensure that a variable with the same name has not been defined
@@ -255,8 +258,7 @@ public class Parser {
* @param isFunction whether the block is for a function and so must contain a return statement
* @return a statement representing a block
*/
- private Statement blockStatement(boolean isFunction){
- boolean hasReturn=false;
+ private Statement blockStatement(){
List<Statement> statements = new ArrayList<>();
//Match statement until an end or else token has been reached
@@ -266,15 +268,8 @@ public class Parser {
throw error(getCurrentToken(),"end missing from block");
}
Statement statement = statement();
- if(statement.getStatmentType()=="return"){
- hasReturn=true;
- }
statements.add(statement);
}
- //Ensure that a function block contains a return statement
- if(isFunction&&!hasReturn){
- throw error(getPreviousToken(), "Function must contain a return statement");
- }
return new Statement.BlockStatement(statements);
}
@@ -289,7 +284,7 @@ public class Parser {
//Get the list of printed values
while(matchAndAdvance(TokenType.COMMA)){
if(checkEOF()){
- throw error(getCurrentToken(),"reached end of file");
+ throw error(getCurrentToken(),"reached end of file scanning print statement");
}
Expression expr = expression();
exprList.add(expr);
@@ -303,20 +298,18 @@ public class Parser {
*/
private Statement ifStatement(){
Expression condition = expression();
- if(matchOrError(TokenType.THEN, "then expected after if statement")){
- //Extract if block
- Statement ifBlock = blockStatement(false);
- Statement elseBlock=null;
+ matchOrError(TokenType.THEN, "then expected after if statement");
+ //Extract if block
+ Statement ifBlock = blockStatement();
+ Statement elseBlock=null;
- //Extract else block if required
- if(matchAndAdvance(TokenType.ELSE)){
- elseBlock=blockStatement(false);
- }
- matchOrError(TokenType.IF, "If statements end with if");
- Statement ifstatement = new Statement.IfStatement(condition, ifBlock,elseBlock);
- return ifstatement;
+ //Extract else block if required
+ if(matchAndAdvance(TokenType.ELSE)){
+ elseBlock=blockStatement();
}
- return null;
+ matchOrError(TokenType.IF, "If statements end with if");
+ Statement ifstatement = new Statement.IfStatement(condition, ifBlock,elseBlock);
+ return ifstatement;
}
/**
@@ -329,17 +322,17 @@ public class Parser {
return whileStatement();
}
Expression variable =expression();
- matchOrError(TokenType.EQUALS, "'=' missing");
+ matchOrError(TokenType.EQUALS, "'=' missing from do statement assignment");
//Extract start, stop, and step variables
Expression start = expression();
- matchOrError(TokenType.COMMA, " use ',' between values");
+ matchOrError(TokenType.COMMA, " use ',' between values in do statement");
Expression stop = expression();
Expression step = null;
if(matchAndAdvance(TokenType.COMMA)){
step = expression();
}
- Statement codeBlock = blockStatement(false);
+ Statement codeBlock = blockStatement();
matchOrError(TokenType.DO, "Do statements end with do");
return new Statement.DoStatement(variable, start, stop, step,codeBlock);
@@ -351,10 +344,10 @@ public class Parser {
*/
private Statement whileStatement(){
//Extract condition
- matchOrError(TokenType.LEFT_PAREN, " missing '(' for do statement condition");
+ matchOrError(TokenType.LEFT_PAREN, " missing '(' for do while statement condition");
Expression condition = expression();
- matchOrError(TokenType.RIGHT_PAREN, " missing ')' for do condition");
- Statement codeBlock = blockStatement(false);
+ matchOrError(TokenType.RIGHT_PAREN, " missing ')' for do while condition");
+ Statement codeBlock = blockStatement();
matchOrError(TokenType.DO, "Do while statements end with do");
return new Statement.DoWhileStatement(condition,codeBlock);
}
@@ -364,6 +357,7 @@ public class Parser {
* @return a return statement object
*/
private Statement returnStatement(){
+ foundReturn=true;
Expression returnValue = expression();
return new Statement.ReturnStatement(returnValue);
}
@@ -543,7 +537,7 @@ public class Parser {
//Parse bracketed expressions
if (matchAndAdvance(TokenType.LEFT_PAREN)){
Expression expr = expression();
- matchOrError(TokenType.RIGHT_PAREN,"Expected ')'");
+ matchOrError(TokenType.RIGHT_PAREN,"Expected ')' after bracketed expression");
return new Expression.BracketedExpression(expr);
}
//Throw an error if the expression was not recognised
diff --git a/src/examples/recursive.ft b/src/examples/recursive.ft
new file mode 100644
index 0000000..d6f7a69
--- /dev/null
+++ b/src/examples/recursive.ft
@@ -0,0 +1,14 @@
+program recursive
+int::value
+int::final
+value=5
+final=factorial(value)
+print*,"The factorial of ",value," is ",final
+end program recursive
+
+function int factorial(int x)
+if x==1 then
+return 1
+end if
+return x*factorial(x-1)
+end \ No newline at end of file