Commit fd6b0f25 authored by Alexandru Dura's avatar Alexandru Dura
Browse files

'Remove dotted rules' visitor implemented for SPPF

parent bb0d0afb
package se.lth.sep;
import java.util.HashSet;
import java.util.Set;
/**
A visitor that removes the nodes that contain dottet rules.
*/
public class SPPFDebinarizeVisitor implements SPPFNodeVisitor {
private HashSet<SPPFNode> visitedNodes = new HashSet<>();
private HashSet<SPPFNode.FamilyNode> visitedFamNodes = new HashSet<>();
public void visit(SPPFNode.FamilyNode familyNode) {
if (!visitedFamNodes.add(familyNode)) {
// node already visited
return;
}
for (int i = 0; i < familyNode.getNumChildren(); ++i)
familyNode.getChild(i).accept(this);
}
public void visit(SPPFNode n) {
if (!visitedNodes.add(n)) {
// node already visited
return;
}
Set<SPPFNode.FamilyNode> children = n.getChildren();
HashSet<SPPFNode.FamilyNode> newChildren = new HashSet<>();
HashSet<SPPFNode.FamilyNode> childrenToRemove = new HashSet<>();
for (SPPFNode.FamilyNode f : children) {
f.accept(this);
if (f.getNumChildren() == 0)
continue;
// only the first child can a be a node representing a dot rule
SPPFNode firstChild = f.getChild(0);
if (!(firstChild.getLabel() instanceof ItemLabel))
continue;
// now we know this is representing a dot rule
for (SPPFNode.FamilyNode g : firstChild.getChildren()) {
SPPFNode[] childArray = new SPPFNode[g.getNumChildren() + f.getNumChildren() - 1];
for (int i = 0; i < g.getNumChildren(); ++i) {
childArray[i] = g.getChild(i);
}
for (int i = 1; i < f.getNumChildren(); ++i) {
childArray[g.getNumChildren() + i - 1] = f.getChild(i);
}
newChildren.add(new SPPFNode.FamilyNode(childArray));
childrenToRemove.add(f);
}
}
children.removeAll(childrenToRemove);
children.addAll(newChildren);
}
}
package se.lth.sep;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
......@@ -7,23 +8,42 @@ public class SPPFNode {
static public class FamilyNode {
private SPPFNode[] child;
FamilyNode(SPPFNode child0) {
assert child0 != null;
child = new SPPFNode[1];
child[0] = child0;
}
FamilyNode() {
child = new SPPFNode[0];
}
FamilyNode(SPPFNode child0, SPPFNode child1) {
assert child0 != null || child1 == null;
assert child0 != null || child1 != null;
child = new SPPFNode[2];
child[0] = child0;
child[1] = child1;
}
FamilyNode(SPPFNode children[]) {
child = Arrays.copyOf(children, children.length);
}
public int getNumChildren() {
return child.length;
}
public SPPFNode getChild(int i) {
return child[i];
}
@Override
public int hashCode() {
final int prime = 31;
final int prime = 47;
int result = 1;
result = prime * result + ((child[0] == null) ? 0 : child[0].hashCode());
result = prime * result + ((child[1] == null) ? 0 : child[1].hashCode());
for (int i = 0; i < child.length; ++i) {
result = prime * result + ((child[0] == null) ? 0 : child[0].hashCode());
}
return result;
}
......@@ -36,16 +56,16 @@ public class SPPFNode {
if (getClass() != obj.getClass())
return false;
FamilyNode other = (FamilyNode) obj;
if (child[0] == null) {
if (other.child[0] != null)
return false;
} else if (!child[0].equals(other.child[0]))
if (other.child.length != child.length)
return false;
if (child[1] == null) {
if (other.child[1] != null)
for (int i = 0; i < child.length; ++i) {
if (child[i] == null) {
if (other.child[i] != null)
return false;
} else if (!child[i].equals(other.child[i])) {
return false;
} else if (!child[1].equals(other.child[1]))
return false;
}
}
return true;
}
......@@ -66,7 +86,7 @@ public class SPPFNode {
}
public void addChild(SPPFNode child) {
children.add(new FamilyNode(child, null));
children.add(new FamilyNode(child));
}
public void addChildren(SPPFNode child0, SPPFNode child1) {
......@@ -74,7 +94,7 @@ public class SPPFNode {
}
public void addEpsilon() {
children.add(new FamilyNode(null, null));
children.add(new FamilyNode());
}
public String prettyPrint(Grammar info) {
......
......@@ -47,22 +47,17 @@ class DotVisitor implements SPPFNodeVisitor {
int currentID = nodeID++;
visitedFamilies.put(f, currentID);
if (f.getChild(0) == null) {
if (f.getNumChildren() == 0) {
// epsilon
ps.print(currentID + " [label=\u03b5];\n");
} else {
ps.print(currentID + " [shape=circle];\n");
f.getChild(0).accept(this);
if (f.getChild(1) != null) {
f.getChild(1).accept(this);
}
for (int i = 0; i < f.getNumChildren(); ++i)
f.getChild(i).accept(this);
}
if (f.getChild(0) != null)
ps.print(currentID + " -> " + visitedNodes.get(f.getChild(0)) + ";\n");
if (f.getChild(1) != null)
ps.print(currentID + " -> " + visitedNodes.get(f.getChild(1)) + ";\n");
for (int i = 0; i < f.getNumChildren(); ++i)
ps.print(currentID + " -> " + visitedNodes.get(f.getChild(i)) + ";\n");
}
@Override
......
......@@ -104,6 +104,11 @@ public class EarleyParserTest {
EarleyParser parser = new EarleyParser(g);
SPPFNode root = parser.parse(str, S);
assertNotNull(root);
Util.dumpParseResult("testParse4-bt.dot", root, g);
SPPFDebinarizeVisitor dbv = new SPPFDebinarizeVisitor();
dbv.visit(root);
Util.dumpParseResult("testParse4.dot", root, g);
}
......@@ -194,6 +199,9 @@ public class EarleyParserTest {
SPPFNode root = parser.parse(str, Java14Grammar.n_class_declaration);
assertNotNull(root);
Util.dumpParseResult("testJava2-bt.dot", root, g);
SPPFDebinarizeVisitor dbv = new SPPFDebinarizeVisitor();
dbv.visit(root);
Util.dumpParseResult("testJava2.dot", root, g);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment