How To Write A Calculator in 70 Python Lines
blog.erezsh.com
blog.erezsh.com
print input()
> 25*4-50
> 50 >>> print input()
"a"+"b"
ab try:print(lambda x:eval(x)if all(i in'0123456789.*/+-'for i in x)else'syntax error')(raw_input())
except:print'error'A. I don't need to; other people will write it for me.
That's fine, I guess. I prefer to understand.
$ python -c "print input('> ')" > 2+3*5 17
Thanks for the cool post. I am not sure I got the difference between the LL and LR parser. Is what you have above an LR parser?
Also, why did you choose to represent both + and - as "ADD" tokens (and * and / as "MUL") is this to enforce evaluation priority? It would be interesting to see if you can add or ^ as an exponent for this calculator.
Maybe you intended this post strictly as as an educational post, but I think doing parsing right (and from first principles) is a really cool thing to have. Check out how khan-exercises framework uses to parse math expressions into an AST: https://github.com/Khan/khan-exercises/blob/master/utils/mat...
An LL-parser tries to expand the initial rule into a more complex rule structure, until it matches the input. So to match a+b+c+d it will do [start] -> [add] -> [add] + [num] -> [add] + [num] + [num] -> etc.
What I wrote is an LL-parser, simply because it's much much simpler to write and to understand.
Yes, both ADD and MUL are used for precedence. Since any list of +- or of */ will evaluate correctly if reduced from left to right, I didn't mind grouping them together and making my life easier (and shorter).
It was strictly educational, and also a shtick; a short code hack. If I was to write an actual parser (and I don't think I would ever try to), it would look very different!
I think a precedence parser could be even shorter, though I don't seem to have one handy in Python. Pratt parsing is similar, though: https://github.com/darius/sketchbook/blob/master/parsing/pra... And here's precedence parsing in C: http://wry.me/~darius/hacks/dcalc.c (I learned this method from Dave Gillespie, author of Gnu Calc.)
Finally, using a small parsing library very similar to the scheme in this post: https://github.com/darius/peglet/blob/master/examples/infix....
https://gist.github.com/ascv/5022712
The idea isn't to 1-up the OP but rather to showcase the technique of recursive descent parsing. The wikipedia entry for recursive descent parsing also has a very nice example.
> 10/2*2
2.5The idea is what is important though. Recursive descent parsing uses the functions that correspond to types in the grammar to mutually call each other thus parsing the expression recursively in a descending fashion.
from sympy import *
var('x,b,c')
print solve(a*x**2+b*x+c,x)
Result: [(-b + (-4*a*c + b**2)**(1/2))/(2*a), -(b + (-4*a*c + b**2)**(1/2))/(2*a)]>>> import this
... though rules are made to be broken
Then you wouldn't be too far from Norvig's little educational gems.
Thank you, you gave me a great compliment. Norvig's short spellchecker was very inspirational for me.