From cac74b1c10c6f788fa9d78551af452c88d49f444 Mon Sep 17 00:00:00 2001 From: Sebastian Hugentobler Date: Sat, 8 Feb 2025 10:21:26 +0100 Subject: [PATCH] add ast generator in java --- README.md | 4 +- java/lox-interpreter/pom.xml | 19 ++++- .../java/ch/vanwa/lox_interpreter/Expr.java | 40 +++++++++++ .../main/java/ch/vanwa/tool/GenerateAst.java | 72 +++++++++++++++++++ 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 java/lox-interpreter/src/main/java/ch/vanwa/lox_interpreter/Expr.java create mode 100644 java/lox-interpreter/src/main/java/ch/vanwa/tool/GenerateAst.java diff --git a/README.md b/README.md index b301b11..d18e422 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ Though my recommendation is to use the provided Implementation of the tree-walk interpreter in java after the book. Run `mvn package` to create an executable jar file in the `target` directory and -`mvn exec:java` to get a repl. +`mvn exec:java@jlox` to get a repl. + +Run `mvn exec:java@generate-ast` to generate the expression class. ## [Rust implementation](./rust/rox/) diff --git a/java/lox-interpreter/pom.xml b/java/lox-interpreter/pom.xml index 36e01d3..dabfda5 100644 --- a/java/lox-interpreter/pom.xml +++ b/java/lox-interpreter/pom.xml @@ -112,14 +112,27 @@ 3.5.0 + jlox java + + ch.vanwa.lox_interpreter.App + + + + generate-ast + + java + + + ch.vanwa.tool.GenerateAst + + src/main/java/ch/vanwa/lox_interpreter + + - - ch.vanwa.lox_interpreter.App - diff --git a/java/lox-interpreter/src/main/java/ch/vanwa/lox_interpreter/Expr.java b/java/lox-interpreter/src/main/java/ch/vanwa/lox_interpreter/Expr.java new file mode 100644 index 0000000..ab28035 --- /dev/null +++ b/java/lox-interpreter/src/main/java/ch/vanwa/lox_interpreter/Expr.java @@ -0,0 +1,40 @@ +package ch.vanwa.lox_interpreter; + +import java.util.List; + +abstract class Expr { + static class Binary extends Expr { + Binary(Expr left, Token operator, Expr right) { + this.left = left; + this.operator = operator; + this.right = right; + } + + final Expr left; + final Token operator; + final Expr right; + } + static class Grouping extends Expr { + Grouping(Expr expression) { + this.expression = expression; + } + + final Expr expression; + } + static class Literal extends Expr { + Literal(Object value) { + this.value = value; + } + + final Object value; + } + static class Unary extends Expr { + Unary(Token operator, Expr right) { + this.operator = operator; + this.right = right; + } + + final Token operator; + final Expr right; + } +} diff --git a/java/lox-interpreter/src/main/java/ch/vanwa/tool/GenerateAst.java b/java/lox-interpreter/src/main/java/ch/vanwa/tool/GenerateAst.java new file mode 100644 index 0000000..ad6e201 --- /dev/null +++ b/java/lox-interpreter/src/main/java/ch/vanwa/tool/GenerateAst.java @@ -0,0 +1,72 @@ +package ch.vanwa.tool; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; + +public class GenerateAst { + public static void main(String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: generate_ast "); + System.exit(64); + } + String outputDir = args[0]; + + defineAst(outputDir, "Expr", Arrays.asList( + "Binary : Expr left, Token operator, Expr right", + "Grouping : Expr expression", + "Literal : Object value", + "Unary : Token operator, Expr right")); + } + + private static void defineAst( + String outputDir, String baseName, List types) + throws IOException { + String path = outputDir + "/" + baseName + ".java"; + PrintWriter writer = new PrintWriter(path, "UTF-8"); + + writer.println("package ch.vanwa.lox_interpreter;"); + writer.println(); + writer.println("import java.util.List;"); + writer.println(); + writer.println("abstract class " + baseName + " {"); + + // The AST classes. + for (String type : types) { + String className = type.split(":")[0].trim(); + String fields = type.split(":")[1].trim(); + defineType(writer, baseName, className, fields); + } + + writer.println("}"); + writer.close(); + } + + private static void defineType( + PrintWriter writer, String baseName, + String className, String fieldList) { + writer.println(" static class " + className + " extends " + + baseName + " {"); + + // Constructor. + writer.println(" " + className + "(" + fieldList + ") {"); + + // Store parameters in fields. + String[] fields = fieldList.split(", "); + for (String field : fields) { + String name = field.split(" ")[1]; + writer.println(" this." + name + " = " + name + ";"); + } + + writer.println(" }"); + + // Fields. + writer.println(); + for (String field : fields) { + writer.println(" final " + field + ";"); + } + + writer.println(" }"); + } +}