Returning from calls 10.5.1

This commit is contained in:
nazrin 2025-06-02 00:06:31 +00:00
parent 10cc5e6e89
commit 7f4946f1e9
10 changed files with 196 additions and 23 deletions

View file

@ -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();