package de.psi.alloy4smt.smt; import java.util.Arrays; import java.util.List; import java.util.Vector; public abstract class SExpr<V> { public static<V> SExpr<V> num(int i) { return new Symbol<V>(String.valueOf(i)); } public static<V> SExpr<V> sym(String name) { return new Symbol<V>(name); } public static<V> SExpr<V> leaf(V leaf) { return new Leaf<V>(leaf); } public static<V> SExpr<V> call(String funcName, SExpr<V>... args) { List<SExpr<V>> l = new Vector<SExpr<V>>(); l.add(new Symbol<V>(funcName)); l.addAll(Arrays.asList(args)); return new SList<V>(l); } public static<V> SExpr<V> and(SExpr<V>... args) { if (args.length > 1) { return call("and", args); } else if (args.length == 1) { return args[0]; } else { return new Symbol<V>("#t"); } } public static<V> SExpr<V> add(SExpr<V>... args) { return SExpr.<V>call("+", args); } public static<V> SExpr<V> eq(SExpr<V>... args) { return SExpr.<V>call("=", args); } public static class Symbol<V> extends SExpr<V> { private final String name; public Symbol(String name) { this.name = name; } public String getName() { return name; } @Override public String toString() { return name; } @Override public <T> T accept(Visitor<V, T> vtVisitor) { return vtVisitor.visit(this); } } public static class Leaf<V> extends SExpr<V> { private final V value; public Leaf(V item) { this.value = item; } public V getValue() { return value; } @Override public <T> T accept(Visitor<V, T> vtVisitor) { return vtVisitor.visit(this); } @Override public String toString() { return value.toString(); } } public static class SList<V> extends SExpr<V> { private final List<SExpr<V>> items; public SList(List<SExpr<V>> items) { this.items = items; } public List<SExpr<V>> getItems() { return items; } @Override public String toString() { boolean first = true; StringBuilder sb = new StringBuilder(); sb.append("("); for (SExpr expr : items) { if (first) first = false; else sb.append(" "); sb.append(expr.toString()); } sb.append(")"); return sb.toString(); } @Override public <T> T accept(Visitor<V, T> vtVisitor) { return vtVisitor.visit(this); } } public static abstract class Visitor<V, T> { public final T visitThis(SExpr<V> x) { return x.accept(this); } public abstract T visit(Symbol<V> vSymbol); public abstract T visit(Leaf<V> vLeaf); public abstract T visit(SList<V> vsList); } public abstract<T> T accept(Visitor<V, T> vtVisitor); }