1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
globalvars = {} # We will store the calculator's variables here
def lookup(map, name):
for x,v in map:
if x == name: return v
if name not in globalvars: print('Undefined (defaulting to 0):', name)
return globalvars.get(name, 0)
def stack_input(scanner,ign):
"""Grab more input"""
scanner.stack_input(input(">?> "))
%%
parser Calculator:
ignore: "[ \r\t\n]+"
ignore: "[?]" {{ stack_input }}
token END: "$"
token NUM: "[0-9]+"
token VAR: "[a-zA-Z_]+"
# Each line can either be an expression or an assignment statement
rule goal: expr<<[]>> END {{ print('=', expr) }}
{{ return expr }}
| "set" VAR expr<<[]>> END {{ globalvars[VAR] = expr }}
{{ print(VAR, '=', expr) }}
{{ return expr }}
# An expression is the sum and difference of factors
rule expr<<V>>: factor<<V>> {{ n = factor }}
( "[+]" factor<<V>> {{ n = n+factor }}
| "-" factor<<V>> {{ n = n-factor }}
)* {{ return n }}
# A factor is the product and division of terms
rule factor<<V>>: term<<V>> {{ v = term }}
( "[*]" term<<V>> {{ v = v*term }}
| "/" term<<V>> {{ v = v/term }}
)* {{ return v }}
# A term is a number, variable, or an expression surrounded by parentheses
rule term<<V>>:
NUM {{ return int(NUM) }}
| VAR {{ return lookup(V, VAR) }}
| "\\(" expr "\\)" {{ return expr }}
| "let" VAR "=" expr<<V>> {{ V = [(VAR, expr)] + V }}
"in" expr<<V>> {{ return expr }}
%%
if __name__=='__main__':
print('Welcome to the calculator sample for Yapps 2.')
print(' Enter either "<expression>" or "set <var> <expression>",')
print(' or just press return to exit. An expression can have')
print(' local variables: let x = expr in expr')
# We could have put this loop into the parser, by making the
# `goal' rule use (expr | set var expr)*, but by putting the
# loop into Python code, we can make it interactive (i.e., enter
# one expression, get the result, enter another expression, etc.)
while 1:
try: s = input('>>> ')
except EOFError: break
if not s.strip(): break
parse('goal', s)
print('Bye.')
|