Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions 3.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ Exp('add', [1, Exp('mul', [2, 3, 4])])

**求值。**`calc_eval`函数接受表达式作为参数,并返回它的值。它根据表达式的形式为表达式分类,并且指导它的求值。对于计算器来说,表达式的两种句法形式是数值或调用表达式,后者是`Exp`的实例。数值是自求值的,它们可以直接从`calc_eval`中返回。调用表达式需要使用函数。

```py
>>> def calc_eval(exp):
"""Evaluate a Calculator expression."""
if type(exp) in (int, float):
return exp
elif type(exp) == Exp:
arguments = list(map(calc_eval, exp.operands))
return calc_apply(exp.operator, arguments)
```

调用表达式首先通过将`calc_eval`函数递归映射到操作数的列表,计算出参数列表来求值。之后,在第二个函数`calc_apply`中,运算符会作用于这些参数上。

计算器语言足够简单,我们可以轻易地在单一函数中表达每个运算符的使用逻辑。在`calc_apply`中,每种条件子句对应一个运算符。
Expand Down Expand Up @@ -265,7 +275,7 @@ Exp('add', [2, Exp('mul', [4, 6])])
'add(2, mul(4, 6))'
```

`analyse`函数只会返回符合格式的表达式树,并且它必须检测输入中的语法错误。特别是,它必须检测表达式是否完整、正确分隔,以及只含有已知的运算符。下面的修订版本确保了语法分析的每一步都找到了预期的标记。
`analyze`函数只会返回符合格式的表达式树,并且它必须检测输入中的语法错误。特别是,它必须检测表达式是否完整、正确分隔,以及只含有已知的运算符。下面的修订版本确保了语法分析的每一步都找到了预期的标记。

```py
>>> known_operators = ['add', 'sub', 'mul', 'div', '+', '-', '*', '/']
Expand Down Expand Up @@ -298,6 +308,6 @@ Exp('add', [2, Exp('mul', [4, 6])])
raise SyntaxError('unexpected end of line')
```

大量的语法错误在本质上提升了解释器的可用性。在上面,`SyntaxError `异常包含所发生的问题描述。这些错误字符串也用作这些分析函数的定义文档。
信息丰富的语法错误在本质上提升了解释器的可用性。在上面,`SyntaxError `异常包含所发生的问题描述。这些错误字符串也用作这些分析函数的定义文档。

这个定义完成了我们的计算器解释器。你可以获取单独的 Python 3 源码 [`calc.py`](http://www-inst.eecs.berkeley.edu/~cs61a/sp12/book/calc.py)来测试。我们的解释器对错误健壮,用户在`calc>`提示符后面的每个输入都会求值为数值,或者产生合适的错误,描述输入为什么不是符合格式的计算器表达式。
这个定义完成了我们的计算器解释器。你可以获取单独的 Python 3 源码 [`calc.py`](http://www-inst.eecs.berkeley.edu/~cs61a/sp12/book/calc.py)来测试。我们的解释器对错误的处理能力很强,用户在`calc>`提示符后面的每个输入都会求值为数值,或者产生合适的错误,描述输入为什么不是符合格式的计算器表达式。