|
@@ -29,6 +29,9 @@ class Derivation(Tree): |
|
|
Tree.__init__(self, 'drv', items or []) |
|
|
Tree.__init__(self, 'drv', items or []) |
|
|
self.rule = rule |
|
|
self.rule = rule |
|
|
|
|
|
|
|
|
|
|
|
def _pretty_label(self): # Nicer pretty for debugging the parser |
|
|
|
|
|
return self.rule.origin if self.rule else self.data |
|
|
|
|
|
|
|
|
END_TOKEN = EndToken() |
|
|
END_TOKEN = EndToken() |
|
|
|
|
|
|
|
|
class Item(object): |
|
|
class Item(object): |
|
@@ -106,8 +109,11 @@ class Column: |
|
|
new_tree = old_tree.copy() |
|
|
new_tree = old_tree.copy() |
|
|
new_tree.rule = old_tree.rule |
|
|
new_tree.rule = old_tree.rule |
|
|
old_tree.set('_ambig', [new_tree]) |
|
|
old_tree.set('_ambig', [new_tree]) |
|
|
|
|
|
old_tree.rule = None # No longer a 'drv' node |
|
|
|
|
|
|
|
|
if item.tree.children[0] is old_tree: # XXX a little hacky! |
|
|
if item.tree.children[0] is old_tree: # XXX a little hacky! |
|
|
raise ParseError("Infinite recursion in grammar! (Rule %s)" % item.rule) |
|
|
raise ParseError("Infinite recursion in grammar! (Rule %s)" % item.rule) |
|
|
|
|
|
|
|
|
old_tree.children.append(item.tree) |
|
|
old_tree.children.append(item.tree) |
|
|
else: |
|
|
else: |
|
|
self.completed[item] = item |
|
|
self.completed[item] = item |
|
@@ -234,6 +240,14 @@ def _compare_drv(tree1, tree2): |
|
|
# Probably trees that don't take part in this parse (better way to distinguish?) |
|
|
# Probably trees that don't take part in this parse (better way to distinguish?) |
|
|
return compare(tree1, tree2) |
|
|
return compare(tree1, tree2) |
|
|
|
|
|
|
|
|
|
|
|
# XXX These artifacts can appear due to imperfections in the ordering of Visitor_NoRecurse, |
|
|
|
|
|
# when confronted with duplicate (same-id) nodes. Fixing this ordering is possible, but would be |
|
|
|
|
|
# computationally inefficient. So we handle it here. |
|
|
|
|
|
if tree1.data == '_ambig': |
|
|
|
|
|
_resolve_ambig(tree1) |
|
|
|
|
|
if tree2.data == '_ambig': |
|
|
|
|
|
_resolve_ambig(tree2) |
|
|
|
|
|
|
|
|
c = _compare_rules(tree1.rule, tree2.rule) |
|
|
c = _compare_rules(tree1.rule, tree2.rule) |
|
|
if c: |
|
|
if c: |
|
|
return c |
|
|
return c |
|
@@ -247,12 +261,19 @@ def _compare_drv(tree1, tree2): |
|
|
return compare(len(tree1.children), len(tree2.children)) |
|
|
return compare(len(tree1.children), len(tree2.children)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _resolve_ambig(tree): |
|
|
|
|
|
assert tree.data == '_ambig' |
|
|
|
|
|
|
|
|
|
|
|
best = min(tree.children, key=cmp_to_key(_compare_drv)) |
|
|
|
|
|
assert best.data == 'drv' |
|
|
|
|
|
tree.set('drv', best.children) |
|
|
|
|
|
tree.rule = best.rule # needed for applying callbacks |
|
|
|
|
|
|
|
|
|
|
|
assert tree.data != '_ambig' |
|
|
|
|
|
|
|
|
class ResolveAmbig(Visitor_NoRecurse): |
|
|
class ResolveAmbig(Visitor_NoRecurse): |
|
|
def _ambig(self, tree): |
|
|
def _ambig(self, tree): |
|
|
best = min(tree.children, key=cmp_to_key(_compare_drv)) |
|
|
|
|
|
assert best.data == 'drv' |
|
|
|
|
|
tree.set('drv', best.children) |
|
|
|
|
|
tree.rule = best.rule # needed for applying callbacks |
|
|
|
|
|
|
|
|
_resolve_ambig(tree) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# RULES = [ |
|
|
# RULES = [ |
|
|