使用高级语言,解释器/编译器的工作是在执行之前将数学表达式从中缀表示法转换为后缀或前缀。实际上,是否需要对中缀表达式进行转换才能对它们进行“处理”?我试图了解“幕后”的情况。不过我对堆栈的概念及其与RPN的使用很好。
答案 0 :(得分:2)
(反向与否)波兰表示法不是由计算机内部使用的:它完全适用于人类。它很受欢迎,因为它是一种表示电子计算器相当复杂的算术表达式的方法,当它们不够复杂,无法理解运算符优先级和括号时,就像今天的计算器一样。那些用这些计算器“长大”的工程师习惯于这样思考,所以通用计算机上的第一个计算器程序自然会以同样的方式工作。
当您使用编程语言编写表达式时,解析器(理解语言的解释器或编译器的一部分)将该表达式转换为树,其中树的每个节点都是一个操作,并且每个子节点都是node是表达式的操作数。例如,
f(3 + 4)
可能是“函数调用”节点,其第一个子节点是名称f
,其第二个子节点是“添加”节点。 “add”节点的子节点是“文字”节点(即值),其值为3和4。
这棵树被称为抽象语法树(AST),因为它是一种树,其结构与语言的语法分开(即语法被抽象掉)。在像gcc这样理解几种不同语言的编译器中,每种语言的解析器产生相同类型的AST,原始语言是使用RPN还是数学式中缀符号或仅函数调用无关紧要。
解析器然后将其提供给后端。在解释器中,后端将一次评估每个节点,最有可能从底部开始。也就是说,首先它将值“7”替换为“add”节点及其子节点,然后查找名为f
的函数,然后用函数的结果替换“函数调用节点”及其子节点调用
编译器将树转换为指令序列。在这个例子中,它们可能类似于:
将3载入寄存器0
中
将4加载到寄存器1中 添加寄存器0和1,并将答案放入寄存器0
跳转到f
的代码,该代码期望其在寄存器0中的参数 将结果用在寄存器0
显然,这些说明并不那么冗长:它们是用汇编语言编写的,它通常特定于目标体系结构(您正在编译的计算机类型)。我不会显示整个程序集程序,但add指令可能如下所示:
add r0, r0, r1
编译器的最后一步是汇编程序,然后将汇编程序的每条指令转换为实际CPU理解的数字。
任何一个都没有RPN或操作数堆栈。你听到的关于程序使用的“堆栈”(例如本网站名称中的那个)是一个内存区域(种类)自动增长。程序可以使用它来存储太大而不适合寄存器的东西,或者被函数调用擦除的东西(因为被调用的函数想要使用你正在使用的寄存器)。
有CPU architectures that actually did use a stack,CPU的汇编语言看起来有点像RPN。 PostScript使用的“虚拟机”就是一个示例,Lisp Machines是真正的硬件示例。但是,今天流行的CPU架构都不会以这种方式工作。
答案 1 :(得分:0)
完全取决于特定语言的设计 - 只要确保计算的正确性,无论是使用中缀,后缀还是其他任何方式。