由我的大学codeboot.org构建的解释器为表达式提供了一步一步的执行.因此,我能够看到程序是如何读取算术表达式的。这就是我开始忏悔的地方。
例如,这个表达式: 10-5+(7+2)/3
我们总是说我们应该计算括号中的表达式,因此,这就是我所期望的顺序。
但是,解释器执行的内容完全不同。
尽管结果是一样的,但为什么要先计算10-5呢?而“我们必须先计算括号中的内容”会发生什么呢?这让我很困惑
我想知道,这是否是正确的行为,解释器总是从左到右,并计算它可以首先计算的一切。而不是像我们预期的那样直接跳入()
发布于 2020-09-05 18:40:01
“先做括号”不是JS中的一条规则。“从左到右”也不是一条规则。以1 + 4 * 6
为例。严格的从左到右会导致
这不是JS做的。
相反,JS将表达式解析为表达式树,然后从树根开始计算它。(严格地说,构建树不需要JS实现,但它必须提供与树相同的结果。)
例如,示例表达式10-5+(7+2)/3
将生成一棵树,大致如下所示:
AdditiveExpression:
AdditiveExpression
AdditiveExpression
MultiplicativeExpression
... NumericLiteral 10
- -
MultiplicativeExpression
... NumericLiteral 5
+ +
MultiplicativeExpression
MultiplicativeExpression
... ParenthesizeExpression
( (
Expression
... AdditiveExpression 7+2
) )
MultiplicativeOperator /
ExponentiationExpression
... NumericLiteral 3
其中:
的完整子树。
(我找不到让codeboot.org显示其解析树的方法。如果有某种方式,或者使用其他工具来显示表达式的解析树,请注意,它看起来可能与上面不完全相同,但是它应该非常相似,这样就会产生相同的行为。)
要计算表达式,它从根开始,根是一个AdditiveExpression
,其子级为:
(7+2)/3
).
AdditiveExpression
(用于10-5
)、+
令牌和MultiplicativeExpression
(用于10-5
)规则是
这就是为什么(a) 10-5 => 5
是您的解释器计算的第一件事。
接下来是(b)计算MultiplicativeExpression for (7+2)/3
。这里的规则类似,所以我们需要:
/
. (
(7+2)
),然后计算右操作数( ExponentiationExpression表示3
),所以(b1) 7+2 => 9
是下一件事
然后(b2) 3 => 3
然后(b3) 9/3 => 3
。
我们现在完成了步骤(b),所以我们继续到(c) 5+3 => 8
。
这与您的解释器执行的一系列计算相匹配。
https://stackoverflow.com/questions/63743918
复制相似问题