Commit 57bc805c authored by Taddeus Kroes's avatar Taddeus Kroes

Interactive parser state is not changed by parser hooks anymore, but separated in functions.

parent 4c081113
...@@ -21,7 +21,7 @@ from node import ExpressionBase, ExpressionNode as Node, \ ...@@ -21,7 +21,7 @@ from node import ExpressionBase, ExpressionNode as Node, \
OP_INT_INDEF, OP_ABS, OP_NEG, negation_to_node OP_INT_INDEF, OP_ABS, OP_NEG, negation_to_node
from rules import RULES from rules import RULES
from rules.utils import find_variable from rules.utils import find_variable
from strategy import pick_suggestion #from strategy import sort_possiblities
from possibilities import filter_duplicates, apply_suggestion from possibilities import filter_duplicates, apply_suggestion
import Queue import Queue
...@@ -58,6 +58,34 @@ def find_integration_variable(exp): ...@@ -58,6 +58,34 @@ def find_integration_variable(exp):
return exp, find_variable(exp) return exp, find_variable(exp)
def find_possibilities(node, depth=0):
"""
Find all possibilities inside a node and return them in a list.
"""
p = []
handlers = []
# Add negation handlers
if node.negated:
handlers.extend(RULES[OP_NEG])
if not node.is_leaf:
# Traverse through child nodes first using postorder traversal
for child in node:
p.extend(find_possibilities(child, depth + 1))
# Add operator-specific handlers
if node.op in RULES:
handlers.extend(RULES[node.op])
# Run handlers
for handler in handlers:
possibilities = [(pos, depth) for pos in handler(node)]
p.extend(possibilities)
return p
class Parser(BisonParser): class Parser(BisonParser):
""" """
Implements the calculator parser. Grammar rules are defined in the method Implements the calculator parser. Grammar rules are defined in the method
...@@ -93,7 +121,6 @@ class Parser(BisonParser): ...@@ -93,7 +121,6 @@ class Parser(BisonParser):
('left', ('MINUS', 'PLUS', 'NEG')), ('left', ('MINUS', 'PLUS', 'NEG')),
('left', ('TIMES', 'DIVIDE')), ('left', ('TIMES', 'DIVIDE')),
('right', ('FUNCTION', )), ('right', ('FUNCTION', )),
#('left', ('NEG', )),
('right', ('POW', )), ('right', ('POW', )),
('left', ('SUB', )), ('left', ('SUB', )),
('right', ('FUNCTION_LPAREN', )), ('right', ('FUNCTION_LPAREN', )),
...@@ -239,50 +266,79 @@ class Parser(BisonParser): ...@@ -239,50 +266,79 @@ class Parser(BisonParser):
return data return data
def hook_handler(self, target, option, names, values, retval): def hook_handler(self, target, option, names, values, retval):
if target in ['exp', 'line', 'input'] \
or not isinstance(retval, ExpressionBase):
return retval return retval
if not retval.negated and retval.type != TYPE_OPERATOR: #if target in ['exp', 'line', 'input'] \
return retval # or not isinstance(retval, ExpressionBase):
# return retval
if retval.negated: #if not retval.negated and retval.type != TYPE_OPERATOR:
handlers = RULES[OP_NEG] # return retval
elif retval.type == TYPE_OPERATOR and retval.op in RULES:
handlers = RULES[retval.op]
else:
return retval
for handler in handlers: #if retval.negated:
possibilities = handler(retval) # handlers = RULES[OP_NEG]
self.possibilities.extend(possibilities) #elif retval.type == TYPE_OPERATOR and retval.op in RULES:
# handlers = RULES[retval.op]
#else:
# return retval
return retval #for handler in handlers:
# possibilities = handler(retval)
# self.possibilities.extend(possibilities)
#return retval
def find_possibilities(self):
if not self.root_node:
raise RuntimeError('No expression')
p = find_possibilities(self.root_node)
#sort_possiblities(p)
self.root_possibilities = [pos for pos, depth in p]
def display_hint(self): def display_hint(self):
print pick_suggestion(self.last_possibilities) self.find_possibilities()
if self.root_possibilities:
print self.root_possibilities[0]
else:
print 'No further reduction is possible.'
def display_possibilities(self): def display_possibilities(self):
if self.last_possibilities: self.find_possibilities()
print '\n'.join(map(str, self.last_possibilities))
if self.root_possibilities:
print '\n'.join(map(str, self.root_possibilities))
def rewrite(self): def rewrite(self):
suggestion = pick_suggestion(self.last_possibilities) self.find_possibilities()
if self.verbose: if not self.root_possibilities:
print 'applying suggestion:', suggestion return False
if not suggestion: suggestion = self.root_possibilities[0]
return self.root_node
if self.verbose:
print 'Applying suggestion:', suggestion
expression = apply_suggestion(self.root_node, suggestion) expression = apply_suggestion(self.root_node, suggestion)
if self.verbose: if self.verbose:
print 'After application, expression=', expression print 'After application:', expression
self.read_queue.put_nowait(str(expression)) self.root_node = expression
return True
def rewrite_all(self):
i = 0
while self.rewrite():
i += 1
return expression if i > 100:
print 'Too many rewrite steps, aborting...'
break
#def hook_run(self, filename, retval): #def hook_run(self, filename, retval):
# return retval # return retval
...@@ -304,7 +360,6 @@ class Parser(BisonParser): ...@@ -304,7 +360,6 @@ class Parser(BisonParser):
""" """
input : input :
| input line | input line
| input REWRITE NEWLINE
""" """
if option == 1: if option == 1:
# Interactive mode is enabled if the term rewriting system is used # Interactive mode is enabled if the term rewriting system is used
...@@ -315,10 +370,6 @@ class Parser(BisonParser): ...@@ -315,10 +370,6 @@ class Parser(BisonParser):
return values[1] return values[1]
if option == 2: # rule: input REWRITE NEWLINE
self.root_node = self.rewrite()
return self.root_node
def on_line(self, target, option, names, values): def on_line(self, target, option, names, values):
""" """
line : NEWLINE line : NEWLINE
...@@ -326,20 +377,11 @@ class Parser(BisonParser): ...@@ -326,20 +377,11 @@ class Parser(BisonParser):
| debug NEWLINE | debug NEWLINE
| HINT NEWLINE | HINT NEWLINE
| POSSIBILITIES NEWLINE | POSSIBILITIES NEWLINE
| REWRITE NEWLINE
| REWRITE_ALL NEWLINE
| RAISE NEWLINE | RAISE NEWLINE
""" """
if option == 1: # rule: EXP NEWLINE if option in (1, 2): # rule: {exp,debug} NEWLINE
self.root_node = values[0]
# Clear list of last possibilities when current expression has no
# possibilities. Otherwise, an invalid expression gets the last
# possibilities of a valid expression.
if not self.possibilities:
self.last_possibilities = []
return values[0]
if option == 2: # rule: DEBUG NEWLINE
self.root_node = values[0] self.root_node = values[0]
return values[0] return values[0]
...@@ -351,7 +393,15 @@ class Parser(BisonParser): ...@@ -351,7 +393,15 @@ class Parser(BisonParser):
self.display_possibilities() self.display_possibilities()
return return
if option == 5: if option == 5: # rule: REWRITE NEWLINE
self.rewrite()
return self.root_node
if option == 6: # rule: REWRITE_ALL NEWLINE
self.rewrite_all()
return self.root_node
if option == 7:
raise RuntimeError('on_line: exception raised') raise RuntimeError('on_line: exception raised')
def on_debug(self, target, option, names, values): def on_debug(self, target, option, names, values):
......
...@@ -18,7 +18,7 @@ class Possibility(object): ...@@ -18,7 +18,7 @@ class Possibility(object):
if self.handler in MESSAGES: if self.handler in MESSAGES:
return MESSAGES[self.handler].format(self.root, *self.args) return MESSAGES[self.handler].format(self.root, *self.args)
return self.__repr__() return repr(self)
def __repr__(self): def __repr__(self):
return '<Possibility root="%s" handler=%s args=%s>' \ return '<Possibility root="%s" handler=%s args=%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