Compiler construction 使用反向波兰符号(RPN)的算术表达式求值

Compiler construction 使用反向波兰符号(RPN)的算术表达式求值,compiler-construction,infix-notation,expression-evaluation,shunting-yard,Compiler Construction,Infix Notation,Expression Evaluation,Shunting Yard,数学表达式通常用中缀符号表示。出于计算目的,我们可以将其更改为后缀(反向波兰)表示法(使用类似的算法),然后使用堆栈计算后缀表示法 我发现计算器使用这种技术,但今天的现代编译器是否使用这种技术来计算算术表达式?它是否足够有效,或者正在使用其他技术(或算法)?为了回答这个问题,让我们集中讨论您提到的概念,中缀符号,调车场和评估,然后将它们与编译联系起来 首先,我们需要了解计算机如何处理表达式。表达式转换为(AST),然后用于创建代码。将树转换为代码的过程各不相同,但AST的遍历与计算表达式的过程相

数学表达式通常用中缀符号表示。出于计算目的,我们可以将其更改为后缀(反向波兰)表示法(使用类似的算法),然后使用堆栈计算后缀表示法


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

为了回答这个问题,让我们集中讨论您提到的概念,
中缀符号
调车场
评估
,然后将它们与编译联系起来

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

1+2的AST:

   + 
  / \ 
 1   2
后缀:
12+

这通过访问左分支进行评估,
1

访问右分支,
2

然后将运算符
+
应用于两个操作数

1*2+3^4的AST:

     + 
   /   \
  ^     *
 / \   / \
3   4 1   2
后缀:
34^12*+

这是由 访问左分支
3^4

然后访问它的左分支
3

然后访问它的右分支
4

然后访问操作员,
^
, 计算
3^4
,并将其作为“+”的新左分支,即81

然后访问右分支
1*2

然后访问它的左分支
1

然后访问它的右分支
2

然后访问操作员,
*
, 计算
1*2
,并将其作为“+”的新右分支,即2

然后访问操作员,
+
, 计算
81+2
并返回结果
83

现在中缀符号是为了让人类更容易阅读表达式。为了帮助将中缀符号转换为AST,转换算法需要知道运算符的and。该算法还使用了一个堆栈,该堆栈是调车场算法的主要关键之一。我所知道的每一种将中缀转换为评估策略的方法都以某种方式使用堆栈

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

注意:由于我不知道每种语言的每一个编译器,我只能根据一般概念给你一个答案。没有规则要求遵循这些规则,如果一些编译器跳过AST,从输入代码转到编译代码而不使用AST,我也不会感到惊讶

另外,因为您提到了编译器,所以我只讨论了编译后的代码,没有涉及脚本语言

现在回到你的问题:

今天的现代编译器是否将其用于算术表达式 评估

我不会特别使用调车场算法,而是使用堆栈的概念,这是我将使用的算法的关键概念之一。如果使用算法的概念与使用算法相同,您可以自己选择

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


希望你现在知道这个问题的答案。重要的不是调车场算法,而是使用堆栈转换中缀符号的概念,这是编译器使用的概念。请记住,编译语言通常不只是计算表达式,它们处理类型、处理条件表达式、存储值,并创建更高的类型,如方法/函数、类和模块。

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