Skip to content

Instantly share code, notes, and snippets.

@hltbra
Created January 17, 2010 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hltbra/279357 to your computer and use it in GitHub Desktop.
Save hltbra/279357 to your computer and use it in GitHub Desktop.
'''
The BNF for this small infix calculator looks like:
<expr> ::= <num>
| (<num>)
| (+ <expr> <expr>)
| (- <expr> <expr>)
| (* <expr> <expr>)
| (/ <expr> <expr>)
| (^ <expr> <expr>)
>>> calculate('666')
666.0
>>> calculate('(666)')
666.0
>>> calculate('(+ 1 2)')
3.0
>>> calculate('1 + 2')
Traceback (most recent call last):
...
ParseException: Please, correct your input! (at char 0), (line:1, col:1)
>>> calculate('(- (* 1 2) 3)')
-1.0
>>> calculate('(^ 2 (/ (+ (* (- 1 2) -3) 5) 2))')
16.0
'''
from pyparsing import *
expr = Forward()
point = Literal('.')
blanks = ZeroOrMore(White()).suppress()
lparent = Literal('(').suppress()
rparent = Literal(')').suppress()
plus = Literal('+')
minus = Literal('-')
multiply = Literal('*')
division = Literal('/')
exp = Literal('^')
operator = plus | minus | multiply | division | exp
number = Word(nums)
float_number = Combine(Optional(plus|minus) + number + Optional(point + Optional(number)))
atom = float_number | expr
expr << (float_number |
Combine(lparent + float_number + rparent) |
Group(lparent + operator + blanks + atom + blanks + atom + rparent))
OPERATORS = {
'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
'*': lambda x, y: x * y,
'/': lambda x, y: x / y,
'^': lambda x, y: x ** y,
}
def _evaluate(e):
if isinstance(e, str):
return float(e)
operation = OPERATORS[e[0]]
return operation(_evaluate(e[1]),
_evaluate(e[2]))
def calculate(e):
try:
expressions = expr.parseString(e, True)
return _evaluate(expressions[0])
except ParseException:
raise ParseException('Please, correct your input!')
if __name__ == '__main__':
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment