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

OR  number + number

| number'+'number

;

number + number + number + number

[number + number] + number + number

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

| mul'+'mul

| mul

;

mul: mul'*'number

| number'*'number

| number

;

| mul

;

mul: mul'*'number

| number

;

number + number * number * number

number + [number] * number * number

number + [mul * number] * number

number + [mul * number]

[number] + mul

[mul] + mul

mul: mul mul_symbol number | number;

number:'[d.]+';      // 十进制数的正则表达式

mul_symbol:'*'|'/';// Match * or /

>>>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

?mul: mul mul_symbol number | number;// Expand mul if it's just a number

number:'[d.]+';

mul_symbol:'*'|'/';

>>> 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

?mul: (mul mul_symbol)? atom;

neg:'-'atom;

number:'[d.]+';

mul_symbol:'*'|'/';

WHITESPACE:'[ t]+'(%ignore);

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

尾(tail)：包含所有与其匹配的子规则的列表。

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

>>>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，现在我们运行这段代码来检查一下结果。

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

31.357142857142858

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

31.357142857142858

defmain():

calc=Calc()

whileTrue:

try:

s=raw_input('> ')

exceptEOFError:

break

ifs=='':

break

tree=calc_grammar.parse(s)

printcalc.transform(tree)

https://github.com/erezsh/plyplus/blob/master/examples/calc.py

PythonTab微信公众号:

Python技术交流互助群 ( 请勿加多个群 ):