## 如何使用 50 行 Python代码制作一个计算器

1
2
OR  number + number

1
2
3
| number'+'number
;

number + number + number + number

[number + number] + number + number

1 + 2 * 3 / 4 – 5 + 6

1 + (2 * 3 / 4) – 5 + 6

1
2
3
4
5
6
| mul'+'mul
;
mul: mul '*; number
| number'*'number
;

number + number * number * number
number + [number * number] * number

number + [mul * number]
number + mul
???

1
2
3
4
5
6
7
8
| mul'+'mul
| mul
;
mul: mul'*'number
| number'*'number
| number
;

1
2
3
4
5
6
| mul
;
mul: mul'*'number
| number
;

number + number * number * number

number + [number] * number * number
number + [mul * number] * number
number + [mul * number]
[number] + mul
[mul] + mul

1
2
3
4
5
6
mul: mul mul_symbol number | number;
number:'[d.]+';      // 十进制数的正则表达式
mul_symbol:'*'|'/';// Match * or /

Shell
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
>>>fromplyplusimportGrammar
>>> g=Grammar(&quot;&quot;&quot;...&quot;&quot;&quot;)
>>>printg.parse('1+2*3-5').pretty()
start
mul
number
1
+
mul
mul
number
2
mul_symbol
*
number
3
-
mul
number
5

1
2
3
4
5
6
?mul: mul mul_symbol number | number;// Expand mul if it's just a number
number:'[d.]+';
mul_symbol:'*'|'/';

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> g=Grammar(&quot;&quot;&quot;...&quot;&quot;&quot;)
>>>printg.parse('1+2*3-5').pretty()
start
number
1
+
mul
number
2
mul_symbol
*
number
3
-
number
5

1
2
3
4
5
6
7
8
9
?mul: (mul mul_symbol)? atom;
@atom : neg | number |'('add')';
neg:'-'atom;
number:'[d.]+';
mul_symbol:'*'|'/';
WHITESPACE:'[ t]+'(%ignore);

1.每个分支都是包含如下两个属性的实例：

尾(tail)：包含所有与其匹配的子规则的列表。
2.Plyplus默认会删除不必要的标记。在本例中，'( ‘ ，’)’ 和 ‘-‘ 会被删除。但add和mul会有自己的规则，Plyplus会知道它们是必须的，从而不会被删除它们。如果你需要保留这些标记，可以手动关掉这项功能，但从我的经验来看，最好不要这样做，而是手动修改相关语法效果更佳。

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>>importoperator as op
>>>fromplyplusimportSTransformer

classCalc(STransformer):

def_bin_operator(self, exp):
arg1, operator_symbol, arg2=exp.tail

'-': op.sub,
'*': op.mul,
'/': op.div }[operator_symbol]

returnoperator_func(arg1, arg2)

number     =lambdaself, exp:float(exp.tail[0])
neg        =lambdaself, exp:-exp.tail[0]
__default__=lambdaself, exp: exp.tail[0]

mul=_bin_operator

OK，现在我们运行这段代码来检查一下结果。

Shell
1
2
>>> Calc().transform( g.parse('1 + 2 * -(-3+2) / 5.6 + 30'))
31.357142857142858

Shell
1
2
>>>eval('1 + 2 * -(-3+2) / 5.6 + 30')
31.357142857142858

Python
1
2
3
4
5
6
7
8
9
10
11
defmain():
calc=Calc()
whileTrue:
try:
s=raw_input('> ')
exceptEOFError:
break
ifs=='':
break
tree=calc_grammar.parse(s)
printcalc.transform(tree)我有建立一个python学习交流群，在群里我们相互帮助，相互关心，相互分享内容，这样出问题帮助你的人就比较多，群号是301，还有056，最后是051，这样就可以找到大神聚合的群，如果你只愿意别人帮助你，不愿意分享或者帮助别人，那就请不要加了，你把你会的告诉别人这是一种分享。如果你看了觉得还可以的麻烦给我点个赞谢谢