Classes 12

This commit is contained in:
nazrin 2025-06-02 22:22:04 +00:00
parent 52a7b73a9e
commit d8ac625429
18 changed files with 417 additions and 186 deletions

View file

@ -83,7 +83,7 @@ class Parser{
private Stmt printStatement(){
version(LoxPrintMultiple){
Expr[] values;
do {
if(!check(TokenType.SEMICOLON)) do {
values ~= expression();
} while(match(TokenType.COMMA));
consume(TokenType.SEMICOLON, "Expect ';' after values.");
@ -144,7 +144,7 @@ class Parser{
else
initialiser = expressionStatement();
Expr condition = check(TokenType.SEMICOLON) ? new Expr.Literal(TValue.bln(true)) : expression();
Expr condition = check(TokenType.SEMICOLON) ? new Expr.Literal(new LoxBool(true)) : expression();
consume(TokenType.SEMICOLON, "Expect ';' after loop condition.");
Expr increment;
@ -197,8 +197,11 @@ class Parser{
if(match(TokenType.EQUAL)){
Token equals = previous();
Expr value = assignment();
if(auto v = cast(Expr.Variable)expr)
if(auto v = cast(Expr.Variable)expr){
return new Expr.Assign(v.name, value);
} else if(auto get = cast(Expr.Get)expr){
return new Expr.Set(get.object, get.name, value);
}
error(equals, "Invalid assignment target.");
}
return expr;
@ -280,10 +283,14 @@ class Parser{
}
Expr expr = primary();
while(true){
if(match(TokenType.LEFT_PAREN))
if(match(TokenType.LEFT_PAREN)){
expr = finishCall(expr);
else
} else if(match(TokenType.DOT)){
Token name = consume(TokenType.IDENTIFIER, "Expect property name after '.'.");
expr = new Expr.Get(expr, name);
} else {
break;
}
}
return expr;
}
@ -291,13 +298,15 @@ class Parser{
if(match(TokenType.IDENTIFIER))
return new Expr.Variable(previous());
if(match(TokenType.FALSE))
return new Expr.Literal(TValue.bln(false));
return new Expr.Literal(new LoxBool(false));
if(match(TokenType.TRUE))
return new Expr.Literal(TValue.bln(true));
return new Expr.Literal(new LoxBool(true));
if(match(TokenType.NIL))
return new Expr.Literal(tvalueNil);
return new Expr.Literal(new LoxNil());
if(match(TokenType.NUMBER, TokenType.STRING))
return new Expr.Literal(previous().literal);
if(match(TokenType.THIS))
return new Expr.This(previous());
if(match(TokenType.LEFT_PAREN)){
Expr expr = expression();
consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.");
@ -313,12 +322,23 @@ class Parser{
consume(TokenType.SEMICOLON, "Expect ';' after variable declaration.");
return new Stmt.Var(name, initialiser);
}
private Stmt classDeclaration() {
Token name = consume(TokenType.IDENTIFIER, "Expect class name.");
consume(TokenType.LEFT_BRACE, "Expect '{' before class body.");
Stmt.Function[] methods;
while(!check(TokenType.RIGHT_BRACE) && !isAtEnd)
methods ~= fun("method");
consume(TokenType.RIGHT_BRACE, "Expect '}' after class body.");
return new Stmt.Class(name, methods);
}
private Stmt declaration(){
try {
if(match(TokenType.FUN))
return fun("function");
if(match(TokenType.VAR))
return varDeclaration();
if(match(TokenType.FUN))
return fun("function");
if(match(TokenType.CLASS))
return classDeclaration();
return statement();
} catch(ParseError error){
synchronise();