Moved argument parser and added 'hint' and 'apply'

Introduced new symbols "?" (suggest hint) and '@' (apply one suggestion).
Moved the argument parser to main.py.

Removed replace from expression{leaf,node}.
parent 834e15e0
#!/usr/bin/python
"""
Shell front-end for the mathematical term rewriting system. This shell will
parse mathematical expressions into an expression tree, produce possible
rewrite steps and, if requested, provide a hint to rewrite the last entered
expression.
"""
import argparse
import sys
import os
def init_readline():
import os
try:
import readline
except ImportError:
......@@ -19,7 +28,48 @@ def init_readline():
atexit.register(readline.write_history_file, histfile)
def get_args():
parser = argparse.ArgumentParser(prog='trs', description=__doc__)
parser.add_argument('--debug', '-d', action='store_true',
default=False,
help='Enable debug mode in bison and flex.')
parser.add_argument('--verbose', '-v', action='store_true',
default=False,
help='Enable verbose output messages (printed to stdout).')
parser.add_argument('--keepfiles', '-k', action='store_true',
default=False,
help='Keep temporary generated bison and lex files.')
parser.add_argument('--batch', '-b', action='store_true', default=False,
help='Disable interactive mode and execute expressions in batch' \
' mode.')
parser.add_argument('--interactive', action='store_true',
default=sys.stdin.isatty(),
help='Enable interactive mode (default). This is the inverse of' \
' --batch.')
return parser.parse_args()
def main():
from src.parser import Parser
args = get_args()
interactive = args.interactive and not args.batch
p = Parser(verbose=args.verbose,
keepfiles=args.keepfiles,
interactive=interactive)
node = p.run(debug=args.debug)
# Clear the line, when the shell exits.
if interactive:
print
return node
if __name__ == '__main__':
from src.parser import main
init_readline()
main()
......@@ -128,12 +128,6 @@ class ExpressionNode(Node, ExpressionBase):
def graph(self): # pragma: nocover
return generate_graph(self)
def replace(self, node):
pos = self.parent.nodes.index(self)
self.parent.nodes[pos] = node
node.parent = self.parent
self.parent = None
def extract_polynome_properties(self):
"""
Extract polynome properties into tuple format: (coefficient, root,
......@@ -219,12 +213,3 @@ class ExpressionLeaf(Leaf, ExpressionBase):
"""
# rule: 1 * r ^ 1 -> (1, r, 1)
return (ExpressionLeaf(1), self, ExpressionLeaf(1))
def replace(self, node):
if not hasattr(self, 'parent'):
return
pos = self.parent.nodes.index(self)
self.parent.nodes[pos] = node
node.parent = self.parent
self.parent = None
#!/usr/bin/env python
"""
This parser will parse the given input and build an expression tree. Grammar
file for the supported mathematical expressions.
......@@ -6,8 +5,6 @@ file for the supported mathematical expressions.
from node import ExpressionNode as Node, ExpressionLeaf as Leaf
import argparse
import os.path
PYBISON_BUILD = os.path.realpath('build/external/pybison')
EXTERNAL_MODS = os.path.realpath('external')
......@@ -21,7 +18,7 @@ from graph_drawing.graph import generate_graph
from node import TYPE_OPERATOR, OP_COMMA
from rules import RULES
from possibilities import filter_duplicates
from possibilities import filter_duplicates, pick_suggestion, apply_suggestion
# Check for n-ary operator in child nodes
......@@ -55,7 +52,7 @@ class Parser(BisonParser):
# of tokens of the lex script.
tokens = ['NUMBER', 'IDENTIFIER',
'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'POW',
'LPAREN', 'RPAREN', 'COMMA',
'LPAREN', 'RPAREN', 'COMMA', 'HINT', 'REWRITE',
'NEWLINE', 'QUIT', 'RAISE', 'GRAPH']
# ------------------------------
......@@ -75,11 +72,9 @@ class Parser(BisonParser):
BisonParser.__init__(self, **kwargs)
self.interactive = kwargs.get('interactive', 0)
self.timeout = kwargs.get('timeout', 0)
self.possibilities = []
self.possibilities = self.last_possibilities = []
# ------------------------------------------------------------------
# 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):
if self.file == sys.stdin and self.file.closed:
return ''
......@@ -90,10 +85,15 @@ class Parser(BisonParser):
return ''
def hook_read_before(self):
if self.interactive and self.possibilities:
print 'possibilities:'
if self.possibilities:
if self.interactive: # pragma: nocover
print 'possibilities:'
items = filter_duplicates(self.possibilities)
print ' ' + '\n '.join(map(str, items))
self.last_possibilities = self.possibilities
if self.interactive: # pragma: nocover
print ' ' + '\n '.join(map(str, items))
self.possibilities = []
......@@ -147,7 +147,7 @@ class Parser(BisonParser):
if data == data_after:
break
if self.verbose:
if self.verbose: # pragma: nocover
print 'hook_read_after() modified the input data:'
print 'before:', data.replace('\n', '\\n')
print 'after :', data_after.replace('\n', '\\n')
......@@ -192,7 +192,7 @@ class Parser(BisonParser):
# 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
# output of the evaluation.
if self.interactive and values[1]:
if self.interactive and values[1]: # pragma: nocover
print values[1]
return values[1]
......@@ -202,12 +202,22 @@ class Parser(BisonParser):
line : NEWLINE
| exp NEWLINE
| debug NEWLINE
| HINT NEWLINE
| REWRITE NEWLINE
| RAISE NEWLINE
"""
if option in [1, 2]:
return values[0]
if option == 3:
print pick_suggestion(self.last_possibilities)
return
if option == 4:
suggestion = pick_suggestion(self.last_possibilities)
return apply_suggestion(suggestion)
if option == 5:
raise RuntimeError('on_line: exception raised')
def on_debug(self, target, option, names, values):
......@@ -332,6 +342,8 @@ class Parser(BisonParser):
"^" { returntoken(POW); }
"/" { returntoken(DIVIDE); }
"," { returntoken(COMMA); }
"?" { returntoken(HINT); }
"@" { returntoken(REWRITE); }
"quit" { yyterminate(); returntoken(QUIT); }
"raise" { returntoken(RAISE); }
"graph" { returntoken(GRAPH); }
......@@ -344,39 +356,3 @@ class Parser(BisonParser):
yywrap() { return(1); }
"""
def get_args():
parser = argparse.ArgumentParser(prog='parser', description=__doc__)
parser.add_argument('--debug', '-d', action='store_true',
default=False,
help='Enable debug mode in bison and flex.')
parser.add_argument('--verbose', '-v', action='store_true',
default=False,
help='Enable verbose output messages (printed to stdout).')
parser.add_argument('--keepfiles', '-k', action='store_true',
default=False,
help='Keep temporary generated bison and lex files.')
parser.add_argument('--batch', '-b', action='store_true', default=False,
help='Disable interactive mode and execute expressions in batch' \
' mode.')
return parser.parse_args()
def main():
args = get_args()
interactive = not args.batch and sys.stdin.isatty()
p = Parser(verbose=args.verbose,
keepfiles=args.keepfiles,
interactive=interactive)
node = p.run(debug=args.debug)
# Clear the line, when the shell exits.
if interactive:
print
return node
......@@ -36,3 +36,13 @@ def filter_duplicates(items):
unique.append(item)
return unique
def pick_suggestion(possibilities):
# TODO: pick the best suggestion.
suggestion = 0
return possibilities[suggestion]
def apply_suggestion(suggestion):
return suggestion.handler(suggestion.root, suggestion.args)
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