diff options
author | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-12-08 04:37:18 +0000 |
---|---|---|
committer | AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com> | 2021-12-08 04:37:18 +0000 |
commit | 0d32b01fde73224469b8bb5971ebdaacd9bfa32c (patch) | |
tree | a6ff8bd4dbbf144cb112d24785b525ce2b59fb8a /src | |
parent | 5c4d41c63af3ef064090336a14efe91931051e7e (diff) | |
download | esotericFORTRAN-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.json | 2 | ||||
-rw-r--r-- | src/Compiler/Parser.java | 72 | ||||
-rw-r--r-- | src/examples/recursive.ft | 14 |
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 |