Returning from calls 10.5.1
This commit is contained in:
parent
10cc5e6e89
commit
7f4946f1e9
10 changed files with 196 additions and 23 deletions
|
|
@ -8,6 +8,7 @@ import jlox.util;
|
|||
import jlox.expr;
|
||||
import jlox.main;
|
||||
import jlox.stmt;
|
||||
import jlox.loxfunction;
|
||||
|
||||
class Parser{
|
||||
private Token[] tokens;
|
||||
|
|
@ -84,11 +85,35 @@ class Parser{
|
|||
consume(TokenType.SEMICOLON, "Expect ';' after value.");
|
||||
return new Stmt.Print(value);
|
||||
}
|
||||
private Stmt returnStatement(){
|
||||
Token keyword = previous();
|
||||
Expr value;
|
||||
if(!check(TokenType.SEMICOLON))
|
||||
value = expression();
|
||||
consume(TokenType.SEMICOLON, "Expect ';' after return value.");
|
||||
return new Stmt.Return(keyword, value);
|
||||
}
|
||||
private Stmt expressionStatement(){
|
||||
Expr expr = expression();
|
||||
consume(TokenType.SEMICOLON, "Expect ';' after expression.");
|
||||
return new Stmt.Expression(expr);
|
||||
}
|
||||
private Stmt.Function fun(string kind){
|
||||
Token name = consume(TokenType.IDENTIFIER, "Expect " ~ kind ~ " name.");
|
||||
consume(TokenType.LEFT_PAREN, "Expect '(' after " ~ kind ~ " name.");
|
||||
Token[] parameters;
|
||||
if(!check(TokenType.RIGHT_PAREN)){
|
||||
do{
|
||||
if(parameters.length >= 255)
|
||||
error(peek(), "Can't have more than 255 parameters.");
|
||||
parameters ~= consume(TokenType.IDENTIFIER, "Expect parameter name.");
|
||||
} while(match(TokenType.COMMA));
|
||||
}
|
||||
consume(TokenType.RIGHT_PAREN, "Expect ')' after parameters.");
|
||||
consume(TokenType.LEFT_BRACE, "Expect '{' before " ~ kind ~ " body.");
|
||||
Stmt[] body = block();
|
||||
return new Stmt.Function(name, parameters, body);
|
||||
}
|
||||
private Stmt ifStatement(){
|
||||
consume(TokenType.LEFT_PAREN, "Expect '(' after 'if'.");
|
||||
Expr condition = expression();
|
||||
|
|
@ -142,6 +167,8 @@ class Parser{
|
|||
return whileStatement();
|
||||
if(match(TokenType.PRINT))
|
||||
return printStatement();
|
||||
if(match(TokenType.RETURN))
|
||||
return returnStatement();
|
||||
if(match(TokenType.LEFT_BRACE))
|
||||
return new Stmt.Block(block());
|
||||
return expressionStatement();
|
||||
|
|
@ -227,7 +254,29 @@ class Parser{
|
|||
Expr right = unary();
|
||||
return new Expr.Unary(operator, right);
|
||||
}
|
||||
return primary();
|
||||
return call();
|
||||
}
|
||||
private Expr call(){
|
||||
Expr finishCall(Expr callee){
|
||||
Expr[] arguments;
|
||||
if(!check(TokenType.RIGHT_PAREN)){
|
||||
do {
|
||||
if(arguments.length >= 255)
|
||||
error(peek(), "Can't have more than 255 arguments.");
|
||||
arguments ~= expression();
|
||||
} while(match(TokenType.COMMA));
|
||||
}
|
||||
Token paren = consume(TokenType.RIGHT_PAREN, "Expect ')' after arguments.");
|
||||
return new Expr.Call(callee, paren, arguments);
|
||||
}
|
||||
Expr expr = primary();
|
||||
while(true){
|
||||
if(match(TokenType.LEFT_PAREN))
|
||||
expr = finishCall(expr);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
private Expr primary(){
|
||||
if(match(TokenType.IDENTIFIER))
|
||||
|
|
@ -237,7 +286,7 @@ class Parser{
|
|||
if(match(TokenType.TRUE))
|
||||
return new Expr.Literal(TValue.bln(true));
|
||||
if(match(TokenType.NIL))
|
||||
return new Expr.Literal(TValue.nil(0));
|
||||
return new Expr.Literal(tvalueNil);
|
||||
if(match(TokenType.NUMBER, TokenType.STRING))
|
||||
return new Expr.Literal(previous().literal);
|
||||
if(match(TokenType.LEFT_PAREN)){
|
||||
|
|
@ -257,6 +306,8 @@ class Parser{
|
|||
}
|
||||
private Stmt declaration(){
|
||||
try {
|
||||
if(match(TokenType.FUN))
|
||||
return fun("function");
|
||||
if(match(TokenType.VAR))
|
||||
return varDeclaration();
|
||||
return statement();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue