diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..92322c4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea/
+target/
diff --git a/README.md b/README.md
index 6cd2507..df36ebd 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
# gombaila
-Let's write a compiler in Java!
-Inspired by Pixeled: https://www.youtube.com/watch?v=vcSijrRsrY0.
\ No newline at end of file
+Let's write a compiler in Java!
+Inspired by Pixeled: https://www.youtube.com/watch?v=vcSijrRsrY0.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1615bd3
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+
+ ch.fritteli
+ fritteli-build-parent
+ 5.0.1-SNAPSHOT
+
+
+ ch.fritteli.gombaila
+ gombaila
+ 0.0.1-SNAPSHOT
+
+
+ UTF-8
+
+
+
+
+ io.vavr
+ vavr
+
+
+ org.jetbrains
+ annotations
+
+
+ org.slf4j
+ slf4j-api
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ org.projectlombok
+ lombok
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+
+
+ org.assertj
+ assertj-core
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 21
+
+
+
+
+
diff --git a/src/main/java/ch/fritteli/gombaila/ElementWalker.java b/src/main/java/ch/fritteli/gombaila/ElementWalker.java
new file mode 100644
index 0000000..86eaac3
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/ElementWalker.java
@@ -0,0 +1,57 @@
+package ch.fritteli.gombaila;
+
+import io.vavr.control.Option;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+
+public class ElementWalker {
+ @NotNull
+ private final T back;
+ @NotNull
+ private final BiPredicate hasNextPredicate;
+ @NotNull
+ private final BiPredicate hasPrevPredicate;
+ @NotNull
+ private final BiFunction atFunction;
+ private int index = 0;
+
+ public ElementWalker(@NotNull final T back,
+ @NotNull final BiPredicate hasNextPredicate,
+ @NotNull final BiPredicate hasPrevPredicate,
+ @NotNull final BiFunction atFunction) {
+ this.back = back;
+ this.hasNextPredicate = hasNextPredicate;
+ this.hasPrevPredicate = hasPrevPredicate;
+ this.atFunction = atFunction;
+ }
+
+ public boolean hasNext() {
+ return this.hasNextPredicate.test(this.back, this.index);
+ }
+
+ @NotNull
+ public E next() {
+ return this.atFunction.apply(this.back, this.index++);
+ }
+
+ @NotNull
+ public Option peekNext() {
+ return Option.when(this.hasNext(), () -> this.atFunction.apply(this.back, this.index));
+ }
+
+ public boolean hasPrev() {
+ return this.hasPrevPredicate.test(this.back, this.index);
+ }
+
+ @NotNull
+ public E prev() {
+ return this.atFunction.apply(this.back, --this.index);
+ }
+
+ @NotNull
+ public Option peekPrev() {
+ return Option.when(this.hasPrev(), () -> this.atFunction.apply(this.back, this.index - 1));
+ }
+}
diff --git a/src/main/java/ch/fritteli/gombaila/GombailaMain.java b/src/main/java/ch/fritteli/gombaila/GombailaMain.java
new file mode 100644
index 0000000..e98a29f
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/GombailaMain.java
@@ -0,0 +1,30 @@
+package ch.fritteli.gombaila;
+
+import ch.fritteli.gombaila.domain.common.NodeProg;
+import ch.fritteli.gombaila.domain.common.Token;
+import ch.fritteli.gombaila.domain.generator.Generator;
+import ch.fritteli.gombaila.domain.lexer.Lexer;
+import ch.fritteli.gombaila.domain.parser.Parser;
+import io.vavr.collection.Stream;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class GombailaMain {
+ public static void main(@NotNull final String[] args) throws URISyntaxException, IOException {
+ final String string = Files.readString(Paths.get(Lexer.class.getClassLoader().getResource("gombaila/simple.gb").toURI()));
+ final Lexer lexer = new Lexer(string);
+ final Stream tokens = lexer.lex();
+ System.out.println("TOKENS:\n" + tokens.mkString("\n"));
+ final Parser parser = new Parser(tokens);
+ final NodeProg nodeProg = parser.parse();
+ System.out.println("STMTS:\n" + nodeProg.stmts().mkString("\n"));
+ final Generator generator = new Generator(nodeProg);
+ final String asm = generator.generate();
+ Files.writeString(Paths.get("./target/simple.asm"), asm, StandardCharsets.UTF_8);
+ }
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/SeqWalker.java b/src/main/java/ch/fritteli/gombaila/domain/SeqWalker.java
new file mode 100644
index 0000000..2f78c76
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/SeqWalker.java
@@ -0,0 +1,16 @@
+package ch.fritteli.gombaila.domain;
+
+import ch.fritteli.gombaila.ElementWalker;
+import io.vavr.collection.Seq;
+import org.jetbrains.annotations.NotNull;
+
+public class SeqWalker extends ElementWalker, E> {
+ public SeqWalker(@NotNull final Seq seq) {
+ super(
+ seq,
+ (back, index) -> index < back.length(),
+ (back, index) -> index > 0,
+ Seq::get
+ );
+ }
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/Node.java b/src/main/java/ch/fritteli/gombaila/domain/common/Node.java
new file mode 100644
index 0000000..160fc19
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/Node.java
@@ -0,0 +1,4 @@
+package ch.fritteli.gombaila.domain.common;
+
+public sealed interface Node permits NodeExpr, NodeProg, NodeStmt {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExpr.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExpr.java
new file mode 100644
index 0000000..04b3f86
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExpr.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+public sealed interface NodeBinExpr extends NodeExpr
+ permits NodeBinExprAdd, NodeBinExprDiv, NodeBinExprExp, NodeBinExprMinus, NodeBinExprMod, NodeBinExprMult {
+
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprAdd.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprAdd.java
new file mode 100644
index 0000000..b839dbf
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprAdd.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprAdd(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprDiv.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprDiv.java
new file mode 100644
index 0000000..9951a2c
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprDiv.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprDiv(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprExp.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprExp.java
new file mode 100644
index 0000000..7885498
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprExp.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprExp(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMinus.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMinus.java
new file mode 100644
index 0000000..9fb2027
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMinus.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprMinus(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMod.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMod.java
new file mode 100644
index 0000000..66b9e50
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMod.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprMod(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMult.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMult.java
new file mode 100644
index 0000000..bb5c0e0
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeBinExprMult.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeBinExprMult(@NotNull NodeExpr lhs, @NotNull NodeExpr rhs) implements NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeExpr.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExpr.java
new file mode 100644
index 0000000..fa1964f
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExpr.java
@@ -0,0 +1,4 @@
+package ch.fritteli.gombaila.domain.common;
+
+public sealed interface NodeExpr extends Node permits NodeExprIdent, NodeExprIntLit, NodeBinExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIdent.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIdent.java
new file mode 100644
index 0000000..14ade85
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIdent.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeExprIdent(@NotNull Token ident) implements NodeExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIntLit.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIntLit.java
new file mode 100644
index 0000000..b24e4d0
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeExprIntLit.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeExprIntLit(@NotNull Token value) implements NodeExpr {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeProg.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeProg.java
new file mode 100644
index 0000000..79ddbec
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeProg.java
@@ -0,0 +1,7 @@
+package ch.fritteli.gombaila.domain.common;
+
+import io.vavr.collection.Seq;
+import org.jetbrains.annotations.NotNull;
+
+public record NodeProg(@NotNull Seq stmts) implements Node {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmt.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmt.java
new file mode 100644
index 0000000..5801f44
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmt.java
@@ -0,0 +1,4 @@
+package ch.fritteli.gombaila.domain.common;
+
+public sealed interface NodeStmt extends Node permits NodeStmtExit, NodeStmtLet, NodeStmtPrint {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtExit.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtExit.java
new file mode 100644
index 0000000..0eea3a7
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtExit.java
@@ -0,0 +1,7 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeStmtExit(@NotNull NodeExpr expr) implements NodeStmt {
+
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtLet.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtLet.java
new file mode 100644
index 0000000..58845d6
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtLet.java
@@ -0,0 +1,7 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeStmtLet(@NotNull Token ident, @NotNull NodeExpr expr) implements NodeStmt {
+
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtPrint.java b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtPrint.java
new file mode 100644
index 0000000..1e8e65e
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/NodeStmtPrint.java
@@ -0,0 +1,6 @@
+package ch.fritteli.gombaila.domain.common;
+
+import org.jetbrains.annotations.NotNull;
+
+public record NodeStmtPrint(@NotNull NodeExpr nodeExpr) implements NodeStmt {
+}
diff --git a/src/main/java/ch/fritteli/gombaila/domain/common/Token.java b/src/main/java/ch/fritteli/gombaila/domain/common/Token.java
new file mode 100644
index 0000000..90b474a
--- /dev/null
+++ b/src/main/java/ch/fritteli/gombaila/domain/common/Token.java
@@ -0,0 +1,10 @@
+package ch.fritteli.gombaila.domain.common;
+
+import io.vavr.control.Option;
+import org.jetbrains.annotations.NotNull;
+
+public record Token(@NotNull TokenType type, @NotNull Option