From 68a2ebd34fc94488e89ffb82b359ec6e7e152ae9 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Thu, 8 Jul 2021 00:14:31 -0700 Subject: Restructure project to make room for clox --- .../com/craftinginterpreters/tool/GenerateAst.java | 100 +++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 jlox/src/com/craftinginterpreters/tool/GenerateAst.java (limited to 'jlox/src/com/craftinginterpreters/tool/GenerateAst.java') diff --git a/jlox/src/com/craftinginterpreters/tool/GenerateAst.java b/jlox/src/com/craftinginterpreters/tool/GenerateAst.java new file mode 100644 index 0000000..04b4500 --- /dev/null +++ b/jlox/src/com/craftinginterpreters/tool/GenerateAst.java @@ -0,0 +1,100 @@ +package com.craftinginterpreters.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("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right", + "Call : Expr callee, Token paren, List arguments", "Get : Expr object, Token name", + "Grouping : Expr expression", "Literal : Object value", + "Logical : Expr left, Token operator, Expr right", "Set : Expr object, Token name, Expr value", + "Super : Token keyword, Token method", "This : Token keyword", + "Unary : Token operator, Expr right", "Variable : Token name")); + defineAst(outputDir, "Stmt", + Arrays.asList("Block : List statements", + "Class : Token name, Expr.Variable superclass, List methods", + "Expression : Expr expression", "Function : Token name, List params, List body", + "If : Expr condition, Stmt thenBranch, Stmt elseBranch", "Print : Expr expression", + "Return : Token keyword, Expr value", "Var : Token name, Expr initializer", + "While : Expr condition, Stmt body")); + } + + private static void defineAst(String outputDir, String baseName, List types) throws IOException { + String path = outputDir + "/" + baseName + ".java"; + PrintWriter writer = new PrintWriter(path); + + writer.println("package com.craftinginterpreters.lox;"); + writer.println(); + writer.println("import java.util.List;"); + writer.println(); + writer.println("abstract class " + baseName + " {"); + + defineVisitor(writer, baseName, types); + + for (String type : types) { + String className = type.split(":")[0].trim(); + String fields = type.split(":")[1].trim(); + defineType(writer, baseName, className, fields); + } + + // The base accept() method + writer.println(); + writer.println(" abstract R accept(Visitor visitor);"); + + writer.println("}"); + writer.close(); + } + + private static void defineVisitor(PrintWriter writer, String baseName, List types) { + writer.println(" interface Visitor {"); + + for (String type : types) { + String typeName = type.split(":")[0].trim(); + writer.println(" R visit" + typeName + baseName + "(" + typeName + " " + baseName.toLowerCase() + ");"); + } + + writer.println(" }"); + } + + 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(" }"); + + // Visitor pattern. + writer.println(); + writer.println(" @Override"); + writer.println(" R accept(Visitor visitor) {"); + writer.println(" return visitor.visit" + className + baseName + "(this);"); + writer.println(" }"); + + // Fields + writer.println(); + for (String field : fields) { + writer.println(" final " + field + ";"); + } + + writer.println(" }"); + } +} -- cgit v1.2.3-54-g00ecf