【问题标题】:Arithmetic Expression Evaluation using Reverse Polish Notation (RPN)使用逆波兰表示法 (RPN) 的算术表达式评估
【发布时间】:2014-01-13 19:15:26
【问题描述】:

数学表达式通常用中缀表示法表示。出于评估目的,我们可以将其更改为后缀(反向抛光)表示法(使用像 Shunting-Yard 这样的算法),然后使用堆栈评估后缀表示法。

我发现计算器使用了这种技术,但是今天的现代编译器是否使用它来进行算术表达式求值?它是否足够有效或正在使用其他技术(或算法)?

【问题讨论】:

  • 你说的是编译器的哪个部分?解析器?代码的中间表示(IR)?优化器中 IR 的编译时评估?从 IR 生成代码的过程?或者在运行时在评估代码中评估非常量表达式的方式?每个选项都有不同的答案。请添加一些上下文。

标签: compiler-construction infix-notation expression-evaluation shunting-yard


【解决方案1】:

要回答这个问题,让我们关注您提到的概念,infix notation、Shunting-Yard 和 evaluation,然后将它们与编译相关联。

首先,我们需要了解通常计算机如何处理表达式。表达式被转换为abstract syntax tree (AST),然后用于创建代码。将树转换为代码的过程各不相同,但遍历 AST 与评估表达式相同。

1+2 的 AST:

   + 
  / \ 
 1   2

后缀:1 2 +

这是通过访问左分支来评估的,1,
访问正确的分支,2,
然后将运算符 + 应用于两个操作数。

1*2+3^4 的 AST:

     + 
   /   \
  ^     *
 / \   / \
3   4 1   2

后缀:3 4 ^ 1 2 * +

这是由 访问左分支3^4,
然后访问它的左分支3,
然后访问它的右分支4,
然后访问运营商^, 并评估 3^4 并将其作为 `+' 的新左分支,即 81

然后访问正确的分支1*2,
然后访问它的左分支1,
然后访问它的右分支2,
然后访问运营商,*, 并评估 1*2 并将其作为“+”的新右分支,即 2

然后访问运营商,+, 并评估81+2 并将其作为结果返回83

现在中缀符号是syntactic sugar,以使使用表达式更易于人类阅读。为了帮助将中缀表示法转换为 AST,转换算法需要知道运算符的 precedence 和 associativity。该算法还使用一个堆栈,这是 Shunting-Yard 算法的主要关键之一。我所知道的将中缀转换为评估策略的所有方法都以某种方式使用堆栈。

虽然编译器不会像计算器应用程序那样显式地计算表达式,但编译器确实会将计算树的遍历转换为执行计算的代码。

注意:由于我不了解每种语言的每种编译器,因此我只能根据一般概念给您一个答案。没有规则要求遵循这些规则,如果某些编译器跳过 AST 并在不使用 AST 的情况下从输入代码转到编译代码,我不会感到惊讶。

另外,既然你提到了编译器,我只讨论了编译后的代码,没有涉及脚本语言。

现在回到您的问题:

当今的现代编译器是否将其用于算术表达式 评价?

我不会专门使用 Shunting-Yard 算法,而是使用堆栈的概念,这是我将使用的算法的关键概念之一。如果使用算法的概念与使用算法相同,您可以自己选择。

它是否足够有效或正在使用其他技术(或算法) 用过吗?

希望您现在知道这个问题的答案。重要的不是 Shunting-Yard 算法,而是使用堆栈转换中缀符号的概念很重要,这也是编译器所使用的。请记住,编译语言通常不仅仅计算表达式,它们还可以处理类型、处理条件表达式、存储值以及创建更高的类型,例如方法/函数、类和模块。

【讨论】:

    猜你喜欢
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 2021-12-24
    • 2015-06-15
    相关资源
    最近更新 更多