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

Factor out the dot printing code

parent a46b502c
......@@ -72,27 +72,16 @@ public class EarleyParser {
}
StateSet finalState = state[s.length];
System.out.println("===========================");
boolean recognized = false;
int count = 0;
if (DEBUG)
System.out.println("===========================");
for (EarleyItem item : finalState) {
if (item.isComplete() && item.start == 0 && item.rule.r.head == start) {
try {
PrintStream out = new PrintStream(new File("sppf_" + count++ + ".dot"));
DotVisitor visitor = new DotVisitor(out, grammar);
visitor.prologue();
item.getSPPF().accept(visitor);
visitor.epilogue();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
recognized = true;
return true;
}
}
return recognized;
return false;
}
public SPPFNode parse(Category s[], Category startSymbol) {
......@@ -115,7 +104,9 @@ public class EarleyParser {
}
/**
symbols - a zero terminated array of symbols
@param symbols - a zero terminated array of symbols
@param startSymbol - the start symbol for the grammar
@return the state set computed by the Earley parsing algorithm
*/
private StateSet[] internalParseScott(int[] symbols, int startSymbol) {
StateSet[] state = new StateSet[symbols.length + 1];
......@@ -140,7 +131,7 @@ public class EarleyParser {
Q_next = new StateSet();
while (!R.isEmpty()) {
// for hash sets this is not deterministic, this may be a problem...
// for hash sets the iteration order is not deterministic, this may be a problem...
EarleyItem Lambda = R.pickOne();
if (!Lambda.isComplete() && !isTerminal(Lambda.afterDot())) { // 1
for (EarleyRule r : rules.get(Lambda.afterDot())) { // 1.1
......@@ -155,7 +146,7 @@ public class EarleyParser {
}
}
SPPFNode v = H.get(Lambda.afterDot()); // TODO: check that we never insert null
SPPFNode v = H.get(Lambda.afterDot());
if (v != null) { // 1.2
EarleyItem LambdaNext = Lambda.advance();
SPPFNode y = makeNode(LambdaNext.getDottedRule(), LambdaNext.start, i, Lambda.getSPPF(), v, V);
......@@ -184,10 +175,11 @@ public class EarleyParser {
v.addEpsilon(); // 2.1.2
}
if (Lambda.start == i) { // 2.2
assert Lambda.getSPPF() != null;
H.put(Lambda.rule.r.head, Lambda.getSPPF());
}
// this is needed to avoid concurrent modification which occurs when Lambda.start == i
// this set is needed to avoid concurrent modification which occurs when Lambda.start == i
HashSet<EarleyItem> RTemp = new HashSet<>();
for (EarleyItem item : state[Lambda.start]) { // 2.3
if (!item.isComplete() && item.afterDot() == Lambda.rule.r.head) {
......@@ -195,7 +187,6 @@ public class EarleyParser {
SPPFNode y = makeNode(itemNext.getDottedRule(), itemNext.start, i, item.getSPPF(), Lambda.getSPPF(), V);
itemNext.setSPPF(y);
if (itemNext.isComplete() || !isTerminal(itemNext.afterDot())) { // 2.3.1
// assert i != Lambda.start;
if (!state[i].contains(itemNext)) { // 2.3.1
RTemp.add(itemNext);
}
......
......@@ -85,67 +85,3 @@ public class SPPFNode {
return label;
}
}
class DotVisitor implements SPPFNodeVisitor {
private PrintStream ps;
private int nodeID = 0;
private HashMap<SPPFNode, Integer> visitedNodes = new HashMap<>();
private HashMap<SPPFNode.FamilyNode, Integer> visitedFamilies = new HashMap<>();
private Grammar info;
public DotVisitor(PrintStream ps, Grammar info) {
this.info = info;
this.ps = ps;
}
public void prologue() {
ps.println("digraph G {");
}
public void epilogue() {
ps.println("}");
}
@Override
public void visit(SPPFNode.FamilyNode f) {
if (visitedFamilies.containsKey(f))
return;
int currentID = nodeID++;
visitedFamilies.put(f, currentID);
if (f.child1 == null) {
// epsilon
ps.print(currentID + " [label=\u03b5];\n");
} else {
ps.print(currentID + " [shape=circle];\n");
f.child1.accept(this);
if (f.child2 != null) {
f.child2.accept(this);
}
}
if (f.child1 != null)
ps.print(currentID + " -> " + visitedNodes.get(f.child1) + ";\n");
if (f.child2 != null)
ps.print(currentID + " -> " + visitedNodes.get(f.child2) + ";\n");
}
@Override
public void visit(SPPFNode n) {
if (visitedNodes.containsKey(n))
return;
int currentID = nodeID++;
visitedNodes.put(n, currentID);
ps.print(currentID + " [shape=box,label=\"" + n.prettyPrint(info) + "\"];\n");
for (SPPFNode.FamilyNode f : n.children) {
f.accept(this);
ps.print(currentID + " -> " + visitedFamilies.get(f) + ";\n");
}
}
}
public interface SPPFNodeVisitor {
public void visit(SPPFNode.FamilyNode familyNode);
public void visit(SPPFNode n);
}
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.HashMap;
public class Util {
public static void dumpParseResult(String dotFileName, SPPFNode node, Grammar grammar) {
try {
PrintStream out = new PrintStream(new File(dotFileName));
DotVisitor visitor = new DotVisitor(out, grammar);
visitor.prologue();
node.accept(visitor);
visitor.epilogue();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class DotVisitor implements SPPFNodeVisitor {
private PrintStream ps;
private int nodeID = 0;
private HashMap<SPPFNode, Integer> visitedNodes = new HashMap<>();
private HashMap<SPPFNode.FamilyNode, Integer> visitedFamilies = new HashMap<>();
private Grammar info;
public DotVisitor(PrintStream ps, Grammar info) {
this.info = info;
this.ps = ps;
}
public void prologue() {
ps.println("digraph G {");
}
public void epilogue() {
ps.println("}");
}
@Override
public void visit(SPPFNode.FamilyNode f) {
if (visitedFamilies.containsKey(f))
return;
int currentID = nodeID++;
visitedFamilies.put(f, currentID);
if (f.child1 == null) {
// epsilon
ps.print(currentID + " [label=\u03b5];\n");
} else {
ps.print(currentID + " [shape=circle];\n");
f.child1.accept(this);
if (f.child2 != null) {
f.child2.accept(this);
}
}
if (f.child1 != null)
ps.print(currentID + " -> " + visitedNodes.get(f.child1) + ";\n");
if (f.child2 != null)
ps.print(currentID + " -> " + visitedNodes.get(f.child2) + ";\n");
}
@Override
public void visit(SPPFNode n) {
if (visitedNodes.containsKey(n))
return;
int currentID = nodeID++;
visitedNodes.put(n, currentID);
if (n.getLabel() instanceof ItemLabel) {
ps.print(currentID + " [shape=box,color=red,label=\"" + n.prettyPrint(info) + "\"];\n");
} else {
ps.print(currentID + " [shape=box,label=\"" + n.prettyPrint(info) + "\"];\n");
}
for (SPPFNode.FamilyNode f : n.children) {
f.accept(this);
ps.print(currentID + " -> " + visitedFamilies.get(f) + ";\n");
}
}
}
......@@ -72,6 +72,38 @@ public class EarleyParserTest {
assertTrue(parser.recognize(str, s));
}
@Test public void testParse4() {
Grammar g = new Grammar();
Category a = new Category("a", true);
Category b = new Category("b", true);
Category c = new Category("c", true);
Category A = new Category("A", false);
Category B = new Category("B", false);
Category C = new Category("C", false);
Category S = new Category("S", false);
g.addRule(new Rule(A, a, b));
g.addRule(new Rule(A, a));
g.addRule(new Rule(A));
g.addRule(new Rule(B, a, b));
g.addRule(new Rule(B, b, c));
g.addRule(new Rule(B, b));
g.addRule(new Rule(B, c));
g.addRule(new Rule(B));
g.addRule(new Rule(C, b, c));
g.addRule(new Rule(C, c));
g.addRule(new Rule(C));
g.addRule(new Rule(S, A, B, C));
Category[] str = {a, b, c};
EarleyParser parser = new EarleyParser(g);
assertTrue(parser.recognize(str, S));
}
@Test public void testScottExample2() {
......@@ -157,6 +189,8 @@ public class EarleyParserTest {
Java14Grammar.t_RBRACE,
Java14Grammar.t_RBRACE};
assertTrue(parser.recognize(str, Java14Grammar.n_class_declaration));
SPPFNode root = parser.parse(str, Java14Grammar.n_class_declaration);
assertNotNull(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