Commit 2d9ca51e authored by Taddeus Kroes's avatar Taddeus Kroes

Merge branch 'master' of kompiler.org:trs

parents f057cada 6c7eb676
...@@ -20,6 +20,8 @@ from node import TYPE_OPERATOR, OP_COMMA ...@@ -20,6 +20,8 @@ from node import TYPE_OPERATOR, OP_COMMA
from rules import RULES from rules import RULES
from possibilities import filter_duplicates, pick_suggestion, apply_suggestion from possibilities import filter_duplicates, pick_suggestion, apply_suggestion
import Queue
# Check for n-ary operator in child nodes # Check for n-ary operator in child nodes
def combine(op, op_type, *nodes): def combine(op, op_type, *nodes):
...@@ -74,16 +76,31 @@ class Parser(BisonParser): ...@@ -74,16 +76,31 @@ class Parser(BisonParser):
self.timeout = kwargs.get('timeout', 0) self.timeout = kwargs.get('timeout', 0)
self.possibilities = self.last_possibilities = [] self.possibilities = self.last_possibilities = []
self.read_buffer = ''
self.read_queue = Queue.Queue()
# Override default read method with a version that prompts for input. # Override default read method with a version that prompts for input.
def read(self, nbytes): def read(self, nbytes):
if self.file == sys.stdin and self.file.closed: if self.file == sys.stdin and self.file.closed:
return '' return ''
if not self.read_buffer and not self.read_queue.empty():
self.read_buffer = self.read_queue.get_nowait() + '\n'
if self.read_buffer:
read_buffer = self.read_buffer[:nbytes]
self.read_buffer = self.read_buffer[nbytes:]
return read_buffer
try: try:
return raw_input('>>> ' if self.interactive else '') + '\n' read_buffer = raw_input('>>> ' if self.interactive else '') + '\n'
except EOFError: except EOFError:
return '' return ''
self.read_buffer = read_buffer[nbytes:]
return read_buffer[:nbytes]
def hook_read_before(self): def hook_read_before(self):
if self.possibilities: if self.possibilities:
if self.interactive: # pragma: nocover if self.interactive: # pragma: nocover
...@@ -95,14 +112,17 @@ class Parser(BisonParser): ...@@ -95,14 +112,17 @@ class Parser(BisonParser):
if self.interactive: # pragma: nocover if self.interactive: # pragma: nocover
print ' ' + '\n '.join(map(str, items)) print ' ' + '\n '.join(map(str, items))
self.possibilities = []
def hook_read_after(self, data): def hook_read_after(self, data):
""" """
This hook will be called when the read() method returned. The data This hook will be called when the read() method returned. The data
argument points to the data read by the read() method. This hook argument points to the data read by the read() method. This hook
function should return the data to be used by the parser. function should return the data to be used by the parser.
""" """
if not data.strip():
return data
self.possibilities = []
import re import re
# TODO: remove this quick preprocessing hack. This hack enables # TODO: remove this quick preprocessing hack. This hack enables
...@@ -187,7 +207,6 @@ class Parser(BisonParser): ...@@ -187,7 +207,6 @@ class Parser(BisonParser):
input : input :
| input line | input line
""" """
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
# as a shell. In that case, it is useful that the shell prints the # as a shell. In that case, it is useful that the shell prints the
...@@ -207,20 +226,22 @@ class Parser(BisonParser): ...@@ -207,20 +226,22 @@ class Parser(BisonParser):
| REWRITE NEWLINE | REWRITE NEWLINE
| RAISE NEWLINE | RAISE NEWLINE
""" """
if option in [1, 2]: if option in [1, 2]: # rule: EXP NEWLINE | DEBUG NEWLINE
return values[0] return values[0]
if option == 3: if option == 3: # rule: HINT NEWLINE
print pick_suggestion(self.last_possibilities) print pick_suggestion(self.last_possibilities)
return return
if option == 4: if option == 4: # rule: POSSIBILITIES NEWLINE
print '\n'.join(map(str, self.last_possibilities)) print '\n'.join(map(str, self.last_possibilities))
return return
if option == 5: if option == 5: # rule: REWRITE NEWLINE
suggestion = pick_suggestion(self.last_possibilities) suggestion = pick_suggestion(self.last_possibilities)
return apply_suggestion(suggestion) expression = apply_suggestion(suggestion)
self.read_queue.put_nowait(str(expression))
return expression
if option == 6: if option == 6:
raise RuntimeError('on_line: exception raised') raise RuntimeError('on_line: exception raised')
......
...@@ -4,6 +4,9 @@ from src.possibilities import MESSAGES, Possibility as P, filter_duplicates ...@@ -4,6 +4,9 @@ from src.possibilities import MESSAGES, Possibility as P, filter_duplicates
from src.rules.numerics import add_numerics from src.rules.numerics import add_numerics
from tests.test_rules_poly import tree from tests.test_rules_poly import tree
from src.parser import Parser
from tests.parser import ParserWrapper
def dummy_handler(root, args): # pragma: nocover def dummy_handler(root, args): # pragma: nocover
pass pass
...@@ -36,6 +39,36 @@ class TestPossibilities(unittest.TestCase): ...@@ -36,6 +39,36 @@ class TestPossibilities(unittest.TestCase):
assert self.p0 == P(self.n, dummy_handler, (self.l1, self.l2)) assert self.p0 == P(self.n, dummy_handler, (self.l1, self.l2))
assert self.p0 != self.p1 assert self.p0 != self.p1
def test_multiple_input(self):
parser = ParserWrapper(Parser)
parser.run(['1+2', '3+4'])
possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="3 + 4" handler=add_numerics' \
' args=(3, 4, 3, 4)>')
def test_multiple_runs(self):
parser = ParserWrapper(Parser)
parser.run(['1+2'])
possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="1 + 2" handler=add_numerics' \
' args=(1, 2, 1, 2)>')
# Keep previous possibilities (skip whitespace lines)
parser.run(['', ' '])
possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="1 + 2" handler=add_numerics' \
' args=(1, 2, 1, 2)>')
# Overwrite previous possibilities with new ones
parser.run(['3+4'])
possibilities = parser.parser.possibilities
self.assertEqual('\n'.join([repr(pos) for pos in possibilities]),
'<Possibility root="3 + 4" handler=add_numerics' \
' args=(3, 4, 3, 4)>')
def test_filter_duplicates(self): def test_filter_duplicates(self):
a, b = ab = tree('a + b') a, b = ab = tree('a + b')
p0 = P(a, dummy_handler, (1, 2)) p0 = P(a, dummy_handler, (1, 2))
......
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