Renamed Node to Term, changed the API accordingly

This commit is contained in:
Fedor Isakov 2015-08-01 12:11:46 +02:00
parent 2fb992ead3
commit 5ee965a88d
11 changed files with 207 additions and 211 deletions

View File

@ -57,20 +57,20 @@ public class Substitution {
}
public static class Binding {
private Node myVar;
private Node myNode;
private Term myVar;
private Term myTerm;
public Binding(Node myVar, Node myNode) {
public Binding(Term myVar, Term myTerm) {
this.myVar = myVar;
this.myNode = myNode;
this.myTerm = myTerm;
}
public Node var() {
public Term var() {
return myVar;
}
public Node node() {
return myNode;
public Term term() {
return myTerm;
}
}

View File

@ -26,17 +26,15 @@ import java.util.Collection;
* A term must implement {@link java.lang.Comparable}, but this is only really used for
* comparing the variables.
*
* Soon to be renamed to Term.
*
* @author Fedor Isakov
*/
public interface Node extends Comparable<Node> {
public interface Term extends Comparable<Term> {
Object symbol();
Collection<? extends Node> children();
Collection<? extends Term> children();
Node get();
Term get();
boolean is(Kind kind);

View File

@ -28,7 +28,7 @@ import java.util.*;
*/
public class Unification {
public static Substitution unify(Node a, Node b) {
public static Substitution unify(Term a, Term b) {
UnionFindTermGraphUnifier dagUnifier = new UnionFindTermGraphUnifier();
return dagUnifier.unify(a, b);
@ -72,14 +72,14 @@ public class Unification {
String sep = "";
for (Binding b : myBindings) {
sb.append(sep); sep = ", ";
sb.append(b.var()).append(" -> ").append(b.node());
sb.append(b.var()).append(" -> ").append(b.term());
}
return sb.append("]").toString();
}
protected void addBinding(Node v, Node n) {
protected void addBinding(Term v, Term n) {
Binding bng;
if (n.is(Node.Kind.VAR) && n.compareTo(n) < 0) {
if (n.is(Term.Kind.VAR) && n.compareTo(n) < 0) {
bng = new Binding(n, v);
}
else {

View File

@ -21,7 +21,7 @@ import jetbrains.mps.unification.Unification.SuccessfulSubstitution;
import java.util.*;
import static jetbrains.mps.unification.Node.Kind.*;
import static jetbrains.mps.unification.Term.Kind.*;
import static jetbrains.mps.unification.Substitution.FailureCause.*;
import static jetbrains.mps.unification.Unification.*;
@ -53,7 +53,7 @@ public class UnionFindTermGraphUnifier {
private FailureCause myFailureCause = UKNOWN;
public Substitution unify(Node a, Node b) {
public Substitution unify(Term a, Term b) {
if (!unifClosure(a, b)) {
return failedSubstitution(myFailureCause);
}
@ -61,14 +61,14 @@ public class UnionFindTermGraphUnifier {
return findSolution(a);
}
private boolean unifClosure(Node s, Node t) {
private boolean unifClosure(Term s, Term t) {
s = find(s);
t = find(t);
if (s == t) return true;
Node zs = getSchema(s);
Node zt = getSchema(t);
Term zs = getSchema(s);
Term zt = getSchema(t);
// a VAR always matches another node
if(zs.is(VAR) || zt.is(VAR)) {
@ -77,8 +77,8 @@ public class UnionFindTermGraphUnifier {
}
// dereference REF nodes
Node ds = zs.is(REF) ? zs.get() : zs;
Node dt = zt.is(REF) ? zt.get() : zt;
Term ds = zs.is(REF) ? zs.get() : zs;
Term dt = zt.is(REF) ? zt.get() : zt;
if (ds.is(VAR)) {
if (s != find(ds)) {
@ -119,8 +119,8 @@ public class UnionFindTermGraphUnifier {
union(s, t);
}
Iterator<? extends Node> scit = zs.children().iterator();
Iterator<? extends Node> tcit = zt.children().iterator();
Iterator<? extends Term> scit = zs.children().iterator();
Iterator<? extends Term> tcit = zt.children().iterator();
while (scit.hasNext() && tcit.hasNext()) {
if (!unifClosure(scit.next(), tcit.next())) {
return false; // children mismatch
@ -136,18 +136,18 @@ public class UnionFindTermGraphUnifier {
}
}
private void union(Node s, Node t) {
private void union(Term s, Term t) {
int ssize = getSize(s);
int tsize = getSize(t);
// keep the order: the smaller class gets inserted under the bigger one
if (ssize < tsize) {
Node tmp = t; t = s; s = tmp;
Term tmp = t; t = s; s = tmp;
}
else if (ssize == tsize && s.is(VAR) && t.is(VAR)) {
// ensure proper order of variables in the substitution
if(t.compareTo(s) < 0) {
Node tmp = t; t = s; s = tmp;
Term tmp = t; t = s; s = tmp;
}
}
@ -156,8 +156,8 @@ public class UnionFindTermGraphUnifier {
setSize(s, ssize + tsize);
appendVars(s, getVars(t));
Node zs = getSchema(s);
Node zt = getSchema(t);
Term zs = getSchema(s);
Term zt = getSchema(t);
if (zs.is(VAR) || (zs.is(REF) && zs.get().is(VAR) && !zt.is(VAR)))
{
setSchema(s, zt);
@ -166,33 +166,33 @@ public class UnionFindTermGraphUnifier {
setRepresentative(t, s);
}
private Node find(Node s) {
Node node = getRepresentative(s);
if (node == s) {
private Term find(Term s) {
Term term = getRepresentative(s);
if (term == s) {
return s;
}
// find representative and compress paths
List<Node> path = new ArrayList<Node>();
path.add(node);
for (Node t; (t = getRepresentative(node)) != node; ) {
List<Term> path = new ArrayList<Term>();
path.add(term);
for (Term t; (t = getRepresentative(term)) != term; ) {
path.add(t);
node = t;
term = t;
}
for (Node p : path) {
setRepresentative(p, node);
for (Term p : path) {
setRepresentative(p, term);
}
return node;
return term;
}
private Substitution findSolution(Node s) {
private Substitution findSolution(Term s) {
return findSolution(s, EMPTY_SUBSTITUTION);
}
private Substitution findSolution(Node s, Substitution substitution) {
Node z = getSchema(find(s));
private Substitution findSolution(Term s, Substitution substitution) {
Term z = getSchema(find(s));
if (isAcyclic(z)) {
return substitution; // not part of a cycle
@ -204,7 +204,7 @@ public class UnionFindTermGraphUnifier {
if (z.is(FUN)) {
setVisited(z, true);
for (Node c : z.children()) {
for (Term c : z.children()) {
substitution = findSolution(c, substitution);
if (!substitution.isSuccessful()) {
@ -222,9 +222,9 @@ public class UnionFindTermGraphUnifier {
setAcyclic(z, true);
SuccessfulSubstitution success = new SuccessfulSubstitution(substitution);
for (Node var : getVars(find(z))) {
for (Term var : getVars(find(z))) {
if (var != z) {
Node val = z.is(REF) ? z.get() : z;
Term val = z.is(REF) ? z.get() : z;
// Keep the order of variables within a binding
if (val.is(VAR) && val.compareTo(var) < 0) {
@ -240,65 +240,65 @@ public class UnionFindTermGraphUnifier {
}
private int getSize(Node n) {
private int getSize(Term n) {
if (!hasData(n)) return 1;
return getData(n).mySize;
}
private void setSize(Node n, int size) {
private void setSize(Term n, int size) {
getData(n).mySize = size;
}
private Node getRepresentative(Node n) {
private Term getRepresentative(Term n) {
if (!hasData(n)) return n;
return getData(n).myClass;
}
private void setRepresentative(Node n, Node rep) {
private void setRepresentative(Term n, Term rep) {
getData(n).myClass = rep;
}
private Node getSchema(Node n) {
private Term getSchema(Term n) {
if (!hasData(n)) return n;
return getData(n).mySchema;
}
private void setSchema(Node n, Node schema) {
private void setSchema(Term n, Term schema) {
getData(n).mySchema = schema;
}
private List<Node> getVars(Node n) {
private List<Term> getVars(Term n) {
return hasData(n) ? getData(n).myVars : singletonVar(n);
}
private void appendVars(Node n, List<Node> vars) {
List<Node> newVars = new ArrayList<Node>(getVars(n));
private void appendVars(Term n, List<Term> vars) {
List<Term> newVars = new ArrayList<Term>(getVars(n));
newVars.addAll(vars);
getData(n).myVars = newVars;
}
private boolean isAcyclic(Node n) {
private boolean isAcyclic(Term n) {
return hasData(n) && getData(n).myAcyclic;
}
private void setAcyclic(Node n, boolean acyclic) {
private void setAcyclic(Term n, boolean acyclic) {
getData(n).myAcyclic = acyclic;
}
private boolean isVisited(Node n) {
private boolean isVisited(Term n) {
return hasData(n) && getData(n).myVisited;
}
private void setVisited(Node n, boolean visited) {
private void setVisited(Term n, boolean visited) {
getData(n).myVisited = visited;
}
private boolean hasData(Node n) {
private boolean hasData(Term n) {
Object key = n.is(VAR) ? String.valueOf(n.symbol()).intern() : n;
return myData.containsKey(key);
}
private Data getData(Node n) {
private Data getData(Term n) {
Object key = n.is(VAR) ? String.valueOf(n.symbol()).intern() : n;
if (myData.containsKey(key)) return myData.get(key);
Data data = new Data(n);
@ -310,10 +310,10 @@ public class UnionFindTermGraphUnifier {
return a == null ? b == null : a.equals(b);
}
private static List<Node> singletonVar(Node n) {
private static List<Term> singletonVar(Term n) {
return n.is(VAR) ?
Collections.singletonList(n) :
Collections.<Node>emptyList();
Collections.<Term>emptyList();
}
private static class Data {
@ -322,11 +322,11 @@ public class UnionFindTermGraphUnifier {
boolean myVisited = false;
boolean myReferenced = false;
List<Node> myVars;
Node myClass;
Node mySchema;
List<Term> myVars;
Term myClass;
Term mySchema;
Data(Node n) {
Data(Term n) {
myClass = n;
mySchema = n;
myVars = singletonVar(n);

View File

@ -16,7 +16,7 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import java.util.Arrays;
import java.util.Collection;
@ -28,8 +28,8 @@ import static org.junit.Assert.assertEquals;
*/
public class AssertAll {
public static void assertEqualsAll(Collection<Node> parsed, Node ... nodes) {
assertEquals(parsed, Arrays.asList(nodes));
public static void assertEqualsAll(Collection<Term> parsed, Term... terms) {
assertEquals(parsed, Arrays.asList(terms));
}
}

View File

@ -16,7 +16,7 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import static org.junit.Assert.*;
import java.util.*;
@ -26,24 +26,24 @@ import java.util.*;
*/
public class AssertStructurallyEquivalent {
public static void assertEquivalent(Node a, Node b) throws Exception {
public static void assertEquivalent(Term a, Term b) throws Exception {
final Signature signature = new Signature();
signature.setWalkers(
// first pass
new NodeWalker(
new NodeVisitor<Node>(Node.Kind.FUN) {
new TermWalker(
new TermVisitor<Term>(Term.Kind.FUN) {
@Override
public Collection<? extends Node> visit(Node term) throws Exception {
public Collection<? extends Term> visit(Term term) throws Exception {
signature.label(term);
return term.children();
}
}
,
new NodeVisitor<Node>(Node.Kind.REF) {
new TermVisitor<Term>(Term.Kind.REF) {
@Override
public Collection<? extends Node> visit(Node ref) throws Exception {
if (ref.get().is(Node.Kind.FUN)) {
public Collection<? extends Term> visit(Term ref) throws Exception {
if (ref.get().is(Term.Kind.FUN)) {
return Collections.singletonList(ref.get());
}
return Collections.emptyList();
@ -51,24 +51,24 @@ public class AssertStructurallyEquivalent {
}
),
// second pass
new NodeWalker(
new NodeVisitor<Node>(Node.Kind.FUN) {
new TermWalker(
new TermVisitor<Term>(Term.Kind.FUN) {
@Override
public Collection<? extends Node> visit(Node term) throws Exception {
public Collection<? extends Term> visit(Term term) throws Exception {
signature.appendSignature("@").append(signature.getLabel(term)).append(term.symbol());
return term.children();
}
},
new NodeVisitor<Node>(Node.Kind.VAR) {
new TermVisitor<Term>(Term.Kind.VAR) {
@Override
public Collection<? extends Node> visit(Node var) throws Exception {
public Collection<? extends Term> visit(Term var) throws Exception {
signature.appendSignature("$").append(var.symbol());
return Collections.emptyList();
}
}, new NodeVisitor<Node>(Node.Kind.REF) {
}, new TermVisitor<Term>(Term.Kind.REF) {
@Override
public Collection<? extends Node> visit(Node ref) throws Exception {
if (ref.get().is(Node.Kind.FUN)) {
public Collection<? extends Term> visit(Term ref) throws Exception {
if (ref.get().is(Term.Kind.FUN)) {
Integer label = signature.getLabel(ref.get());
assertNotNull("not found label for '" + ref.get() + "'", label);
if (signature.isTopLevel(ref.get())) {
@ -79,7 +79,7 @@ public class AssertStructurallyEquivalent {
return Collections.singletonList(ref.get());
}
}
else if (ref.get().is(Node.Kind.VAR)) {
else if (ref.get().is(Term.Kind.VAR)) {
signature.appendSignature("^").append(ref.get().symbol());
return Collections.emptyList();
}
@ -100,30 +100,30 @@ public class AssertStructurallyEquivalent {
private static class Signature {
private NodeWalker[] walkers;
private TermWalker[] walkers;
private IdentityHashMap<Node, Integer> labels = new IdentityHashMap<Node, Integer>();
private IdentityHashMap<Term, Integer> labels = new IdentityHashMap<Term, Integer>();
private int label = 1;
private StringBuilder signature = new StringBuilder();
protected void label(Node node) {
labels.put(node, label++);
protected void label(Term term) {
labels.put(term, label++);
}
protected Integer getLabel(Node node) {
return labels.get(node);
protected Integer getLabel(Term term) {
return labels.get(term);
}
protected boolean isTopLevel(Node node) { return labels.get(node) == 1; }
protected boolean isTopLevel(Term term) { return labels.get(term) == 1; }
protected StringBuilder appendSignature(String str) {
return signature.append(str);
}
public String getSignature (Node node) throws Exception {
public String getSignature (Term term) throws Exception {
reset();
for (NodeWalker walker : walkers) {
walker.walk(node);
for (TermWalker walker : walkers) {
walker.walk(term);
}
return signature.toString();
}
@ -134,51 +134,51 @@ public class AssertStructurallyEquivalent {
signature.setLength(0);
}
protected void setWalkers(NodeWalker ... walkers) {
protected void setWalkers(TermWalker... walkers) {
this.walkers = walkers;
}
}
private static abstract class NodeVisitor <T extends Node> {
private static abstract class TermVisitor<T extends Term> {
private Node.Kind kind;
private Term.Kind kind;
public NodeVisitor(Node.Kind kind) {
public TermVisitor(Term.Kind kind) {
this.kind = kind;
}
public Node.Kind applicableTo() {
public Term.Kind applicableTo() {
return kind;
}
public abstract Collection<? extends Node> visit(T t) throws Exception ;
public abstract Collection<? extends Term> visit(T t) throws Exception ;
}
private static class NodeWalker {
private static class TermWalker {
private static Object SINGLETON = new Object();
private Map<Node.Kind, NodeVisitor<? extends Node>> visitorMap = new HashMap<Node.Kind, NodeVisitor<? extends Node>>();
private Map<Term.Kind, TermVisitor<? extends Term>> visitorMap = new HashMap<Term.Kind, TermVisitor<? extends Term>>();
public NodeWalker(NodeVisitor<? extends Node>... visitors) {
for (NodeVisitor<? extends Node> visitor : visitors) {
public TermWalker(TermVisitor<? extends Term>... visitors) {
for (TermVisitor<? extends Term> visitor : visitors) {
visitorMap.put(visitor.applicableTo(), visitor);
}
}
public void walk(Node node) throws Exception {
walk(node, new IdentityHashMap<Node, Object>());
public void walk(Term term) throws Exception {
walk(term, new IdentityHashMap<Term, Object>());
}
private void walk(Node node, Map<Node, Object> visited) throws Exception {
if (node.is(Node.Kind.FUN)) {
visited.put(node, SINGLETON);
private void walk(Term term, Map<Term, Object> visited) throws Exception {
if (term.is(Term.Kind.FUN)) {
visited.put(term, SINGLETON);
}
Collection<? extends Node> children = switchClass(node);
for (Node child : children) {
Collection<? extends Term> children = switchClass(term);
for (Term child : children) {
if (visited.containsKey(child)) {
continue;
}
@ -186,11 +186,11 @@ public class AssertStructurallyEquivalent {
}
}
private Collection<? extends Node> switchClass(Node node) throws Exception {
for (Map.Entry<Node.Kind, NodeVisitor<? extends Node>> e : visitorMap.entrySet()) {
if (node.is(e.getKey())) {
NodeVisitor<Node> value = (NodeVisitor<Node>) e.getValue();
return value.visit(node);
private Collection<? extends Term> switchClass(Term term) throws Exception {
for (Map.Entry<Term.Kind, TermVisitor<? extends Term>> e : visitorMap.entrySet()) {
if (term.is(e.getKey())) {
TermVisitor<Term> value = (TermVisitor<Term>) e.getValue();
return value.visit(term);
}
}
return Collections.emptyList();

View File

@ -19,7 +19,7 @@ package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Substitution;
import static jetbrains.mps.unification.Substitution.*;
import jetbrains.mps.unification.Unification;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import java.util.*;
@ -39,7 +39,7 @@ public class AssertUnification {
}
};
public static Binding bind(Node v, Node n) {
public static Binding bind(Term v, Term n) {
return new Binding(v, n);
}
@ -56,12 +56,12 @@ public class AssertUnification {
Binding actb = actIt.next();
assertEquals(expb.var(), actb.var());
assertEquivalent(expb.node(), actb.node());
assertEquivalent(expb.term(), actb.term());
}
if(expIt.hasNext() || actIt.hasNext()) throw new Exception("mismatched number of bindings");
}
public static void assertUnifiesWithBindings(Node s, Node t, Substitution.Binding ... bindings) throws Exception{
public static void assertUnifiesWithBindings(Term s, Term t, Substitution.Binding ... bindings) throws Exception{
Substitution subs = Unification.unify(s, t);
assertTrue(subs.isSuccessful());
@ -77,7 +77,7 @@ public class AssertUnification {
assertSameBindings(subs.bindings(), subs2.bindings());
}
public static void assertUnifiesWithBindingsAsymm(Node s, Node t, Substitution.Binding ... bindings) throws Exception{
public static void assertUnifiesWithBindingsAsymm(Term s, Term t, Substitution.Binding ... bindings) throws Exception{
Substitution subs = Unification.unify(s, t);
assertTrue(subs.isSuccessful());
@ -88,7 +88,7 @@ public class AssertUnification {
subs.bindings());
}
public static void assertUnificationFails(Node s, Node t) throws Exception {
public static void assertUnificationFails(Term s, Term t) throws Exception {
Substitution subs1 = Unification.unify(s, t);
assertFalse(subs1.isSuccessful());
@ -98,7 +98,7 @@ public class AssertUnification {
assertFalse(subs2.isSuccessful());
}
public static void assertUnificationFails(Node s, Node t, FailureCause failureCause) throws Exception {
public static void assertUnificationFails(Term s, Term t, FailureCause failureCause) throws Exception {
Substitution subs1 = Unification.unify(s, t);
assertFalse(subs1.isSuccessful());

View File

@ -16,36 +16,36 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import java.util.*;
/**
* Created by fyodor on 09.06.2014.
*/
public abstract class MockNode implements Node {
public abstract class MockTerm implements Term {
public MockNode() {
public MockTerm() {
}
public static Node term(Object sym, Node ... children) {
return new MockTerm(sym, children);
public static Term term(Object sym, Term... children) {
return new MockFun(sym, children);
}
public static Node var(String name) {
public static Term var(String name) {
return new MockVar(name);
}
public static Node ref(Node term) {
public static Term ref(Term term) {
return new MockRef(term);
}
public static Node ref(TermLookup termLookup) {
public static Term ref(TermLookup termLookup) {
return new MockRef(termLookup);
}
interface TermLookup {
Node lookupTerm();
Term lookupTerm();
}
@Override
@ -54,27 +54,27 @@ public abstract class MockNode implements Node {
}
@Override
public Collection<? extends Node> children() {
public Collection<? extends Term> children() {
return null;
}
@Override
public Node get() {
public Term get() {
return this;
}
@Override
public int compareTo(Node node) {
return String.valueOf(symbol()).compareTo(String.valueOf(node.symbol()));
public int compareTo(Term term) {
return String.valueOf(symbol()).compareTo(String.valueOf(term.symbol()));
}
public static class MockTerm extends MockNode {
private List<Node> myChildren;
public static class MockFun extends MockTerm {
private List<Term> myArgs;
private Object mySymbol;
public MockTerm(Object symbol, Node... children) {
public MockFun(Object symbol, Term... children) {
mySymbol = symbol;
this.myChildren = Arrays.asList(children);
this.myArgs = Arrays.asList(children);
}
@Override
@ -83,8 +83,8 @@ public abstract class MockNode implements Node {
}
@Override
public Collection<Node> children() {
return Collections.unmodifiableList(myChildren);
public Collection<Term> children() {
return Collections.unmodifiableList(myArgs);
}
@Override
@ -95,10 +95,10 @@ public abstract class MockNode implements Node {
@Override
public String toString() {
StringBuilder sb = new StringBuilder(String.valueOf(mySymbol));
if (!myChildren.isEmpty()) {
if (!myArgs.isEmpty()) {
sb.append("{");
String sep = "";
for (Node child : myChildren) {
for (Term child : myArgs) {
sb.append(sep); sep = " ";
sb.append(child.toString());
}
@ -110,17 +110,17 @@ public abstract class MockNode implements Node {
@Override
public int hashCode() {
int hash = 43 + mySymbol.hashCode();
return hash*19 + myChildren.hashCode();
return hash*19 + myArgs.hashCode();
}
@Override
public boolean equals(Object o) {
return ((MockTerm)o).mySymbol.equals(mySymbol) &&
((MockTerm)o).myChildren.equals(myChildren);
return ((MockFun)o).mySymbol.equals(mySymbol) &&
((MockFun)o).myArgs.equals(myArgs);
}
}
public static class MockVar extends MockNode {
public static class MockVar extends MockTerm {
private String myName;
public MockVar(String name) {
@ -154,12 +154,12 @@ public abstract class MockNode implements Node {
}
public static class MockRef extends MockNode {
public static class MockRef extends MockTerm {
private Node term;
private Term term;
private TermLookup termLookup;
public MockRef(Node term) {
public MockRef(Term term) {
this.term = term;
}
@ -168,7 +168,7 @@ public abstract class MockNode implements Node {
}
@Override
public final Node get() {
public final Term get() {
if (term == null && termLookup != null) {
term = termLookup.lookupTerm();
termLookup = null;
@ -183,7 +183,7 @@ public abstract class MockNode implements Node {
@Override
public String toString() {
Node t = get();
Term t = get();
return t != null ? "^"+ t.symbol() : "^<NULL>";
}
@ -192,12 +192,12 @@ public abstract class MockNode implements Node {
if (that == this) return true;
if (that == null || getClass() != that.getClass()) return false;
return get() == ((MockNode) that).get();
return get() == ((MockTerm) that).get();
}
@Override
public int hashCode() {
Node t = get();
Term t = get();
return t != null ? System.identityHashCode(t) : 0;
}
}

View File

@ -16,36 +16,36 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static jetbrains.mps.unification.test.MockNode.*;
import static jetbrains.mps.unification.test.MockTerm.*;
/**
* Created by fyodor on 10.06.2014.
*/
public class MockTreeParser {
public class MockTermsParser {
public static Collection<Node> parseAll(String str) {
public static Collection<Term> parseAll(String str) {
return new RecursiveDescent().parse(str);
}
public static Node parse(String str) {
List<Node> nodes = new RecursiveDescent().parse(str);
if (nodes.size() != 1) {
public static Term parse(String str) {
List<Term> terms = new RecursiveDescent().parse(str);
if (terms.size() != 1) {
throw new IllegalArgumentException("expected single asTerm or asVar");
}
return nodes.get(0);
return terms.get(0);
}
public static Node parseTerm(String str) {
return (Node) parse(str);
public static Term parseTerm(String str) {
return parse(str);
}
public static Node parseVar(String str) {
public static Term parseVar(String str) {
return parse(str);
}
@ -54,19 +54,19 @@ public class MockTreeParser {
private Token lastToken;
private LinkedList<String> termsStack = new LinkedList<String>();
private LinkedList<Integer> termLabelsStack = new LinkedList<Integer>();
private LinkedList<List<Node>> childrenStack = new LinkedList<List<Node>>();
private LinkedList<List<Term>> childrenStack = new LinkedList<List<Term>>();
private int lastLabel = -1;
private Map<Integer, Node> termRefs = new HashMap<Integer, Node>();
private Map<Integer, Term> termRefs = new HashMap<Integer, Term>();
// initialized on the parse finished
private LookupHelper lookupHelper = new LookupHelper();
private List<Node> parse(String toParse) {
private List<Term> parse(String toParse) {
parseNextToken(Token.START, null);
loop(toParse);
parseNextToken(Token.END, null);
checkFinalState();
checkAllRefsExist();
lookupHelper.setTermRefs(Collections.unmodifiableMap(new HashMap<Integer, Node>(termRefs)));
lookupHelper.setTermRefs(Collections.unmodifiableMap(new HashMap<Integer, Term>(termRefs)));
return Collections.unmodifiableList(childrenStack.pop());
}
@ -93,7 +93,7 @@ public class MockTreeParser {
private void parseNextToken(Token token, String value) {
switch (token) {
case START:
childrenStack.push(new ArrayList<Node>());
childrenStack.push(new ArrayList<Term>());
break;
case END:
checkLastTokenOneOf(Token.TERM, Token.VAR, Token.VARREF, Token.RBRACE);
@ -183,7 +183,7 @@ public class MockTreeParser {
}
private void checkAllRefsExist() {
for (Map.Entry<Integer, Node> e: termRefs.entrySet()) {
for (Map.Entry<Integer, Term> e: termRefs.entrySet()) {
if (e.getValue() == null) {
throw new ParseException("non-existing label '" + e.getKey() + "'");
}
@ -199,7 +199,7 @@ public class MockTreeParser {
private void emptyTerm() {
String name = termsStack.pop();
Integer label = termLabelsStack.pop();
Node newTerm = term(name);
Term newTerm = term(name);
childrenStack.peek().add(newTerm);
if (label != null) {
termRefs.put(label, newTerm);
@ -207,14 +207,14 @@ public class MockTreeParser {
}
private void beginChildren(){
childrenStack.push(new ArrayList<Node>());
childrenStack.push(new ArrayList<Term>());
}
private void endChildren() {
List<Node> children = childrenStack.pop();
List<Term> children = childrenStack.pop();
String name = termsStack.pop();
Integer label = termLabelsStack.pop();
Node newTerm = term(name, children.toArray(new Node[children.size()]));
Term newTerm = term(name, children.toArray(new Term[children.size()]));
childrenStack.peek().add(newTerm);
if (label != null) {
termRefs.put(label, newTerm);
@ -267,16 +267,16 @@ public class MockTreeParser {
}
private static class LookupHelper {
private Map<Integer, Node> termRefs;
private Map<Integer, Term> termRefs;
private void setTermRefs (Map<Integer, Node> termRefs) {
private void setTermRefs (Map<Integer, Term> termRefs) {
this.termRefs = termRefs;
}
public TermLookup lookup(final int label) {
return new TermLookup() {
@Override
public Node lookupTerm() {
public Term lookupTerm() {
if (termRefs == null) {
throw new IllegalStateException("call to uninitialized lookup");
}

View File

@ -16,14 +16,14 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import org.junit.ComparisonFailure;
import org.junit.Test;
import static org.junit.Assert.*;
import static jetbrains.mps.unification.test.MockNode.*;
import static jetbrains.mps.unification.test.MockTreeParser.*;
import static jetbrains.mps.unification.test.MockTerm.*;
import static jetbrains.mps.unification.test.MockTermsParser.*;
import static jetbrains.mps.unification.test.AssertAll.*;
import static jetbrains.mps.unification.test.AssertStructurallyEquivalent.*;
@ -33,10 +33,10 @@ import static jetbrains.mps.unification.test.AssertStructurallyEquivalent.*;
public class ParserTests {
private static class LazyTermLookup implements TermLookup{
private Node term;
private Term term;
@Override
public Node lookupTerm() {
public Term lookupTerm() {
return term;
}
}
@ -94,23 +94,23 @@ public class ParserTests {
@Test
public void testRef() throws Exception {
LazyTermLookup termLookup = new LazyTermLookup();
Node a = termLookup.term = term("a", ref(termLookup));
Term a = termLookup.term = term("a", ref(termLookup));
assertEquivalent(
parse("@1a{^1}"),
a);
Node b = term("b");
Term b = term("b");
assertEquivalent(
parse("a{@1b ^1}"),
term("a", b, ref(b)));
Node c = term("c");
Term c = term("c");
assertEquivalent(
parse("a{^1 @1c}"),
term("a", ref(c), c));
Node b1 = term("b");
Node b2 = term("b");
Term b1 = term("b");
Term b2 = term("b");
assertEquivalent(
parse("a{@2b ^1 ^2 @1b}"),
term("a", b2, ref(b1), ref(b2), b1));
@ -118,7 +118,7 @@ public class ParserTests {
@Test
public void testVarRef() throws Exception {
Node x = var("X");
Term x = var("X");
assertEquivalent(
parse("^X"),
@ -131,27 +131,27 @@ public class ParserTests {
@Test(expected = ComparisonFailure.class)
public void testNotEquivalent1() throws Exception {
Node d = term("d");
Term d = term("d");
assertEquivalent(parse("a{^1 @1c}"),
term("a", ref(d), d));
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testUnclosedFail() {
parse("a{b ");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testUnclosedFail2() {
parse("a{X b");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testUnclosedFail3() {
parse("a{{X b}");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testDoubleClosed() {
parse("a{X b}}");
}
@ -166,32 +166,32 @@ public class ParserTests {
parse("a b");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testEmptyFail() {
parse("");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testEmptyChildrenFail() {
parse("a{}");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testWrongStartFail() {
parse("{a}");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testVarHasChilrenFail() {
parse("X{a}");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testExtraSymbolFail() {
parse("a}");
}
@Test(expected = MockTreeParser.ParseException.class)
@Test(expected = MockTermsParser.ParseException.class)
public void testNonExistingRefFail() {
parse("a{b ^1}");
}

View File

@ -16,15 +16,13 @@
package jetbrains.mps.unification.test;
import jetbrains.mps.unification.Node;
import jetbrains.mps.unification.Term;
import org.junit.Test;
import static jetbrains.mps.unification.Substitution.FailureCause.*;
import static jetbrains.mps.unification.test.AssertUnification.*;
import static jetbrains.mps.unification.test.MockNode.ref;
import static jetbrains.mps.unification.test.MockNode.term;
import static jetbrains.mps.unification.test.MockNode.var;
import static jetbrains.mps.unification.test.MockTreeParser.*;
import static jetbrains.mps.unification.test.MockTerm.*;
import static jetbrains.mps.unification.test.MockTermsParser.*;
/**
* Created by fyodor on 09.06.2014.
@ -340,8 +338,8 @@ public class SolverTests {
@Test
public void testCyclicExt() throws Exception {
Node left = parse("@1 j{^1}");
Node right = term("j", term("j", ref(left)));
Term left = parse("@1 j{^1}");
Term right = term("j", term("j", ref(left)));
assertUnifiesWithBindings(
left,
right