Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
trs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
trs
Commits
d67e91b7
Commit
d67e91b7
authored
May 17, 2012
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pick the best possibiltity using the shortest path with breadth first traversal.
parent
91a26452
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
148 additions
and
30 deletions
+148
-30
src/parser.py
src/parser.py
+9
-6
src/possibilities.py
src/possibilities.py
+123
-15
src/strategy.py
src/strategy.py
+1
-7
src/validation.py
src/validation.py
+15
-2
No files found.
src/parser.py
View file @
d67e91b7
...
...
@@ -22,7 +22,7 @@ from node import ExpressionNode as Node, \
from
rules.utils
import
find_variable
from
rules.precedences
import
IMPLICIT_RULES
from
strategy
import
find_possibilities
from
possibilities
import
apply_suggestion
from
possibilities
import
apply_suggestion
,
pick_best_possibility
import
Queue
import
re
...
...
@@ -258,7 +258,7 @@ class Parser(BisonParser):
if self.interactive:
if self.possibilities:
print
self.possibilities[0]
print
pick_best_possibility(self, self.possibilities)
else:
print '
No
further
reduction
is
possible
.
'
...
...
@@ -268,13 +268,16 @@ class Parser(BisonParser):
for i, p in enumerate(self.possibilities):
print '
%
d
%
s
' % (i, p)
def rewrite(self, index=
0
, verbose=False, check_implicit=True):
def rewrite(self, index=
None
, verbose=False, check_implicit=True):
self.find_possibilities()
if not self.possibilities:
return
suggestion = self.possibilities[index]
if index is None:
suggestion = pick_best_possibility(self, self.possibilities)
else:
suggestion = self.possibilities[index]
if self.verbose:
print '
EXPLICIT
:
', suggestion
...
...
@@ -327,10 +330,10 @@ class Parser(BisonParser):
return self.root_node
def rewrite_all(self, verbose=False):
def rewrite_all(self,
index=None,
verbose=False):
i = 0
while self.rewrite(verbose=verbose):
while self.rewrite(
index=index,
verbose=verbose):
i += 1
if i > 100:
...
...
src/possibilities.py
View file @
d67e91b7
from
node
import
TYPE_OPERATOR
from
node
import
TYPE_OPERATOR
,
OP_NEG
# Each rule will append its hint message to the following dictionary. The
...
...
@@ -7,6 +7,12 @@ from node import TYPE_OPERATOR
# message. The string will be processed using string.format().
MESSAGES
=
{}
# Dictionary used to map a stringified expression tree to the index of the
# best / shortest possibility.
BEST_POSSIBILITY_CACHE
=
{}
MAX_TREE_DEPTH
=
20
class
Possibility
(
object
):
def
__init__
(
self
,
root
,
handler
,
args
=
()):
...
...
@@ -39,6 +45,36 @@ class Possibility(object):
and
self
.
args
==
other
.
args
def
find_possibilities
(
node
,
parent_op
=
None
):
possibilities
=
[]
handlers
=
[]
from
rules
import
RULES
if
not
node
.
is_leaf
:
# Traverse through child nodes first using postorder traversal
for
child
in
node
:
possibilities
+=
find_possibilities
(
child
,
node
.
op
)
# Add operator-specific handlers. Prevent duplicate possibilities in
# n-ary nodes by only executing the handlers on the outermost node of
# related nodes with the same operator
#if node.op in RULES and (node.op != parent_op \
# or node.op not in NARY_OPERATORS):
# handlers += RULES[node.op]
if
node
.
op
in
RULES
:
handlers
+=
RULES
[
node
.
op
]
if
node
.
negated
:
handlers
+=
RULES
[
OP_NEG
]
# Run handlers
for
handler
in
handlers
:
possibilities
+=
handler
(
node
)
return
possibilities
def
find_parent_node
(
root
,
child
):
nodes
=
[
root
]
...
...
@@ -59,25 +95,97 @@ def find_parent_node(root, child):
def
apply_suggestion
(
root
,
suggestion
):
# TODO: clone the root node before modifying. After deep copying the root
# node, the subtree_map cannot be used since the hash() of each node in the
# deep copied root node has changed.
#root = root.clone()
# Apply the suggestion on the sub tree root with the given arguments.
subtree
=
suggestion
.
handler
(
suggestion
.
root
,
suggestion
.
args
)
parent_node
=
find_parent_node
(
root
,
suggestion
.
root
)
# There is either a parent node or the subtree is the root node.
# FIXME: FAIL: test_diagnostic_test_application in tests/test_b1_ch08.py
#try:
# assert bool(parent_node) != (subtree == root)
#except:
# print 'parent_node: %s' % (str(parent_node))
# print 'subtree: %s == %s' % (str(subtree), str(root))
# raise
# Find the parent node of the sub tree and, if it has a parent node,
# substitute the new sub tree into the parent's list of child nodes.
parent_node
=
find_parent_node
(
root
,
suggestion
.
root
)
if
parent_node
:
parent_node
.
substitute
(
suggestion
.
root
,
subtree
)
return
root
# Apparently the whole tree is updated. Return the new tree instead of the
# old root node
return
subtree
def
pick_best_possibility
(
parser
,
possibilities
):
root
=
parser
.
root_node
#print 'pick_best_possibility for:', root
# Get the final expression
parser
.
set_root_node
(
root
.
clone
())
result
=
parser
.
rewrite_all
(
index
=
0
)
def
traverse_breadth_first
(
node
,
result
,
depth
=
0
):
if
depth
>
MAX_TREE_DEPTH
:
return
node_expr
=
str
(
node
)
if
node_expr
in
BEST_POSSIBILITY_CACHE
:
return
BEST_POSSIBILITY_CACHE
[
node_expr
]
# If the nodes match, there is no rewrite step needed. If the nodes to
# not converge at all, the step_index will be None as well (since there
# still is no rewrite step to do).
step_index
=
None
#print ' ' * depth + 'node:', node, 'result:', result, 'equal:', \
# node.equals(result)
if
not
node
.
equals
(
result
):
children
=
[]
possibilities
=
find_possibilities
(
node
)
#print ' ' * depth + (' ' * depth + '\n').join(map(str,
# enumerate(possibilities)))
for
p
,
possibility
in
enumerate
(
possibilities
):
#print ' ' * depth + 'possibility:', possibility, 'on:', node
# Clone the root node because it will be used in multiple
# substitutions
child
=
apply_suggestion
(
node
.
clone
(),
possibility
)
#print ' ' * depth + 'child:', child
if
child
.
equals
(
result
):
step_index
=
p
break
children
.
append
(
child
)
# If the final expression is not found in the direct children,
# start searching in the children of the children.
if
step_index
is
None
:
for
c
,
child
in
enumerate
(
children
):
child_step
=
traverse_breadth_first
(
child
,
result
,
depth
+
1
)
#print ' ' * depth + 'child_step:', child_step
if
child_step
is
not
None
:
step_index
=
c
break
BEST_POSSIBILITY_CACHE
[
node_expr
]
=
step_index
return
step_index
#print '--- start traversal ---'
step_index
=
traverse_breadth_first
(
root
,
result
)
#print 'step_index:', step_index
#print '--- cache: ---'
#print BEST_POSSIBILITY_CACHE
# Reset the parser's original state
parser
.
set_root_node
(
root
)
parser
.
find_possibilities
()
return
parser
.
possibilities
[
step_index
]
src/strategy.py
View file @
d67e91b7
...
...
@@ -87,16 +87,10 @@ def depth_possibilities(node, depth=0, parent_op=None):
def
find_possibilities
(
node
):
"""
Find all possibilities inside a node and return them
in
a list.
Find all possibilities inside a node and return them
as
a list.
"""
possibilities
=
depth_possibilities
(
node
)
#import copy
#old_possibilities = copy.deepcopy(possibilities)
possibilities
.
sort
(
compare_possibilities
)
#get_handler = lambda (p, d): str(p.handler)
#if old_possibilities != possibilities:
# print 'before:', '\n '.join(map(get_handler, old_possibilities))
# print 'after:', '\n '.join(map(get_handler, possibilities))
return
[
p
for
p
,
depth
in
possibilities
]
...
...
src/validation.py
View file @
d67e91b7
from
parser
import
Parser
from
possibilities
import
apply_suggestion
from
possibilities
import
apply_suggestion
,
BEST_POSSIBILITY_CACHE
from
strategy
import
find_possibilities
from
tests.parser
import
ParserWrapper
...
...
@@ -16,7 +16,20 @@ def validate(exp, result):
if
node
.
equals
(
result
):
return
True
for
p
in
find_possibilities
(
node
):
node_expr
=
str
(
node
)
if
node_expr
in
BEST_POSSIBILITY_CACHE
:
possibility_index
=
BEST_POSSIBILITY_CACHE
[
node_expr
]
# If there is no possible rewrite step, bail out
if
possibility_index
is
None
:
return
False
possibilities
=
[
possibility_index
]
else
:
possibilities
=
find_possibilities
(
node
)
for
p
in
possibilities
:
# Clone the root node because it will be used in multiple
# substitutions
child
=
apply_suggestion
(
node
.
clone
(),
p
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment