d79f13e8 by Ulrich Schoepp

Datentypen fuer abstrakte Syntax

1 parent db9f43e7
Showing 40 changed files with 1348 additions and 0 deletions
package minijava.syntax;
import java.util.List;
import java.util.Optional;
public class ClassDeclaration {
private final String className;
private final String superName;
private final List<VariableDeclaration> fields;
private final List<MethodDeclaration> methods;
public ClassDeclaration(String className,
List<VariableDeclaration> fields, List<MethodDeclaration> methods) {
this(className, null, fields, methods);
}
public ClassDeclaration(String className, String superName,
List<VariableDeclaration> fields, List<MethodDeclaration> methods) {
this.className = className;
this.superName = superName;
this.fields = fields;
this.methods = methods;
}
public String getClassName() {
return className;
}
public String getSuperName() {
return superName;
}
public List<VariableDeclaration> getFields() {
return fields;
}
public List<MethodDeclaration> getMethods() {
return methods;
}
}
package minijava.syntax;
public abstract class Exp {
public abstract <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T;
public String prettyPrint() {
return accept(new PrettyPrint.PrettyPrintVisitorExp());
}
}
package minijava.syntax;
/**
* Represents {@code array[index]}.
*/
public class ExpArrayGet extends Exp {
private final Exp array;
private final Exp index;
public ExpArrayGet(Exp array, Exp index) {
this.array = array;
this.index = index;
}
public Exp getArray() {
return array;
}
public Exp getIndex() {
return index;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents {@code array.length}.
*/
public class ExpArrayLength extends Exp {
private final Exp array;
public ExpArrayLength(Exp body) {
this.array = body;
}
public Exp getArray() {
return array;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T{
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents {@code left op right}.
*/
public class ExpBinOp extends Exp {
public enum Op {
// note: there is no OR in MiniJava
PLUS("+"), MINUS("-"), TIMES("*"), DIV("/"), AND("&&"), LT("<");
private final String name;
Op(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
private final Exp left;
private final Op op;
private final Exp right;
public ExpBinOp(Exp e1, Op op, Exp e2) {
this.left = e1;
this.op = op;
this.right = e2;
}
public Exp getLeft() {
return left;
}
public Op getOp() {
return op;
}
public Exp getRight() {
return right;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents {@code false}.
*/
public class ExpFalse extends Exp {
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents a variable {@code id}.
*/
public class ExpId extends Exp {
private final String id;
public ExpId(String id) {
this.id = id;
}
public String getId() {
return id;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T{
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents a constant number {@code value}.
*/
public class ExpIntConst extends Exp {
private final int value;
public ExpIntConst(int value) {
this.value = value;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T{
return v.visit(this);
}
public int getValue() {
return value;
}
}
package minijava.syntax;
import minijava.analysis.SymbolTable;
import java.util.Collections;
import java.util.List;
/**
* Represents a method call {@code obj.method(args)}.
*/
public class ExpInvoke extends Exp {
private final Exp obj;
private final String method;
private final List<Exp> args;
public ExpInvoke(Exp obj, String method, List<Exp> args) {
this.obj = obj;
this.method = method;
this.args = args;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T{
return v.visit(this);
}
public Exp getObj() {
return obj;
}
public String getMethod() {
return method;
}
public List<Exp> getArgs() {
return Collections.unmodifiableList(args);
}
}
package minijava.syntax;
/**
* Represents {@code !exp}.
*/
public class ExpNeg extends Exp {
private final Exp exp;
public ExpNeg(Exp exp) {
this.exp = exp;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
public Exp getExp() {
return exp;
}
}
package minijava.syntax;
/**
* Represents {@code new ClassName}.
*/
public class ExpNew extends Exp {
private final String className;
public ExpNew(String className) {
this.className = className;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
public String getClassName() {
return className;
}
}
package minijava.syntax;
/**
* Represents {@code new int[size]}.
*/
public class ExpNewIntArray extends Exp {
private final Exp size;
public ExpNewIntArray(Exp size) {
this.size = size;
}
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
public Exp getSize() {
return size;
}
}
package minijava.syntax;
/**
* Represents {@code System.in.read()}.
*/
public class ExpRead extends Exp {
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents {@code this}.
*/
public class ExpThis extends Exp {
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T {
return v.visit(this);
}
}
package minijava.syntax;
/**
* Represents {@code true}.
*/
public class ExpTrue extends Exp {
@Override
public <A, T extends Throwable> A accept(ExpVisitor<A, T> v) throws T{
return v.visit(this);
}
}
package minijava.syntax;
public interface ExpVisitor<A, T extends Throwable> {
A visit(ExpTrue e) throws T;
A visit(ExpFalse e) throws T;
A visit(ExpThis e) throws T;
A visit(ExpNewIntArray e) throws T;
A visit(ExpNew e) throws T;
A visit(ExpNeg e) throws T;
A visit(ExpBinOp e) throws T;
A visit(ExpArrayGet e) throws T;
A visit(ExpArrayLength e) throws T;
A visit(ExpInvoke e) throws T;
A visit(ExpRead e) throws T;
A visit(ExpIntConst e) throws T;
A visit(ExpId e) throws T;
}
package minijava.syntax;
public class MainClassDeclaration {
private final String className;
private final String mainArg;
private final Stm mainBody;
private final boolean throwsIOException;
public MainClassDeclaration(String className, String mainArg, boolean throwsIOException, Stm mainBody) {
this.className = className;
this.mainArg = mainArg;
this.throwsIOException = throwsIOException;
this.mainBody = mainBody;
}
public String getClassName() {
return className;
}
public String getMainArg() {
return mainArg;
}
public boolean throwsIOException() {
return throwsIOException;
}
public Stm getMainBody() {
return mainBody;
}
}
package minijava.syntax;
import java.util.Collections;
import java.util.List;
public class MethodDeclaration {
private final Type returnType;
private final Boolean throwsIOException;
private final String methodName;
private final List<Parameter> parameters;
private final List<VariableDeclaration> localVars;
private final Stm body;
private final Exp returnExp;
public MethodDeclaration(Type returnType,
boolean throwsIOException,
String methodName,
List<Parameter> parameters,
List<VariableDeclaration> localVars,
Stm body,
Exp returnExp) {
this.returnType = returnType;
this.throwsIOException = throwsIOException;
this.methodName = methodName;
this.parameters = parameters;
this.localVars = localVars;
this.body = body;
this.returnExp = returnExp;
}
public Type getReturnType() {
return returnType;
}
public Boolean throwsIOException() {
return throwsIOException;
}
public String getMethodName() {
return methodName;
}
public List<Parameter> getParameters() {
return Collections.unmodifiableList(parameters);
}
public List<VariableDeclaration> getLocalVars() {
return Collections.unmodifiableList(localVars);
}
public Stm getBody() {
return body;
}
public Exp getReturnExp() {
return returnExp;
}
}
package minijava.syntax;
public class Parameter {
private final String id;
private final Type type;
public Parameter(String id, Type type) {
this.id = id;
this.type = type;
}
public String getId() {
return id;
}
public Type getType() {
return type;
}
}
package minijava.syntax;
import java.util.List;
/** Einfacher (nicht effizienter) Prettyprinter, der MiniJava-AST-Werte als Java-Text ausgeben kann. */
public class PrettyPrint {
private static final String indentStep = " ";
public static String prettyPrint(Program p) {
return prettyPrintMain(p.mainClass, "") + "\n" +
prettyPrintClassList(p.classes, "");
}
private static String prettyPrintClass(ClassDeclaration c, String indent) {
return indent + "class " + c.getClassName() +
(c.getSuperName() == null ? " " : " extends " + c.getSuperName() + " ") + "{\n\n" +
prettyPrintVarList(c.getFields(), indent + indentStep) +
prettyPrintMethList(c.getMethods(), indent + indentStep) +
indent + "}\n";
}
private static String prettyPrintClassList(List<ClassDeclaration> cl, String indent) {
StringBuilder classes = new StringBuilder();
String sep = "";
for (ClassDeclaration d : cl) {
classes.append(sep);
classes.append(prettyPrintClass(d, indent));
sep = "\n";
}
return classes.toString();
}
private static String prettyPrintMeth(MethodDeclaration m, String indent) {
StringBuilder params = new StringBuilder();
String sep = "";
for (Parameter p : m.getParameters()) {
params.append(sep).append(p.getType().accept(new PrettyPrintVisitorType())).append(" ").append(p.getId());
sep = ", ";
}
return indent + "public " +
m.getReturnType().accept(new PrettyPrintVisitorType()) + " " + m.getMethodName() +
" (" + params + ")" +
prettyPrintThrows(m.throwsIOException()) +
" {\n" +
prettyPrintVarList(m.getLocalVars(), indent + indentStep) +
m.getBody().accept(new PrettyPrintVisitorStm(indent + indentStep)) +
indent + indentStep +
"return " + m.getReturnExp().accept(new PrettyPrintVisitorExp()) + ";\n" +
indent + "}\n";
}
private static String prettyPrintMethList(List<MethodDeclaration> dm, String indent) {
StringBuilder meths = new StringBuilder();
for (MethodDeclaration m : dm) {
meths.append("\n");
meths.append(prettyPrintMeth(m, indent));
}
return meths.toString();
}
private static String prettyPrintVar(VariableDeclaration d, String indent) {
return indent + d.getType().accept(new PrettyPrintVisitorType()) + " " +
d.getName() + ";";
}
private static String prettyPrintVarList(List<VariableDeclaration> dl, String indent) {
StringBuilder decls = new StringBuilder();
for (VariableDeclaration d : dl) {
decls.append(prettyPrintVar(d, indent));
decls.append("\n");
}
return decls.toString();
}
private static String prettyPrintMain(MainClassDeclaration d, String indent) {
return indent + "class " + d.getClassName() + " {\n" +
indent + indentStep + "public static void main (String[] " +
d.getMainArg() + ")" +
prettyPrintThrows(d.throwsIOException()) +
" {\n" +
d.getMainBody().accept(new PrettyPrintVisitorStm(indent + indentStep + indentStep)) +
indent + indentStep + "}\n" +
indent + "}\n";
}
private static String prettyPrintThrows(boolean throwsIOException) {
if (throwsIOException) {
return " throws java.io.IOException";
} else {
return "";
}
}
static class PrettyPrintVisitorType implements TypeVisitor<String> {
@Override
public String visit(TypeVoid x) {
return "void";
}
@Override
public String visit(TypeBoolean x) {
return "boolean";
}
@Override
public String visit(TypeInt x) {
return "int";
}
@Override
public String visit(TypeClass x) {
return x.getName();
}
@Override
public String visit(TypeArray x) {
return x.getEntryType().accept(this) + "[]";
}
}
static class PrettyPrintVisitorExp implements ExpVisitor<String, RuntimeException> {
@Override
public String visit(ExpTrue x) {
return "true";
}
@Override
public String visit(ExpFalse x) {
return "false";
}
@Override
public String visit(ExpThis x) {
return "this";
}
@Override
public String visit(ExpNewIntArray x) {
return "new int [" + x.getSize().accept(this) + "]";
}
@Override
public String visit(ExpNew x) {
return "new " + x.getClassName() + "()";
}
@Override
public String visit(ExpBinOp e) {
return "(" + e.getLeft().accept(this) + e.getOp().toString() + e.getRight().accept(this) + ")";
}
@Override
public String visit(ExpArrayGet e) {
return e.getArray().accept(this) + "[" + e.getIndex().accept(this) + "]";
}
@Override
public String visit(ExpArrayLength e) {
return e.getArray().accept(this) + ".length";
}
@Override
public String visit(ExpInvoke e) {
StringBuilder args = new StringBuilder();
String sep = "";
for (Exp ea : e.getArgs()) {
args.append(sep).append(ea.accept(new PrettyPrintVisitorExp()));
sep = ", ";
}
return e.getObj().accept(this) + "." + e.getMethod() + "(" + args + ")";
}
@Override
public String visit(ExpRead e) {
return "System.in.read()";
}
@Override
public String visit(ExpIntConst x) {
return (new Integer(x.getValue())).toString();
}
@Override
public String visit(ExpId x) {
return x.getId();
}
@Override
public String visit(ExpNeg x) {
return "!(" + x.getExp().accept(this) + ")";
}
}
static class PrettyPrintVisitorStm implements StmVisitor<String, RuntimeException> {
final String indent;
public PrettyPrintVisitorStm() {
this.indent = "";
}
public PrettyPrintVisitorStm(String indent) {
this.indent = indent;
}
@Override
public String visit(StmSeq slist) {
StringBuilder str = new StringBuilder();
for (Stm s : slist.getStmList()) {
str.append(s.accept(new PrettyPrintVisitorStm(indent)));
}
return str.toString();
}
@Override
public String visit(StmIf s) {
return indent + "if (" + s.getCond().accept(new PrettyPrintVisitorExp()) + ") {\n" +
s.getTrueBranch().accept(new PrettyPrintVisitorStm(this.indent + indentStep)) +
indent + "} else {\n" +
s.getFalseBranch().accept(new PrettyPrintVisitorStm(this.indent + indentStep)) +
indent + "}\n";
}
@Override
public String visit(StmWhile s) {
return indent + "while (" +
s.getCond().accept(new PrettyPrintVisitorExp()) + ") {\n" +
s.getBody().accept(new PrettyPrintVisitorStm(this.indent + " ")) +
indent + "}\n";
}
@Override
public String visit(StmPrintln s) {
return indent + "System.out.println(" +
s.getArg().accept(new PrettyPrintVisitorExp()) + ");\n";
}
@Override
public String visit(StmWrite s) {
return indent + "System.out.write(" +
s.getExp().accept(new PrettyPrintVisitorExp()) + ");\n";
}
@Override
public String visit(StmAssign s) {
return indent + s.getId() + " = " +
s.getExp().accept(new PrettyPrintVisitorExp()) + ";\n";
}
@Override
public String visit(StmArrayAssign s) {
return indent + s.getId() +
"[" + s.getIndexExp().accept(new PrettyPrintVisitorExp()) + "] = " +
s.getExp().accept(new PrettyPrintVisitorExp()) + ";\n";
}
}
}
package minijava.syntax;
import java.util.List;
public class Program {
final public MainClassDeclaration mainClass;
final public List<ClassDeclaration> classes;
public Program(MainClassDeclaration mainClass, List<ClassDeclaration> classes) {
this.mainClass = mainClass;
this.classes = classes;
}
@SuppressWarnings("unused")
public String prettyPrint() {
return PrettyPrint.prettyPrint(this);
}
}
package minijava.syntax;
public abstract class Stm {
public abstract <A, T extends Throwable> A accept(StmVisitor<A, T> v) throws T;
public String prettyPrint() {
return accept(new PrettyPrint.PrettyPrintVisitorStm());
}
}
package minijava.syntax;
/**
* Represents {@code id[index] = exp;}.
*/
public class StmArrayAssign extends Stm {
private final String id;
private final Exp index;
private final Exp exp;
public StmArrayAssign(String id, Exp index, Exp exp) {
this.id = id;
this.index = index;
this.exp = exp;
}
@Override
public <A, T extends Throwable> A accept(StmVisitor<A, T> v) throws T {
return v.visit(this);
}
public String getId() {
return id;
}
public Exp getIndexExp() {
return index;
}
public Exp getExp() {
return exp;
}
}