package tool; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.Charset; 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", "Variable : Token name")); defineAST( outputDir, "Stmt", Arrays.asList( "Expression : Expr expression", "Var : Token name, Expr initializer", "Print : Expr expression")); } private static void defineAST(String outputDir, String baseName, List types) throws IOException { String path = outputDir + "/" + baseName + ".java"; PrintWriter writer = new PrintWriter(path, Charset.defaultCharset()); writer.println("package 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); } 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(" }"); writer.println(); } private static void defineType( PrintWriter writer, String baseName, String className, String fieldList) { writer.println(" static class " + className + " extends " + baseName + " {"); writer.println(" " + className + "(" + fieldList + ") {"); String[] fields = fieldList.split(", "); for (String field : fields) { String name = field.split(" ")[1]; writer.println(" this." + name + " = " + name + ";"); } writer.println(" }"); writer.println(); writer.println(" @Override"); writer.println(" R accept(Visitor visitor) {"); writer.println(" return visitor.visit" + className + baseName + "(this);"); writer.println(" }"); writer.println(); for (String field : fields) { writer.println(" final " + field + ";"); } writer.println(" }"); writer.println(); } }