finish off chapter 5

This commit is contained in:
David 2021-09-18 13:21:50 -04:00
parent f7585ea87a
commit 362569e6ce
3 changed files with 104 additions and 1 deletions

42
src/lox/ASTPrinter.java Normal file
View File

@ -0,0 +1,42 @@
package lox;
class ASTPrinter implements Expr.Visitor<String> {
String print(Expr expr) {
return expr.accept(this);
}
@Override
public String visitBinaryExpr(Expr.Binary expr) {
return parenthesize(expr.operator.lexeme, expr.left, expr.right);
}
@Override
public String visitGroupingExpr(Expr.Grouping expr) {
return parenthesize("group", expr.expression);
}
@Override
public String visitLiteralExpr(Expr.Literal expr) {
if (expr.value == null) {
return "nil";
}
return expr.value.toString();
}
@Override
public String visitUnaryExpr(Expr.Unary expr) {
return parenthesize(expr.operator.lexeme, expr.right);
}
private String parenthesize(String name, Expr... exprs) {
StringBuilder builder = new StringBuilder();
builder.append("(").append(name);
for (Expr expr : exprs) {
builder.append(" ").append(expr.accept(this));
}
builder.append(")");
return builder.toString();
}
}

View File

@ -1,6 +1,15 @@
package lox; package lox;
import java.util.List;
abstract class Expr { abstract class Expr {
interface Visitor<R> {
R visitBinaryExpr(Binary expr);
R visitGroupingExpr(Grouping expr);
R visitLiteralExpr(Literal expr);
R visitUnaryExpr(Unary expr);
}
static class Binary extends Expr { static class Binary extends Expr {
Binary(Expr left, Token operator, Expr right) { Binary(Expr left, Token operator, Expr right) {
this.left = left; this.left = left;
@ -8,6 +17,11 @@ abstract class Expr {
this.right = right; this.right = right;
} }
@Override
<R> R accept(Visitor<R> visitor) {
return visitor.visitBinaryExpr(this);
}
final Expr left; final Expr left;
final Token operator; final Token operator;
final Expr right; final Expr right;
@ -18,6 +32,11 @@ abstract class Expr {
this.expression = expression; this.expression = expression;
} }
@Override
<R> R accept(Visitor<R> visitor) {
return visitor.visitGroupingExpr(this);
}
final Expr expression; final Expr expression;
} }
@ -26,6 +45,11 @@ abstract class Expr {
this.value = value; this.value = value;
} }
@Override
<R> R accept(Visitor<R> visitor) {
return visitor.visitLiteralExpr(this);
}
final Object value; final Object value;
} }
@ -35,7 +59,14 @@ abstract class Expr {
this.right = right; this.right = right;
} }
@Override
<R> R accept(Visitor<R> visitor) {
return visitor.visitUnaryExpr(this);
}
final Token operator; final Token operator;
final Expr right; final Expr right;
} }
abstract <R> R accept(Visitor<R> visitor);
} }

View File

@ -34,16 +34,40 @@ public class GenerateAST {
writer.println(); writer.println();
writer.println("abstract class " + baseName + " {"); writer.println("abstract class " + baseName + " {");
defineVisitor(writer, baseName, types);
for (String type : types) { for (String type : types) {
String className = type.split(":")[0].trim(); String className = type.split(":")[0].trim();
String fields = type.split(":")[1].trim(); String fields = type.split(":")[1].trim();
defineType(writer, baseName, className, fields); defineType(writer, baseName, className, fields);
} }
writer.println(" abstract <R> R accept(Visitor<R> visitor);");
writer.println("}"); writer.println("}");
writer.close(); writer.close();
} }
private static void defineVisitor(PrintWriter writer, String baseName, List<String> types) {
writer.println(" interface Visitor<R> {");
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( private static void defineType(
PrintWriter writer, String baseName, String className, String fieldList) { PrintWriter writer, String baseName, String className, String fieldList) {
writer.println(" static class " + className + " extends " + baseName + " {"); writer.println(" static class " + className + " extends " + baseName + " {");
@ -59,6 +83,12 @@ public class GenerateAST {
writer.println(" }"); writer.println(" }");
writer.println(); writer.println();
writer.println(" @Override");
writer.println(" <R> R accept(Visitor<R> visitor) {");
writer.println(" return visitor.visit" + className + baseName + "(this);");
writer.println(" }");
writer.println();
for (String field : fields) { for (String field : fields) {
writer.println(" final " + field + ";"); writer.println(" final " + field + ";");
} }