Created
May 19, 2018 17:33
-
-
Save crowsonkb/0a524d6a68f454dd8919a67d9145829b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pyparsing as pp | |
from pyparsing import pyparsing_common as ppc | |
from repl import repl | |
variables = {} | |
var = ppc.identifier.copy() | |
def do_var(t): | |
try: | |
return variables[t[0]] | |
except KeyError as err: | |
raise pp.ParseFatalException(f'variable {err} is undefined') | |
var.addParseAction(do_var) | |
expr = pp.Forward() | |
expr.setName('expression') | |
atom = ppc.fnumber | var | pp.Suppress('(') + expr + pp.Suppress(')') | |
neg = '-' + atom | |
neg.addParseAction(lambda t: -t[1]) | |
s_atom = neg | atom | |
term = s_atom + pp.ZeroOrMore((pp.Literal('*') | pp.Literal('/')) + s_atom) | |
def do_term(t): | |
result = t[0] | |
for i in range(2, len(t), 2): | |
if t[i-1] == '*': | |
result *= t[i] | |
elif t[i-1] == '/': | |
result /= t[i] | |
return result | |
term.addParseAction(do_term) | |
expr <<= term + pp.ZeroOrMore((pp.Literal('+') | pp.Literal('-')) + term) | |
def do_expr(t): | |
result = t[0] | |
for i in range(2, len(t), 2): | |
if t[i-1] == '+': | |
result += t[i] | |
elif t[i-1] == '-': | |
result -= t[i] | |
return result | |
expr.addParseAction(do_expr) | |
assign = ppc.identifier + '=' + expr | |
assign.setName('assignment') | |
def do_assign(t): | |
variables[t[0]] = t[2] | |
return t[2] | |
assign.addParseAction(do_assign) | |
stmt = assign | expr | |
repl(stmt) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from prompt_toolkit import prompt | |
from prompt_toolkit.history import InMemoryHistory | |
from pyparsing import ParseBaseException | |
def sgr(*args): | |
return '\033[{}m'.format(';'.join(str(i) for i in args)) | |
def repl(parser): | |
parser.validate() | |
history = InMemoryHistory() | |
while True: | |
try: | |
s = prompt('> ', history=history) | |
result = parser.parseString(s, parseAll=True)[0] | |
print(result) | |
except ParseBaseException as err: | |
print(f'{sgr(1, 31)}{err.__class__.__name__}{sgr(0)}: {err}') | |
except KeyboardInterrupt: | |
pass | |
except EOFError: | |
break |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment