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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# SimpleCalc.py
#
# Demonstration of the parsing module,
# Sample usage
#
# $ python SimpleCalc.py
# Type in the string to be parse or 'quit' to exit the program
# > g=67.89 + 7/5
# 69.29
# > g
# 69.29
# > h=(6*g+8.8)-g
# 355.25
# > h + 1
# 356.25
# > 87.89 + 7/5
# 89.29
# > ans+10
# 99.29
# > quit
# Good bye!
#
#
from __future__ import division
# Uncomment the line below for readline support on interactive terminal
# import readline
import re
from pyparsing import Word, alphas, ParseException, Literal, CaselessLiteral \
, Combine, Optional, nums, Or, Forward, ZeroOrMore, StringEnd, alphanums
import math
# Debugging flag can be set to either "debug_flag=True" or "debug_flag=False"
debug_flag=False
exprStack = []
varStack = []
variables = {}
def pushFirst( str, loc, toks ):
exprStack.append( toks[0] )
def assignVar( str, loc, toks ):
varStack.append( toks[0] )
# define grammar
point = Literal('.')
e = CaselessLiteral('E')
plusorminus = Literal('+') | Literal('-')
number = Word(nums)
integer = Combine( Optional(plusorminus) + number )
floatnumber = Combine( integer +
Optional( point + Optional(number) ) +
Optional( e + integer )
)
ident = Word(alphas,alphanums + '_')
plus = Literal( "+" )
minus = Literal( "-" )
mult = Literal( "*" )
div = Literal( "/" )
lpar = Literal( "(" ).suppress()
rpar = Literal( ")" ).suppress()
addop = plus | minus
multop = mult | div
expop = Literal( "^" )
assign = Literal( "=" )
expr = Forward()
atom = ( ( e | floatnumber | integer | ident ).setParseAction(pushFirst) |
( lpar + expr.suppress() + rpar )
)
factor = Forward()
factor << atom + ZeroOrMore( ( expop + factor ).setParseAction( pushFirst ) )
term = factor + ZeroOrMore( ( multop + factor ).setParseAction( pushFirst ) )
expr << term + ZeroOrMore( ( addop + term ).setParseAction( pushFirst ) )
bnf = Optional((ident + assign).setParseAction(assignVar)) + expr
pattern = bnf + StringEnd()
# map operator symbols to corresponding arithmetic operations
opn = { "+" : ( lambda a,b: a + b ),
"-" : ( lambda a,b: a - b ),
"*" : ( lambda a,b: a * b ),
"/" : ( lambda a,b: a / b ),
"^" : ( lambda a,b: a ** b ) }
# Recursive function that evaluates the stack
def evaluateStack( s ):
op = s.pop()
if op in "+-*/^":
op2 = evaluateStack( s )
op1 = evaluateStack( s )
return opn[op]( op1, op2 )
elif op == "PI":
return math.pi
elif op == "E":
return math.e
elif re.search('^[a-zA-Z][a-zA-Z0-9_]*$',op):
if variables.has_key(op):
return variables[op]
else:
return 0
elif re.search('^[-+]?[0-9]+$',op):
return long( op )
else:
return float( op )
if __name__ == '__main__':
# input_string
input_string=''
# Display instructions on how to quit the program
print "Type in the string to be parse or 'quit' to exit the program"
input_string = raw_input("> ")
while input_string != 'quit':
# Start with a blank exprStack and a blank varStack
exprStack = []
varStack = []
if input_string != '':
# try parsing the input string
try:
L=pattern.parseString( input_string )
except ParseException,err:
L=['Parse Failure',input_string]
# show result of parsing the input string
if debug_flag: print input_string, "->", L
if len(L)==0 or L[0] != 'Parse Failure':
if debug_flag: print "exprStack=", exprStack
# calculate result , store a copy in ans , display the result to user
result=evaluateStack(exprStack)
variables['ans']=result
print result
# Assign result to a variable if required
if debug_flag: print "var=",varStack
if len(varStack)==1:
variables[varStack.pop()]=result
if debug_flag: print "variables=",variables
else:
print 'Parse Failure'
print err.line
print " "*(err.column-1) + "^"
print err
# obtain new input string
input_string = raw_input("> ")
# if user type 'quit' then say goodbye
print "Good bye!"
|