基于编译原理的计算器设计和实现.doc
《基于编译原理的计算器设计和实现.doc》由会员分享,可在线阅读,更多相关《基于编译原理的计算器设计和实现.doc(18页珍藏版)》请在咨信网上搜索。
1、基于编译原理计算器设计与实现 一方面看一下这个计算器功能: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命令可以这样简朴解决:先按分号分隔得到各种赋值解决,再按等号分隔就可以在上下文中设立变量了,并不需要复杂编译过程)。如上演示例子中,咱们使用编
2、译技术解决某些是(10 + pow(b,c) * sqrt(4) - 1,其他某些咱们只使用简朴文本解决。麻雀虽小,但五脏俱全,这个计算器包括编译技术中最必要某些。虽然这次咱们只是实现了一种计算器,但所使用技术足以实现一种简朴脚本语言解释器了。这个计算器分为如下几种某些:词法分析:把表达式文本,解析成词法元素列表(tokenList)。 语法分析:把tokenList解析成语法树(syntaxTree)。 语义分析:把语法树转成汇编语言代码(asm) 汇编器:把汇编代码翻译为机器码(字节码)。 虚拟机:执行字节码。 普通编译步聚中不包括“汇编器”和“虚拟机”,而这里之因此包括这两个某些是由于:
3、普通编译器会直接由中间代码生成机器码,而不是生成汇编代码,而这里我之因此要生成汇编代码因素是“调试时候汇编可读性较好”,如果直接生成目的代码,则会非常难用肉眼来阅读。 自己实现虚拟机因素是:既有机器(涉及物理机和虚拟机以及模仿器)指令虽然也很丰富,但似乎都没有直接计算“乘方”或“开方”指令,自已实现虚拟机可以任意设计计算指令,这样可以减少整个程序复杂度。 因汇编器与虚拟机并不是编译原理某些,所如下文中并不会描述其实现细节,但由于计算器代码编译后目的代码就是汇编代码,因此需要把汇编指令做一下阐明(如下把这个汇编语言简称为ASM)。ASM指令简介指令助记符 操作数 指命阐明 storenumber
4、把number放入栈顶add从栈顶取出两个数相加,并把成果压回栈中sub从栈顶取出一种数做为被减数,再取一种做为减数,相减之后成果入栈mul从栈顶取出两个数相乘,并把成果入栈div从栈顶取出一种数做为除法分子,再取出一种做为除法分母,相除成果入栈pow从栈顶取出一种数做为底,再取出一种做为幂,计算成果入栈sqrt从栈顶取出一种数,把这个数开平方后成果入栈print在控制台打印栈顶数字这个虚拟机是基于栈来设计,所有计算指令操作数都从栈中取,store命令向栈顶添加数据。print指令用于打印当前栈顶数据,在咱们编译汇编代码要做到:对的计算出成果,且计算完毕之后成果要刚好在栈顶,这样最后调用一种p
5、rint指令即可以控制台看到计算成果。ASM举例:例1,如果咱们要计算1-2*3,则咱们写出汇编代码如下(行号是为下文解释代码以便而放上去,不是代码一某些):点击(此处)折叠或打开 store 3store 2mulstore 1sub print 对这段代码阐明如下:前两行向栈顶添加两个数字,先压入3再压入2,这样栈顶数字是2,第二个数字是3。 第三行mul会从栈顶弹出两个数字(2和3)计算乘法,并把成果(6)再压入栈中,此时栈中只有一种数字6。 第四行向栈顶压入一种数字1,此时栈顶为1,第二个数字是6。 第五行sub指令从栈顶取出两个数字,第一种数字1做为被减数,第二个数字6做为减数,即计
6、算1-6,并把成果压入栈中,此时栈中只有一种数字-5。 最后一行print指令不对栈做写操作,只读取栈顶数字,并打印出来。 在这里,咱们用到两个运算,mul和sub,这两个运算都是二元运算,因我在设计指令时候,先取出来数字是第一种操作数,因此先压入应当是第二个操作数,这也是为什么代码中先压入是3,之后是2,最后才是1。 例2,如果咱们要计算(10 + pow(2,3) * sqrt(4) - 1,则咱们写出汇编代码如下(行号是为下文解释代码以便而放上去,不是代码一某些):点击(此处)折叠或打开 store 1store 4sqrtstore 3store 2powstore 10addmuls
7、ubprint 对这段代码阐明如下:这段代码稍有点复杂,但有前一段代码经验,咱们可以看到,所有操作数先后顺序是从右向左store,因此store指令顺序是固定下来,剩余核心是操作指令应当放在哪里。 操作指令也是有一种规律,即:当前栈顶数据刚刚好满足某运算时,则操作指令就放在哪里,如: store 1时候没有任何操作操作数都在栈中。 store 4时候,刚刚好sqrt操作数都在栈中,则此时加入sqrt指令。 store 3 store 2时,刚刚好可以计算pow。 store 10之后,就可以计算加法了,因此此时加入add指令。 add计算完毕之后,再加上之前已计算完sqrt指令,则此时乘法所有
8、操作数都在栈中了,则此时加入mul指令。 最后减操作也可以计算了,则加上sub指令。 所有计算完毕之后打印出成果。 在这个例子中,我所说“规律”其实就是“后缀表达式”。咱们寻常写算术表达式是“中缀”,即符号在操作数中间,如1 + 2, + 在1和2中间,转为后缀形式即为1 2 +这里由于我对于参数顺序设计是与“正常”顺序相反,因此1 + 2对于这个汇编器来说,其后缀形式就应当为2 1 +人们是可以按照这个规律,相对简朴实现这个计算器只要做好词法分析就可以按照后缀表达式规律直接由tokenList生成汇编代码了但咱们目是用这个计算器例子来讲编译,因此还是按步就班来讲。词法分析词法分析目是把一段文
9、本分解成词法元素列表,例如(10 + pow(2,3) * sqrt(4) - 1,做词法分析之后会分解成如下几种词法元素: (10+pow(2,3)*sqrt(4)-1这里只是做了一次文本解决在解决之前,咱们手里有东西就是一串字符构成字符串,在解决之后,咱们按照一定“规则”分解为各种单词。算法是各种各样,有创造力程序员会想出各种办法来解决这个单词分解问题。在编译原理中,普遍方式是用如下一种状态转换图来实现在图中,“椭圆形”是状态,状态与状态之间有一条有方向线,这个线代表从一种状态到另一种状态途径,在这条线上面有一种花括号代表从前一种状态到达 后一种状态输入(为以便表达,0-9表达从0到9十个
10、数字,a-z表达从a到z二十六个字母等),如从START状态开始,输入一种数字1,就会到达 INT状态。图中蓝色状态是终结状态,如果从START状态通过若干输入后到达终结状态,则这些输入字符可合并为词法合法单词这里需要额外阐明一点:在对输入进行匹配状态时采用贪婪方式,即:尽量输入更多字符。在辨认到一种合法词法单元之后,状态回到START继续辨认下一种元素,直到没有新元素为止。这个状态转换图在编译原理中有一种专有名词称呼它“拟定有限状态自动机”,英文简称DFA。这里“拟定”意思是每一种状态通过一种输入字符可以拟定只有 一条途径到达另一种状态,“有限”意思是,状态个数是有限。对于一种复杂语言状态数
11、量是这个状态机几种数量级大小。但咱们当前计算器只需要 这几种状态就够了。普通DFA会由工具读取正则办法描述而生成,而不是直接手工构造,但对咱们当前设计计算器来说,其DFA非常小,手工构造是很以便,因此就不用工具了。此外,如果使用工具话,我这篇文章也不会使用既有工具,而是自己实现一种工具。下面举个例子:咱们有一种表达式12.3 + abc,下面我来描述一下DFA运营过程:定义一种变量s,来表达当前状态机所在状态(初始时s = START)。 输入第一种字符1,此时START状态可接受这个输入1,到达INT状态,则变量s赋值为INT状态,此时可看到INT状态颜色是蓝色表达当前可辨以为一种合法词法元
12、素,但由于咱们规则是贪婪匹配,因此咱们还要看看与否还可以匹配更多字符。 输入第二个字符2,此时INT状态也可以接受这人输入,并到达INT状态(转了一种圈又回到本来状态),此时变量s赋值为INT状态。 再输入第三个字符 . ,此时INT状态可接受 . 到达NUMBER状态,此时变量s赋值为NUMBER状态。 此时咱们再向前看一种字符 + ,此时状态NUMBER无法接受这个字符了,同步咱们可在看到NUMBER状态颜色是蓝色,表达当前状态可辨认一种合法词法元素,即:从 START开始到当前咱们一共经历输入为12.3,则这个单词做为第一种合法词法元素。 第一种词法元素辨认成功之后,变量s要回到STAR
13、T状态,并继续输入 + ,此时从START状态可到达ADD状态,且ADD状态并不容许接受任何输入,同步ADD状态颜色也是蓝色,则咱们又辨认出第二个词法元素 + 。 在辨认到第二个词法元素之后,变更s要回到START状态,并继续输入a,此时START状态可由a指向途径到达ID状态,此时s赋值为新状态ID。 当前状况与辨认NUMBER状况类似,当前状态也是终结状态,但按贪婪匹配原则还要继续看看与否可以匹配到新输入。 背面b和c都在ID一种状态里转圈,我就不在赘述了,这样咱们就辨认到了最后一种词法元素abc了。 用如上过程办法可以辨认任何对的算术表达式,但尚有几点需要特别阐明: 如何辨认错误:当前我
14、见过语言规范都在描述如何对的编译一种语言,但没有一种规范有描述如何报错,因此咱们当前能做是只要按正常走法走不通了,那就是错了,就要报错,并尽量提供详细错误信息。 对空白辨认:我在DFA中并没有画辨认空白某些,因素是对于计算器程序来说,空白完全没有用处,因此我只是在代码中直接忽视这个输入,以免状态机无法 辨认空白,同步在辨认到词法元素之后,去掉单词先后空白。对于某些语言来说,空白是故意义,需要做为词法元素辨认出来,不能忽视掉。 对于词法元素表达:普通咱们会用一种类型Token来表达一种词法元素,Token中有两个属性,一种用于表达这个Token类型,另一种用于表达内 容,只有数字与标记符才需要使
15、用Token类型内容属性,其他类型由于同一类型只有一种表达也许,因此就不需要再把内容保存下来了(如ADD内容 一定是+)。 关于标记符:DFA中ID状态用于辨认标记符,这里标记符涉及自定义变量,也涉及函数名。在DFA设计过程中,咱们可以选取把普通标记符与保存字 做为不同状态,也可以用使用同一种状态。咱们当前设计就使用了一种ID状态表达所有标记符,而在辨认到一种ID之后,咱们在看与否是一种保存字,这 样在返回Token对象时设立不同类型。 对于INT和NUMBER:这个计算器所有计算都使用是double类型数字,所在虽然咱们词法可以辨认到INT,但咱们定义Token类型 时,就只定义一种NUMB
16、ER类型,INT或NUMBER状态拟定单词都返回NUMBER这个类型Token对象。 前面逻辑中有一种贪婪批配原则,这个原则在某些语言词法中会有某些特例不合用,例如在C+和JAVA中均有一种运算符“”,这个运算符代表右移,但在C+11 原则中可以写出这样代码std:vectorstd:vector,在JDK5及以上版本也可以这样写 ListList,这里如果按贪婪批配就错了。因此必要在词法分析中加入上下文判断才干决定是按两 个来辨认还是按一种来辨认上下文判断是语法分析某些了,但对于复杂词法构造在没有一种统一词法解析算法可以解决情 况下就得借助更高档办法了。 当前剩余就是写代码了。 如果我把代码
17、贴在这里就太长了,不太适当。所如下面我只描述一下描述DFA思路: 思路一:直接静态代码来描述,类似这样方式把状态机每个途径都描述出来:IF S = START AND c = 1 THEN S = INT . ELSIF .,这样就可以输入运营了。 思路二:表格驱动式,例如列出下面表格即可懂得哪个状态通过哪个输入之后到达哪个新状态了下表左标题是当前状态,上标题是在当前状态上输入,表格中内容是通过途径到达状态。 思路三:结合前两个思路先写一种代码生成工具,工具读取“思路二”中表格中内容,并生成“思路一”中静态代码。0-9 . _a-zA-Z + - * / ( ) ,START INT POIN
18、T ID ADD SUB MUL DIV LBT RBT COMMA INT INT NUMBER POINT NUMBER NUMBER NUMBER ID ID ID ADD SUB MUL DIV LBT RBT COMMA 下面举一下DFA返回Token对象类型:NUM,FUN,VAR,ADD,SUB,MUL,DIV,LBT,RBT,COMMA这里前三个与DFA状态名不同:NUM代表INT状态和NUMBER状态两个状态辨认出词法元素。 FUN和VAR都是ID状态辨认出元素,如果这个ID是一种函数名,则Token为FUN类型,否则即为VAR类型。 其他类型与DFA状态是一一相应。 最后说
19、一下DFA接口:假设DFA有一种办法叫做parse,则这个办法参数只有一种字符串用于传入表达式即可。如果咱们写DFA是用于解析长文本(而不但仅是解析这个简短算术表达式),则可以考虑参数为输入流。 parse办法返回可以考虑返回一种Token游标,游标供语法分析程序调用;也可以考虑解析完所有词法元素返回一种Token列表。由于当前比较通用语法分析算法只需要向前看一种Token对象,因此游标就足够了。 由于语法分析程序有也许会把已读出来Token放回去,下次再用,因此游 标可考虑加一种putBack办法也可以考虑不实现这个办法,而由语法分析程序自己缓存当前用不到词法元素如果DFA返回是list就简
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 编译 原理 计算器 设计 实现
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【w****g】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【w****g】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。