Commit 073a4a7f authored by Alexandru Dura's avatar Alexandru Dura
Browse files

Decorate each parse tree node with the corresponding rule

parent 0bfa89fe
......@@ -8,13 +8,24 @@ public class ParseTree {
private int start;
private int end;
private Category cat;
private Rule rule;
private ArrayList<ParseTree> children;
public ParseTree(Category c, int start, int end) {
private ParseTree(Category c, Rule rule, int start, int end) {
this.cat = c;
this.children = new ArrayList<ParseTree>();
this.start = start;
this.end = end;
this.rule = rule;
assert rule == null || rule.getHead() == c;
}
public ParseTree(Rule r, int start, int end) {
this(r.getHead(), r, start, end);
}
public ParseTree(Category c, int start, int end) {
this(c, null, start, end);
}
public void addChild(ParseTree t) {
......@@ -40,4 +51,8 @@ public class ParseTree {
public int getEnd() {
return end;
}
public Rule getRule() {
return rule;
}
}
......@@ -67,7 +67,12 @@ public class ParseTreeGenerator implements SPPFNodeVisitor {
LinkedList<LinkedList<ParseTree>> childAlternatives = familyMap.get(f);
for (LinkedList<ParseTree> childAlternative : childAlternatives) {
ParseTree pt = new ParseTree(c, start, end);
ParseTree pt;
if (f.getInfo() != null) {
pt = new ParseTree( (Rule)f.getInfo(), start, end);
} else {
pt = new ParseTree(c, start, end);
}
pt.addChildren(childAlternative);
result.add(pt);
}
......
......@@ -20,6 +20,19 @@ public class Rule {
this.action = act;
}
public String prettyPrint() {
String s = head.getName() + " -> ";
if (body.length == 0) {
s += "\u03b5";
return s;
}
for (Category c : body) {
s += c.getName() + " ";
}
return s;
}
public SemanticAction getAction() {
return action;
}
......
......@@ -4,11 +4,9 @@ import java.util.HashSet;
import java.util.Set;
/**
A visitor that removes the nodes that contain dottet rules.
A visitor that removes the nodes that contain dotted rules.
*/
public class SPPFDebinarizeVisitor implements SPPFNodeVisitor {
private HashSet<SPPFNode> visitedNodes = new HashSet<>();
private HashSet<SPPFNode.FamilyNode> visitedFamNodes = new HashSet<>();
......
......@@ -7,6 +7,7 @@ import java.util.Set;
public class SPPFNode {
static public class FamilyNode {
private SPPFNode[] child;
private Object info = null;
FamilyNode(SPPFNode child0) {
assert child0 != null;
......@@ -72,10 +73,19 @@ public class SPPFNode {
public void accept(SPPFNodeVisitor visitor) {
visitor.visit(this);
}
void setInfo(Object info) {
this.info = info;
}
Object getInfo() {
return info;
}
}
HashSet<FamilyNode> children = new HashSet<>();
private NodeLabel label;
private Object info = null;
public SPPFNode() {
label = null;
......@@ -112,4 +122,12 @@ public class SPPFNode {
public NodeLabel getLabel() {
return label;
}
void setInfo(Object info) {
this.info = info;
}
Object getInfo() {
return info;
}
}
package se.lth.sep;
import java.util.ArrayList;
import java.util.HashSet;
public class SPPFNodeDecorator implements SPPFNodeVisitor {
private HashSet<SPPFNode> visitedNodes = new HashSet<>();
private HashSet<SPPFNode.FamilyNode> visitedFamNodes = new HashSet<>();
Grammar grammar;
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 SPPFNodeDecorator(Grammar grammar) {
this.grammar = grammar;
}
public void visit(SPPFNode n) {
if (!visitedNodes.add(n)) {
// node already visited
return;
}
Category head = ((SymbolLabel)n.getLabel()).getSymbol(grammar);
for (SPPFNode.FamilyNode f : n.getChildren()) {
f.accept(this);
ArrayList<Category> body = new ArrayList<>(f.getNumChildren());
for (int i = 0; i < f.getNumChildren(); ++i) {
Category c = ((SymbolLabel)f.getChild(i).getLabel()).getSymbol(grammar);
body.add(c);
}
Rule r = grammar.getRule(head, body);
assert f.getInfo() == null;
assert head.isTerminal() || r != null;
f.setInfo(r);
}
}
}
......@@ -41,9 +41,6 @@ public class SPPFTrivialProductionRemover implements SPPFNodeVisitor {
HashSet<SPPFNode.FamilyNode> childrenToRemove = new HashSet<>();
for (SPPFNode.FamilyNode f : n.getChildren()) {
if (f.getNumChildren() != 1)
continue;
SPPFNode[] childArray = new SPPFNode[f.getNumChildren()];
boolean updatedChildren = false;
for (int i = 0; i < f.getNumChildren(); ++i) {
......@@ -70,9 +67,13 @@ public class SPPFTrivialProductionRemover implements SPPFNodeVisitor {
updatedChildren = true;
}
}
if (updatedChildren) {
FamilyNode newf = new FamilyNode(childArray);
// preserve the info
newf.setInfo(f.getInfo());
childrenToRemove.add(f);
newChildren.add(new FamilyNode(childArray));
newChildren.add(newf);
}
}
......
......@@ -25,7 +25,10 @@ public class Util {
private static int dumpParseTree(PrintStream ps, ParseTree pt, MutableInt count) {
int currentID = count.getAndIncrement();
ps.println(currentID + " [shape=box,label=\"" + pt.getCategory().getName() + "\"];");
String label = pt.getRule() != null ?
pt.getRule().prettyPrint() : pt.getCategory().getName();
ps.println(currentID + " [shape=box,label=\"" + label + "\"" +
(pt.getRule() == null ? ",color=red" : "") + "];");
for (ParseTree c : pt.getChildren()) {
int childID = dumpParseTree(ps, c, count);
ps.println(currentID + " -> " + childID + ";");
......
......@@ -186,6 +186,9 @@ public class EarleyParserTest {
SPPFDebinarizeVisitor dbv = new SPPFDebinarizeVisitor();
dbv.visit(root);
Util.dumpParseResult("testJava1.dot", root, g);
// decorate nodes with the grammar rules
SPPFNodeDecorator dec = new SPPFNodeDecorator(g);
dec.visit(root);
// remove trivial productions
SPPFTrivialProductionRemover tpr = new SPPFTrivialProductionRemover(g) {
@Override public boolean isBubleUpChild(Category c) {
......@@ -230,6 +233,9 @@ public class EarleyParserTest {
SPPFDebinarizeVisitor dbv = new SPPFDebinarizeVisitor();
dbv.visit(root);
Util.dumpParseResult("testJava2.dot", root, g);
// decorate nodes with the grammar rules
SPPFNodeDecorator dec = new SPPFNodeDecorator(g);
dec.visit(root);
// remove trivial productions
SPPFTrivialProductionRemover tpr = new SPPFTrivialProductionRemover(g) {
@Override public boolean isBubleUpChild(Category c) {
......@@ -337,4 +343,110 @@ public class EarleyParserTest {
Util.dumpParseResult("testJava4-notr.dot", root, g);
}
@Test public void testJava5() {
// This test is expected should finish in a reasonable ammount of time (~10s).
Grammar g = new Grammar();
Java14Grammar.addRules(g);
EarleyParser parser = new EarleyParser(g);
Category str[] = {
Java14Grammar.t_CLASS,
Java14Grammar.t_IDENTIFIER,
Java14Grammar.t_LBRACE,
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
// start ambigous constructor/method declaration
Java14Grammar.t_METAVARID,
Java14Grammar.t_METAVARID,
Java14Grammar.t_LPAREN,
Java14Grammar.t_RPAREN,
Java14Grammar.t_LBRACE,
Java14Grammar.t_GAP,
Java14Grammar.t_RBRACE,
// end ambigous constructor/method declaration
Java14Grammar.t_RBRACE};
SPPFNode root = parser.parse(str, Java14Grammar.n_class_declaration);
assertNotNull(root);
Util.dumpParseResult("testJava5-bt.dot", root, g);
// debinarize
SPPFDebinarizeVisitor dbv = new SPPFDebinarizeVisitor();
dbv.visit(root);
Util.dumpParseResult("testJava5.dot", root, g);
// decorate nodes with the grammar rules
SPPFNodeDecorator dec = new SPPFNodeDecorator(g);
dec.visit(root);
// remove trivial productions
SPPFTrivialProductionRemover tpr = new SPPFTrivialProductionRemover(g) {
@Override public boolean isBubleUpChild(Category c) {
if (c.getName().equals("METAVARID"))
return true;
if (c.getName().equals("GAP"))
return true;
return false;
}
};
tpr.visit(root);
Util.dumpParseResult("testJava5-notr.dot", root, g);
// dump the parse trees
ParseTreeGenerator ptg = new ParseTreeGenerator(g, root);
List<ParseTree> pts = ptg.getParseTrees();
// the parsing should produce 3^6 parse trees
assertEquals(3*3*3*3*3*3, pts.size());
Util.dumpParseTrees("testJava5-parse-tree", pts);
}
}
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import se.lth.sep.*;
import org.junit.Test;
public class UtilTest {
@Test public void test1() {
LinkedList<Integer> l1 = new LinkedList<>(Arrays.asList(1, 2, 3));
LinkedList<Integer> l2 = new LinkedList<>(Arrays.asList(4, 5, 6));
LinkedList<Integer> l3 = new LinkedList<>(Arrays.asList(7, 8));
LinkedList<LinkedList<Integer>> ll = new LinkedList<>(Arrays.asList(l1, l2, l3));
LinkedList<LinkedList<Integer>> r = Util.<Integer>product(ll.iterator());
for (LinkedList<Integer> li : r) {
for (int i : li) {
System.out.print(i + ", ");
}
System.out.println();
}
}
}
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