package eu.wietsevenema.lang.oberon.ast.visitors.interpreter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import xtc.tree.Node;
import xtc.tree.Visitor;
import eu.wietsevenema.lang.oberon.ast.declarations.Declarations;
import eu.wietsevenema.lang.oberon.ast.declarations.FormalVar;
import eu.wietsevenema.lang.oberon.ast.declarations.Module;
import eu.wietsevenema.lang.oberon.ast.declarations.ProcedureDecl;
import eu.wietsevenema.lang.oberon.ast.declarations.RecordSelector;
import eu.wietsevenema.lang.oberon.ast.declarations.TypeDecl;
import eu.wietsevenema.lang.oberon.ast.declarations.VarDecl;
import eu.wietsevenema.lang.oberon.ast.expressions.ArraySelector;
import eu.wietsevenema.lang.oberon.ast.expressions.BinaryExpression;
import eu.wietsevenema.lang.oberon.ast.expressions.BooleanConstant;
import eu.wietsevenema.lang.oberon.ast.expressions.Identifier;
import eu.wietsevenema.lang.oberon.ast.expressions.IntegerConstant;
import eu.wietsevenema.lang.oberon.ast.expressions.LogicalNegationExpression;
import eu.wietsevenema.lang.oberon.ast.expressions.TestExpression;
import eu.wietsevenema.lang.oberon.ast.expressions.UnaryMinExpression;
import eu.wietsevenema.lang.oberon.ast.statements.AssignmentStatement;
import eu.wietsevenema.lang.oberon.ast.statements.ProcedureCallStatement;
import eu.wietsevenema.lang.oberon.ast.statements.WhileStatement;
import eu.wietsevenema.lang.oberon.ast.statements.WithStatement;
import eu.wietsevenema.lang.oberon.ast.types.BooleanType;
import eu.wietsevenema.lang.oberon.ast.types.IntegerType;
import eu.wietsevenema.lang.oberon.ast.types.RecordType;
import eu.wietsevenema.lang.oberon.ast.types.TypeAlias;
import eu.wietsevenema.lang.oberon.ast.types.VarType;
/**
* JSON like printer van AST.
*
* @author wietse
*
*/
public class ModulePrinter extends Visitor {
public String visit(TestExpression exp) {
return (String) dispatch(exp.getChild());
}
public String visit(IntegerConstant ic) {
return "" + ic.getValue();
}
public String visit(BooleanConstant ic) {
if (ic.getValue()) {
return "true";
} else {
return "false";
}
}
public String visit(RecordType record) {
ArrayList<String> entries = new ArrayList<String>();
for (Map.Entry<Identifier, VarType> entry : record.entrySet()) {
entries.add(dispatch(entry.getKey()) + ":" + dispatch(entry.getValue()));
}
return printNode(record, "{" + join(entries, ",") + "}");
}
public String visit(Identifier id) {
return id.getName();
}
public String visit(BinaryExpression exp) {
return printNode(exp, (String) dispatch(exp.getLeft()), (String) this.dispatch(exp.getRight()));
}
public String visit(ArraySelector as) {
return printNode(as, (String) dispatch(as.getLeft()), (String) dispatch(as.getIndex()));
}
public String visit(RecordSelector rs) {
return printNode(rs, (String) dispatch(rs.getLeft()), (String) dispatch(rs.getKey()));
}
private String printNode(Node parent) {
return parent.getClass().getSimpleName();
}
private String printNode(Node parent, String child) {
return printNode(parent) + "[" + child + "]";
}
private String printNode(Node parent, String child1, String child2) {
return printNode(parent) + "[" + child1 + "," + child2 + "]";
}
private String printNode(Node parent, String child1, String child2, String child3) {
return printNode(parent) + "[" + child1 + "," + child2 + "," + child3 + "]";
}
private String printNode(Node parent, String child1, String child2, String child3, String child4) {
return printNode(parent) + "[" + child1 + "," + child2 + "," + child3 + "," + child4 + "]";
}
private String printNodes(List<? extends Node> ns) {
if (ns.isEmpty()) {
return "{}";
}
String delimiter = ",";
ArrayList<String> strings = new ArrayList<String>();
for (Object n : ns) {
strings.add((String) dispatch((Node) n));
}
return "{" + join(strings, delimiter) + "}";
}
public String visit(LogicalNegationExpression lne) {
return printNode(lne, (String) dispatch(lne.getChild()));
}
public String visit(UnaryMinExpression un) {
return printNode(un, (String) dispatch(un.getChild()));
}
public String visit(Declarations decls) {
return printNode(decls, printNodes(decls.getConstants()), printNodes(decls.getTypes()),
printNodes(decls.getVars()), printNodes(decls.getProcedures()));
}
public String visit(IntegerType it){
return "INTEGER";
}
public String visit(BooleanType bt){
return "BOOLEAN";
}
public String visit(TypeAlias ta){
return ta.getIdentifier().getName();
}
public String visit(VarDecl vd) {
return printNode(vd, printNodes(vd.getIdentifiers()), (String) dispatch(vd.getType()));
}
public String visit(TypeDecl td) {
return printNode(td, td.getIdentifier().getName(), "" + dispatch(td.getType()));
}
public String visit(ProcedureDecl pd) {
return printNode(pd, pd.getIdentifier().getName(), printNodes(pd.getFormalVars()),
(String) dispatch(pd.getDeclarations()), printNodes(pd.getStatements()));
}
public String visit(AssignmentStatement as) {
return printNode(as, (String) dispatch(as.getIdentifier()), (String) dispatch(as.getExpression()));
}
public String visit(FormalVar fv) {
return printNode(fv, fv.getIdentifier().getName(), dispatch(fv.getType()) + "");
}
public String visit(Module m) {
return printNode(m, m.getIdentifier().getName(), (String) dispatch(m.getDeclarations()),
printNodes(m.getStats()));
}
public String visit(ProcedureCallStatement pcs) {
return printNode(pcs, pcs.getIdentifier().getName(), printNodes(pcs.getParameters()));
}
public String visit(WhileStatement whileStat) {
return printNode(whileStat, (String) dispatch(whileStat.getCondition()), printNodes(whileStat.getStatements()));
}
public String visit(WithStatement whileStat) {
return printNode(whileStat, (String) dispatch(whileStat.getRecord()), printNodes(whileStat.getStatements()));
}
private static String join(List<String> s, String delimiter) {
if (s.isEmpty()) {
return "";
}
Iterator<String> iter = s.iterator();
StringBuffer buffer = new StringBuffer(iter.next());
while (iter.hasNext())
buffer.append(delimiter).append(iter.next());
return buffer.toString();
}
}