]>
jfr.im git - irc/rizon/acid.git/blob - pyva/src/main/python/internets/api/calc.py
2 from __future__
import division
3 from pyparsing
import (
4 Literal
, CaselessLiteral
, Word
, Combine
, Group
, Optional
,
5 ZeroOrMore
, Forward
, nums
, alphas
, oneOf
)
9 __author__
= 'Paul McGuire'
10 __version__
= '$Revision: 0.0 $'
11 __date__
= '$Date: 2009-03-20 $'
12 __source__
= '''http://pyparsing.wikispaces.com/file/view/fourFn.py
13 http://pyparsing.wikispaces.com/message/view/home/15549426
16 All I've done is rewrap Paul McGuire's fourFn.py as a class, so I can use it
17 more easily in other places.
21 class NumericStringParser(object):
24 Most of this code comes from the fourFn.py pyparsing example
28 def pushFirst(self
, strg
, loc
, toks
):
29 self
.exprStack
.append(toks
[0])
31 def pushUMinus(self
, strg
, loc
, toks
):
32 if toks
and toks
[0] == '-':
33 self
.exprStack
.append('unary -')
40 integer :: ['+' | '-'] '0'..'9'+
41 atom :: PI | E | real | fn '(' expr ')' | '(' expr ')'
42 factor :: atom [ expop factor ]*
43 term :: factor [ multop factor ]*
44 expr :: term [ addop term ]*
47 e
= CaselessLiteral("E")
48 fnumber
= Combine(Word("+-" + nums
, nums
) +
49 Optional(point
+ Optional(Word(nums
))) +
50 Optional(e
+ Word("+-" + nums
, nums
)))
51 ident
= Word(alphas
, alphas
+ nums
+ "_$")
56 lpar
= Literal("(").suppress()
57 rpar
= Literal(")").suppress()
61 pi
= CaselessLiteral("PI")
63 atom
= ((Optional(oneOf("- +")) +
64 (pi | e | fnumber | ident
+ lpar
+ expr
+ rpar
).setParseAction(self
.pushFirst
))
65 |
Optional(oneOf("- +")) + Group(lpar
+ expr
+ rpar
)
66 ).setParseAction(self
.pushUMinus
)
67 # by defining exponentiation as "atom [ ^ factor ]..." instead of
68 # "atom [ ^ atom ]...", we get right-to-left exponents, instead of left-to-right
69 # that is, 2^3^2 = 2^(3^2), not (2^3)^2.
72 ZeroOrMore((expop
+ factor
).setParseAction(self
.pushFirst
))
74 ZeroOrMore((multop
+ factor
).setParseAction(self
.pushFirst
))
76 ZeroOrMore((addop
+ term
).setParseAction(self
.pushFirst
))
77 # addop_term = ( addop + term ).setParseAction( self.pushFirst )
78 # general_term = term + ZeroOrMore( addop_term ) | OneOrMore( addop_term)
79 # expr << general_term
81 # map operator symbols to corresponding arithmetic operations
83 self
.opn
= {"+": operator
.add
,
86 "/": operator
.truediv
,
88 self
.fn
= {"sin": math
.sin
,
92 "trunc": lambda a
: int(a
),
94 "sgn": lambda a
: abs(a
) > epsilon
and cmp(a
, 0) or 0}
96 def evaluateStack(self
, s
):
99 return -self
.evaluateStack(s
)
101 op2
= self
.evaluateStack(s
)
102 op1
= self
.evaluateStack(s
)
103 return self
.opn
[op
](op1
, op2
)
105 return math
.pi
# 3.1415926535
107 return math
.e
# 2.718281828
109 return self
.fn
[op
](self
.evaluateStack(s
))
110 elif op
[0].isalpha():
115 def eval(self
, num_string
, parseAll
=True):
117 results
= self
.bnf
.parseString(num_string
, parseAll
) # has side effect that makes next line work
118 val
= self
.evaluateStack(self
.exprStack
[:])