incomp-flame-post/code/code_gen/calc.py
2019-04-19 02:08:36 +09:00

125 lines
2.6 KiB
Python

#
# This example shows how to write a basic calculator with variables.
#
from lark import Lark, Transformer, v_args
try:
input = raw_input # For Python2 compatibility
except NameError:
pass
'''
?function: "log" -> log
| "exp" -> exp
| "dx" -> dx
| "d2x" -> d2x
'''
calc_grammar = """
?varlist: "[" [NAME ("," NAME)*] "]"
?start: NAME "=" sum -> assign_var
| varlist
?sum: product
| sum "+" product -> add
| sum "-" product -> sub
?product: atom
| product "*" atom -> mul
| product "/" atom -> div
?atom: NUMBER -> number
| "-" atom -> neg
| NAME -> var
| "(" sum ")"
| function "(" sum ")" -> fcall
?function: "log" -> log
| "exp" -> exp
| "dx" -> dx
| "d2x" -> d2x
| "sqrt" -> sqrt
%import common.CNAME -> NAME
%import common.NUMBER
%import common.WS
%ignore WS
"""
@v_args(inline=True) # Affects the signatures of the methods
class CalculateTree(Transformer):
from operator import add, sub, mul, truediv as div, neg
number = float
def __init__(self):
self.primary = []
self.derived = {}
def varlist(self, *args):
for arg in args:
self.primary.append(arg.value)
return self.primary
def assign_var(self, name, value):
self.derived[name] = value
return "{} = {}".format(name, value)
def var(self, name):
return name
def fcall (self, a, b):
return "( {} ( {} ) )".format(a, b)
def neg(self, value):
return "( - {} )".format(value)
def add(self, a, b):
return "( {} + {} )".format(a, b)
def sub(self, a, b):
return "( {} - {} )".format(a, b)
def mul(self, a, b):
return "( {} * {} )".format(a, b)
def div(self, a, b):
return "( {} / {} )".format(a, b)
log = lambda self : "log"
exp = lambda self : "exp"
dx = lambda self : "dx"
d2x = lambda self : "d2x"
sqrt = lambda self : "sqrt"
tf=CalculateTree()
calc_parser = Lark(calc_grammar, parser='lalr' , transformer=tf)
calc = calc_parser.parse
def main():
while True:
try:
s = input('> ')
except EOFError:
break
print(calc(s))
def test():
with open("terms.input") as inputfile:
for line in inputfile:
if len(line.strip()) > 0:
print(calc(line))
if __name__ == '__main__':
test()
# main()