下载后可任意编辑基于编译原理的计算器设计与实现 首先看一下这个计算器的功能:CALC> set a = 1; b = 2CALC> set c = 3CALC> calc (10 + pow(b, c)) * sqrt(4) - 135.0CALC> exit如上所示,这个计算器的功能非常简单:1.用 set 命令设置上下文中的变量。 2.用 calc 命令计算一个表达式的值。 3.用 exit 命令退出计算器。 我们把编译的重点放在 calc 命令后面的计算表达式的解析,其它的部分我们可以简单处理(如 set 命令可以这样简单处理:先按分号分隔得到多个赋值处理,再按等号分隔就可以在上下文中设置变量了,并不需要复杂的编译过程)。如上的演示例子中,我们使用编译技术处理的部分是(10 + pow(b, c)) * sqrt(4) - 1,其它部分我们只使用简单的文本处理。麻雀虽小,但五脏俱全,这个计算器包含编译技术中最必要的部分。虽然这次我们只是实现了一个计算器,但所使用的技术足以实现一个简单的脚本语言的解释器了。这个计算器分为如下几个部分:词法分析:把表达式的文本,解析成词法元素列表(tokenList)。 语法分析:把 tokenList 解析成语法树(syntaxTree)。 语义分析:把语法树转成汇编语言的代码(asm) 汇编器:把汇编代码翻译为机器码(字节码)。 虚拟机:执行字节码。 一般的编译步聚中不包含“汇编器”和“虚拟机”,而这里之所以包含这两个部分是因为:通常编译器会直接由中间代码生成机器码,而不是生成汇编代码,而这里我之所以要生成汇编代码的原因是“调试的时候汇编的可读性很好”,假如直接生成目标代码,则会非常难用肉眼来阅读。 自己实现虚拟机的原因是:现有的机器(包括物理机和虚拟机以及模拟器)的指令虽然也很丰富,但似乎都没有直接计算“乘方”或“开方”的指令,自已实现虚拟机可以任意设计计算指令,这样可以降低整个程序的复杂度。 因汇编器与虚拟机并不是编译原理的部分,所以下文中并不会描述其实现细节,但因为计算器代码编译后的目标代码就是汇编代码,所以需要把汇编指令做一下说明(以下把这个汇编语言简称为 ASM)。下载后可任意编辑ASM 指令介绍指令助记符 操作数 指命说明 storenumber把 number 放入栈顶add从栈顶取出两个数相加,并把结果压回栈中sub从栈顶取出一个数做为被减数,再取一个做为减数,相减之后的结果入栈mul从栈顶取出两个数相乘,并把结果入栈div从栈顶取出一个数做为除法的分子,再取出一个做为除法的分母,相除的结果入...