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

Scott's parser processing empty productions

parent 6c2c218f
import javax.swing.plaf.nimbus.State;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
......@@ -181,7 +185,7 @@ public class EarleyParser implements PrettyPrintingInfo {
for (int i = 0; i < s.length + 1; ++i) {
System.out.println("=== Item set at position " + i + " ===");
for (EarleyItem item : state[i]) {
if (item.isComplete())
if (true || item.isComplete())
System.out.println(item.prettyPrint(this));
}
}
......@@ -189,13 +193,26 @@ public class EarleyParser implements PrettyPrintingInfo {
StateSet finalState = state[s.length];
System.out.println("===========================");
boolean recognized = false;
int count = 0;
for (EarleyItem item : finalState) {
if (item.isComplete() && item.start == 0 && item.rule.r.head == start) {
return true;
try {
PrintStream out = new PrintStream(new File("sppf_" + count++ + ".dot"));
DotVisitor visitor = new DotVisitor(out, this);
visitor.prologue();
item.getSPPF().accept(visitor);
visitor.epilogue();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
recognized = true;
}
}
return false;
return recognized;
}
public void parse(Category s[], Category startSymbol) {
......@@ -217,7 +234,8 @@ public class EarleyParser implements PrettyPrintingInfo {
HashMap<NodeLabel, SPPFNode> V = new HashMap<>();
for (EarleyRule r : rules.get(startSymbol)) {
state[0].add(new EarleyItem(r, 0));
if (r.startsWithNonTerminal())
state[0].add(new EarleyItem(r, 0));
if (!r.isEmpty() && r.body[0] == symbols[0]) {
Q_next.add(new EarleyItem(r, 0));
}
......@@ -239,8 +257,7 @@ public class EarleyParser implements PrettyPrintingInfo {
if (state[i].add(C)) {
R.add(C);
}
}
if (r.body[0] == symbols[i]) { // 1.1.2
} else if (r.body[0] == symbols[i]) { // 1.1.2
assert !r.startsWithNonTerminal();
Q.add(C);
}
......@@ -278,21 +295,25 @@ public class EarleyParser implements PrettyPrintingInfo {
H.put(Lambda.rule.r.head, Lambda.getSPPF());
}
HashSet<EarleyItem> RTemp = new HashSet<>(); // this is needed to avoid concurrent modification which occurs when Lambda.start == i
for (EarleyItem item : state[Lambda.start]) { // 2.3
if (!item.isComplete() && item.afterDot() == Lambda.rule.r.head) {
EarleyItem itemNext = item.advance();
SPPFNode y = makeNode(itemNext.getDottedRule(), itemNext.start, i, item.getSPPF(), Lambda.getSPPF(), V);
// EarleyItem newItem = new EarleyItem(itemNext.rule, itemNext.start);
itemNext.setSPPF(y);
if (itemNext.isComplete() || !isTerminal(itemNext.afterDot())) { // 2.3.1
if (state[i].add(itemNext)) { // 2.3.1
R.add(itemNext);
// assert i != Lambda.start;
if (!state[i].contains(itemNext)) { // 2.3.1
RTemp.add(itemNext);
}
} else if (itemNext.afterDot() == symbols[i]) { // 2.3.2
Q.add(itemNext);
}
}
}
R.addAll(RTemp);
state[i].addAll(RTemp);
}
}
......
......@@ -7,7 +7,7 @@ public class Rule {
public Rule(Category head, Category... body) {
this.head = head;
assert body.length > 0;
// assert body.length > 0;
this.body = body;
}
......
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
......@@ -42,9 +44,13 @@ public class SPPFNode {
return false;
return true;
}
public void accept(SPPFNodeVisitor visitor) {
visitor.visit(this);
}
}
private HashSet<FamilyNode> children = new HashSet<>();
HashSet<FamilyNode> children = new HashSet<>();
private NodeLabel label;
public SPPFNode() {
......@@ -70,8 +76,77 @@ public class SPPFNode {
public String prettyPrint(PrettyPrintingInfo info) {
return label.prettyPrint(info);
}
public void accept(SPPFNodeVisitor visitor) {
visitor.visit(this);
}
}
interface SPPFNodeVisitor {
public void visit(SPPFNode.FamilyNode familyNode);
public void visit(SPPFNode n);
}
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 PrettyPrintingInfo info;
public DotVisitor(PrintStream ps, PrettyPrintingInfo 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");
}
}
}
......@@ -90,4 +90,50 @@ public class EarleyParserTest {
EarleyParser parser = makeAmbiguousParser();
assertTrue(parser.recognize(str, s));
}
@Test public void testScottExample2() {
EarleyParser parser = new EarleyParser();
Category S = new Category("S", false);
Category b = new Category("b", true);
parser.addCategory(S);
parser.addCategory(b);
parser.addRule(new Rule(S, S, S));
parser.addRule(new Rule(S, b));
parser.done();
Category str [] = {b, b, b};
assertTrue(parser.recognize(str, S));
}
@Test public void testScottExample3() {
EarleyParser parser = new EarleyParser();
Category S = new Category("S", false);
Category A = new Category("A", false);
Category B = new Category("B", false);
Category T = new Category("T", false);
Category a = new Category("a", true);
Category b = new Category("b", true);
parser.addCategory(S);
parser.addCategory(A);
parser.addCategory(B);
parser.addCategory(T);
parser.addCategory(a);
parser.addCategory(b);
parser.addRule(new Rule(S, A, T));
parser.addRule(new Rule(S, a, T));
parser.addRule(new Rule(A, a));
parser.addRule(new Rule(A, B, A));
parser.addRule(new Rule(B)); // epsilon production
parser.addRule(new Rule(T, b, b, b));
parser.done();
Category str[] = {a, b, b, b};
assertTrue(parser.recognize(str, S));
}
}
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