if-ELSE!!!!

This commit is contained in:
Manuel Friedli 2024-03-24 04:30:43 +01:00
parent 19c9409ccd
commit 6e0b8f950d
Signed by: manuel
GPG key ID: 41D08ABA75634DA1
8 changed files with 50 additions and 11 deletions

View file

@ -1,4 +1,4 @@
package ch.fritteli.gombaila.domain.common;
public sealed interface NodeStmt extends Node permits NodeStmtAssign, NodeStmtExit, NodeStmtIf, NodeStmtLet, NodeStmtPrint, NodeStmtScope {
public sealed interface NodeStmt extends Node permits NodeStmtAssign, NodeStmtExit, NodeStmtIf, NodeStmtIfElse, NodeStmtLet, NodeStmtPrint, NodeStmtScope {
}

View file

@ -2,6 +2,5 @@ package ch.fritteli.gombaila.domain.common;
import org.jetbrains.annotations.NotNull;
public record NodeStmtIf(@NotNull NodeExpr expr, @NotNull NodeStmtScope scope) implements NodeStmt {
public record NodeStmtIf(@NotNull NodeExpr expr, @NotNull NodeStmtScope ifScope) implements NodeStmt {
}

View file

@ -0,0 +1,7 @@
package ch.fritteli.gombaila.domain.common;
import org.jetbrains.annotations.NotNull;
public record NodeStmtIfElse(@NotNull NodeExpr expr, @NotNull NodeStmtScope ifScope,
@NotNull NodeStmtScope elseScope) implements NodeStmt {
}

View file

@ -26,7 +26,8 @@ public enum TokenType {
IDENTIFIER,
// the rest
WHITESPACE,
IF;
IF,
ELSE;
public boolean isBinaryOperator() {
return switch (this) {

View file

@ -4,6 +4,7 @@ import ch.fritteli.gombaila.domain.common.NodeStmt;
import ch.fritteli.gombaila.domain.common.NodeStmtAssign;
import ch.fritteli.gombaila.domain.common.NodeStmtExit;
import ch.fritteli.gombaila.domain.common.NodeStmtIf;
import ch.fritteli.gombaila.domain.common.NodeStmtIfElse;
import ch.fritteli.gombaila.domain.common.NodeStmtLet;
import ch.fritteli.gombaila.domain.common.NodeStmtPrint;
import ch.fritteli.gombaila.domain.common.NodeStmtScope;
@ -27,6 +28,7 @@ final class StmtVisitor {
case final NodeStmtPrint stmtPrint -> visit(stmtPrint);
case final NodeStmtScope stmtScope -> visit(stmtScope);
case final NodeStmtIf stmtIf -> visit(stmtIf);
case final NodeStmtIfElse stmtIfElse -> visit(stmtIfElse);
}
}
@ -96,9 +98,30 @@ final class StmtVisitor {
"skip to %s if condition is not met".formatted(label),
"jz", label
);
this.visit(stmt.scope());
this.visit(stmt.ifScope());
this.generator.printer.label(label);
}
private void visit(@NotNull final NodeStmtIfElse stmt) {
final String afterIfLabel = this.createNextLabel();
final String afterElseLabel = this.createNextLabel();
this.generator.generateExpr(stmt.expr());
this.generator.pop("rax");
this.generator.printer.commentedLine("test the condition",
"test", "rax, rax");
this.generator.printer.commentedLine(
"skip to %s (else) if condition is not met".formatted(afterIfLabel),
"jz", afterIfLabel
);
this.visit(stmt.ifScope());
this.generator.printer.commentedLine(
"skip to %s to skip the else".formatted(afterElseLabel),
"jmp",
afterElseLabel
);
this.generator.printer.label(afterIfLabel);
this.visit(stmt.elseScope());
this.generator.printer.label(afterElseLabel);
}
private String createNextLabel() {

View file

@ -80,6 +80,7 @@ public class Lexer {
case "let" -> this.appendToken(new Token(TokenType.LET, line, column));
case "print" -> this.appendToken(new Token(TokenType.PRINT, line, column));
case "if" -> this.appendToken(new Token(TokenType.IF, line, column));
case "else" -> this.appendToken(new Token(TokenType.ELSE, line, column));
case final String value ->
this.appendToken(new Token(TokenType.IDENTIFIER, Option.of(value), line, column));
}

View file

@ -15,6 +15,7 @@ import ch.fritteli.gombaila.domain.common.NodeStmt;
import ch.fritteli.gombaila.domain.common.NodeStmtAssign;
import ch.fritteli.gombaila.domain.common.NodeStmtExit;
import ch.fritteli.gombaila.domain.common.NodeStmtIf;
import ch.fritteli.gombaila.domain.common.NodeStmtIfElse;
import ch.fritteli.gombaila.domain.common.NodeStmtLet;
import ch.fritteli.gombaila.domain.common.NodeStmtPrint;
import ch.fritteli.gombaila.domain.common.NodeStmtScope;
@ -65,9 +66,14 @@ public class Parser {
this.assertAndConsumeNextTokenType(TokenType.OPEN_PAREN);
final NodeExpr expr = this.parseExpr(1);
this.assertAndConsumeNextTokenType(TokenType.CLOSE_PAREN);
final NodeStmtScope scope = this.parseScope();
final NodeStmtScope ifScope = this.parseScope();
// there /could/ be an else, so let's check that
if (this.checkNextTokenTypeConsuming(TokenType.ELSE)) {
final NodeStmtScope elseScope = this.parseScope();
return new NodeStmtIfElse(expr, ifScope, elseScope);
}
// NB: We do NOT expect a SEMI here, so we return directly.
return new NodeStmtIf(expr, scope);
return new NodeStmtIf(expr, ifScope);
} else if (this.checkNextTokenType(TokenType.IDENTIFIER)) {
result = this.parseStmtAssign();
} else {

View file

@ -1,5 +1,7 @@
let x = (10 - 2 * 3) / 2;
if (x-2) {
exit (69);
let x = 1;
if (x) {
x = 99;
} else {
x = 12;
}
exit(1);
exit(x);