forked from jasder/antlr
initial add of graph-structured stack. some unit tests. only got singleton merge in there.
This commit is contained in:
parent
ea7037dd2d
commit
bdb2aa9d15
|
@ -0,0 +1,51 @@
|
|||
import java.util.Arrays;
|
||||
|
||||
public class ArrayNode extends GraphNode {
|
||||
public final GraphNode[] parents;
|
||||
public final String[] payloads;
|
||||
|
||||
public ArrayNode(SingletonNode a) {
|
||||
this.parents = new GraphNode[] {a.parent};
|
||||
this.payloads = new String[] {a.payload};
|
||||
}
|
||||
|
||||
public ArrayNode(GraphNode[] parents, String[] payloads) {
|
||||
this.parents = parents;
|
||||
this.payloads = payloads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
else if ( !(o instanceof ArrayNode) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this.hashCode() != o.hashCode() ) {
|
||||
return false; // can't be same if hash is different
|
||||
}
|
||||
|
||||
ArrayNode a = (ArrayNode)o;
|
||||
if ( payloads.length != a.payloads.length ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<payloads.length; i++) {
|
||||
if ( !payloads[i].equals(a.payloads[i]) ) return false;
|
||||
if ( !parents[i].equals(a.parents[i]) ) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(payloads)+":"+id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
public abstract class GraphNode {
|
||||
public static final SingletonNode EMPTY = new SingletonNode(null,"$");
|
||||
|
||||
public static int globalNodeCount = 0;
|
||||
public final int id;
|
||||
|
||||
public GraphNode() {
|
||||
id = globalNodeCount++;
|
||||
}
|
||||
|
||||
public static GraphNode merge(GraphNode a, GraphNode b) { // dispatch
|
||||
if ( a instanceof SingletonNode && b instanceof SingletonNode ) {
|
||||
return mergeSingletons((SingletonNode) a, (SingletonNode) b);
|
||||
}
|
||||
if ( a instanceof SingletonNode ) {
|
||||
a = new ArrayNode((SingletonNode)a);
|
||||
}
|
||||
if ( b instanceof SingletonNode ) {
|
||||
b = new ArrayNode((SingletonNode)b);
|
||||
}
|
||||
return mergeArrays((ArrayNode) a, (ArrayNode) b);
|
||||
}
|
||||
|
||||
public static GraphNode mergeSingletons(SingletonNode a, SingletonNode b) {
|
||||
if ( a == EMPTY ) return a;
|
||||
if ( b == EMPTY ) return b;
|
||||
if ( a.payload.equals(b.payload) ) {
|
||||
GraphNode parent = merge(a.parent, b.parent);
|
||||
if ( parent == a.parent ) return a;
|
||||
if ( parent == b.parent ) return b;
|
||||
// new joined parent so create new singleton pointing to it
|
||||
return new SingletonNode(parent, a.payload);
|
||||
}
|
||||
else { // a != b payloads differ
|
||||
// parents differ, join them; nothing to reuse
|
||||
if ( !a.parent.equals(b.parent) ) {
|
||||
ArrayNode joined =
|
||||
new ArrayNode(new GraphNode[]{a.parent, b.parent},
|
||||
new String[] {a.payload, b.payload});
|
||||
return joined;
|
||||
}
|
||||
// parents are equal, pick left one as parent to reuse
|
||||
GraphNode parent = a.parent;
|
||||
ArrayNode joined =
|
||||
new ArrayNode(new GraphNode[]{parent, parent},
|
||||
new String[] {a.payload, b.payload});
|
||||
return joined;
|
||||
}
|
||||
}
|
||||
|
||||
public static GraphNode mergeArrays(ArrayNode a, ArrayNode b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String toDOT(GraphNode a) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
public class SingletonNode extends GraphNode {
|
||||
public final GraphNode parent;
|
||||
public final String payload;
|
||||
|
||||
public SingletonNode(GraphNode parent, String payload) {
|
||||
this.parent = parent;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
else if ( !(o instanceof SingletonNode) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this.hashCode() != o.hashCode() ) {
|
||||
return false; // can't be same if hash is different
|
||||
}
|
||||
|
||||
SingletonNode s = (SingletonNode)o;
|
||||
return payload.equals(s.payload) && parent.equals(s.parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return payload+":"+id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestGraphNodes extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
GraphNode.globalNodeCount = 1;
|
||||
}
|
||||
|
||||
@Test public void testBothEmpty() {
|
||||
GraphNode a = GraphNode.EMPTY;
|
||||
GraphNode b = GraphNode.EMPTY;
|
||||
GraphNode r = GraphNode.merge(a, b);
|
||||
assertEquals("$:0", r.toString());
|
||||
}
|
||||
|
||||
@Test public void testLeftEmpty() {
|
||||
GraphNode a = GraphNode.EMPTY;
|
||||
GraphNode b = createSingleton(GraphNode.EMPTY, "b");
|
||||
GraphNode r = GraphNode.merge(a, b);
|
||||
assertEquals("$:0", r.toString());
|
||||
}
|
||||
|
||||
@Test public void testRightEmpty() {
|
||||
GraphNode a = GraphNode.EMPTY;
|
||||
GraphNode b = createSingleton(GraphNode.EMPTY, "b");
|
||||
GraphNode r = GraphNode.merge(a, b);
|
||||
assertEquals("$:0", r.toString());
|
||||
}
|
||||
|
||||
@Test public void testSameSingleTops() {
|
||||
GraphNode a1 = createSingleton(GraphNode.EMPTY, "a");
|
||||
GraphNode a2 = createSingleton(GraphNode.EMPTY, "a");
|
||||
GraphNode r = GraphNode.merge(a1, a2);
|
||||
assertEquals("a:1", r.toString());
|
||||
}
|
||||
|
||||
@Test public void testDiffSingleTops() {
|
||||
GraphNode a1 = createSingleton(GraphNode.EMPTY, "a");
|
||||
GraphNode a2 = createSingleton(GraphNode.EMPTY, "b");
|
||||
GraphNode r = GraphNode.merge(a1, a2);
|
||||
assertEquals("[a, b]:3", r.toString());
|
||||
}
|
||||
|
||||
@Test public void test_ax_ax_id() {
|
||||
GraphNode x = createSingleton(GraphNode.EMPTY, "x");
|
||||
GraphNode a1 = createSingleton(x, "a");
|
||||
GraphNode a2 = createSingleton(x, "a");
|
||||
GraphNode r = GraphNode.merge(a1, a2);
|
||||
assertEquals("a:2", r.toString());
|
||||
}
|
||||
|
||||
@Test public void test_ax_ax_eq() {
|
||||
GraphNode x1 = createSingleton(GraphNode.EMPTY, "x");
|
||||
GraphNode x2 = createSingleton(GraphNode.EMPTY, "x");
|
||||
GraphNode a1 = createSingleton(x1, "a");
|
||||
GraphNode a2 = createSingleton(x2, "a");
|
||||
GraphNode r = GraphNode.merge(a1, a2);
|
||||
assertEquals("a:3", r.toString());
|
||||
}
|
||||
|
||||
public SingletonNode createSingleton(GraphNode parent, String payload) {
|
||||
SingletonNode a = new SingletonNode(parent, payload);
|
||||
return a;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue