proplogPP
proplogPP is an example of a pretty printer for propositional logic using Rexastor. You can download all the sources in a package proplogPP.tar.gz.
The example contains the following files:
- pl.rx a description of the Abstract Syntax Trees as given to the code-generator
- subtypes.dot the subtyping relation on generated classes
- PP.java source-code of the pretty printer
- MinVisitor.java source-code of a minimal visitor stub with memoization, partially generated by the tool
- TestPP.java a runnable testing example
pl.rx
package pl; builtin String; // no code is generated for builtin types labels var, or, and, not, xor, imp; alias Var -> var[String]; // Var is an alias for var[String], the corresponding Java type will be called Var /////////// General Prop Log //////////////// alias Pl.Or -> or[Pl.F, Pl.F]; // "Propositional logic Or" will be an inner class of Pl alias Pl.And -> and[Pl.F,Pl.F]; alias Pl.Not -> not[Pl.F]; alias Pl.Xor -> xor[Pl.F,Pl.F]; alias Pl.Imp -> imp[Pl.F,Pl.F]; type Pl.F=Pl.Or | Pl.And | Pl.Not | Pl.Xor | Pl.Imp | Var ; /////////// CNF //////////////// alias CNF.And -> and[CNF.F,CNF.F]; // "CNF And" will be an inner class of CNF alias CNF.Or -> or[CNF.Clause, CNF.Clause]; alias CNF.Not -> not[Var]; type CNF.F=CNF.Clause | CNF.And ; type CNF.Clause = CNF.Lit | CNF.Or ; type CNF.Lit = Var | CNF.Not ;
The subtyping relation on generated classes
Test example
TestPP.java contains a small testing class which demonstrates
the pretty printer as well as the subtyping of the generated code.
import pl.Pl; // import Propositional logic
import pl.CNF; // import CNF logic
// statically import all constructs common to both logics
import static pl.Common.*;
/**
* A tiny testing class for {@code PP} and subtyping on formulas.
* @author Mikolas Janota
*/
public class TestPP {
public static void main(String[] args) {
// Construction is done through static functions
// for conciseness reasons.
// prepare a couple of variables
Var a=Var("a");
Var b=Var("b");
Var c=Var("c");
// construct two Propositional Logic formulas
Pl.F f = Pl.Not(Pl.And(a, b));
Pl.F f1 = Pl.Xor(a, c);
// and one CNF formula
CNF.F cnf = CNF.And(a, CNF.Not(b));
// print via PP
PP pp=new PP();
System.out.println(pp.print(f));
System.out.println(pp.print(f1));
System.out.println(pp.print(cnf));
// the following just shows that subtyping works as expected
Pl.F fFoo=cnf; // OK
Pl.And fAnd=CNF.And(a, c); // OK
CNF.F And1=CNF.And(a, c); // OK
// uncommenting causes compilation error
// And1=fAnd;
// fAnd=And1;
// CNF.F cnfFoo=f1; // not OK
// CNF.F cnfBar=CNF.Or(CNF.And(a, b), c);
}
}
Pretty printer
Source of the pretty printer is contained in PP.java:
import static pl.Pl.*; // import all constructs for Propositional Logic
import static pl.Common.*; // import all constructs common for all Logics
/**
* A simple purely functional infix printer for Propositional Logic.
* @author Mikolas Janota
*/
public class PP extends MinVisitor<String> {
private static String p(String s) { return "(" + s + ")"; }
/** Converts a given formula to a String representation. */
public String print(F f) { return eval(f); }
@Override public String visit(Var v, String s) { return s; }
@Override public String visit(Xor n, String first, String second)
{return p(first) + " XOR " + p(second);}
@Override public String visit(Imp n, String first, String second)
{return p(first) + " => " + p(second);}
@Override public String visit(Or n, String first, String second)
{return p(first) + " OR " + p(second);}
@Override public String visit(Not n, String first)
{return "NOT" + p(first);}
@Override public String visit(And n, String first, String second)
{return p(first) + " AND " + p(second);}
}
Visitor
Minimal visitor with memoization, partially generated by the tool
is in the file MinVisitor.java:
import static pl.Common.*;
import pl.Pl;
import pl.CNF;
import java.util.HashMap;
/**
* A visitor stub for depth-first search traversal.
*/
public abstract class MinVisitor<R> implements Pl.FVisitor<R> {
private final HashMap<Pl.F, R> m=new HashMap<Pl.F, R>();
R eval(Pl.F n) {
// memoize
R retv=m.get(n);
if (retv!=null) return retv;
retv=n.accept(this);
m.put(n, retv);
return retv;
}
public final R visit(Var node) { return visit(node, node.getFirst()); }
public final R visit(Pl.Xor node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public final R visit(CNF.Not node) {
return visit(node, eval(node.getFirst()));
}
public final R visit(Pl.Imp node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public final R visit(CNF.Or node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public final R visit(Pl.Or node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public final R visit(Pl.Not node) {
return visit(node, eval(node.getFirst()));
}
public final R visit(CNF.And node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public final R visit(Pl.And node) {
return visit(node, eval(node.getFirst()), eval(node.getSecond()));
}
public abstract R visit(Var n, String first);
public abstract R visit(Pl.Xor n, R first, R second);
public abstract R visit(Pl.Imp n, R first, R second);
public abstract R visit(Pl.Or n, R first, R second);
public abstract R visit(Pl.And n, R first, R second);
public abstract R visit(Pl.Not n, R first);
// run parent visit methods
public R visit(CNF.Not n, R first) {return visit((Pl.Not)n);}
public R visit(CNF.Or n, R first, R second) {return visit((Pl.Or)n);}
public R visit(CNF.And n, R first, R second) {return visit((Pl.And)n);}
}
