编译器_编译原理课程设计报告书
编译原理课程设计报告

《编译原理》课程设计报告一、课程设计目的通过课程设计进一步理解高级语言在计算机中的执行过程,了解现代编译器的运作机制,加深对编译原理中重点算法和编译技术的理解,提高自己自学和理解的能力。
学会如何利用已有软件JFLex、Java_cup对词法分析器及语法分析器的构造。
二、设计概述本tiger语言编译器的编译过程涉及到编译五个阶段中的二个,即词法分析器、语法分析器。
其中语法分析后还完成了语法树的打印的构造以及类型检查。
词法分析器由JFLex编译正则式生成,词法分析器编译产生式生成,语法分析器由CUP生成。
结果通过GUI界面呈现在使用者面前。
编译程序需要在单词级别上来分析和翻译源程序,所以首先要识别出单词,而词法分析部分的任务是:从左至右扫描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。
因此,词法分析是编译的基础。
执行词法分析的程序称为词法分析器。
语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。
三、设计过程(一)设计构思程序主要完成三大功能模块:词法分析器、语法分析器、GUI人机交互界面。
词法分析器由JFLex编译正则式生成,其中必须为外界提供一个获取记号流的接口,实验中定为java_cup.runtime.Symbol next_token。
语法分析器是建立在词法分析器上的,故必须包含词法分析器以便获得记号流,next_token为语法分析器提供TOKEN,语法分析器的对外接口是:java_cup.runtime.Symbol debug_parse(),同时返回语法树的根节点。
GUI 界面是提供人机交互的,它能够依次显示词法分析阶段分析得到的所有TOKEN 的信息,语法阶段生成的语法树,另外对于词法和语法阶段出现的错误在“错误提示”文本框中一一列举出来,提供用户改进代码的信息。
编译原理课程设计C-语言编译器

编译原理课程设计报告课题名称: C-语言编译器设计提交文档学生姓名:李杰提交文档学生学号:0743041240同组成员名单:无指导教师姓名:金军N不指导教师评阅意见:..提交报告时间: 2010年 6 月 10日1.课程设计目标实验建立C-编译器。
只含有scanner和parser部分。
2.分析与设计(1)实现方法:编程语言为C语言。
编程方法:scanner部分根据DFA图用switch-case结构实现状态转换;parser部分用递归下降分析方法实现。
(2)扫描器:C-惯用的词法1、语言的关键字:else if int return void while2、专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */3、其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|94、空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
5. 注释用通常的C语言符号/ * . . . * /围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。
注释不能嵌套各单词的状态转换图(DFA图如下)词法结构见文件"globals.h"中。
(3)分析器:分析树结构见文件"globals.h"中。
C-的BNF语法如下:(4)代码设计说明:程序结构:语法分析函数parse通过调用词法分析函数getToken实现语法分析。
文件和函数的设计说明:文件main.c包含相应头文件,及main函数的实现;文件golbals.h 包含符号表和分析数的数据结构及在其它文件中使用的变量;文件util.h 和util.c实现与词法分析和语法分析输出相关的函数printToken和printTree,以及分析树节点初始化相关的函数newStmtNode,newExpNode(Expkind)和copyString;文件scan.h 和scan.c实现词法分析,主要函数为getToken;文件parse.h 和parse.c实现语法分析,函数为与文法规则对应的函数。
编译原理课程设计报告

课程设计报告( 2021--2022年度第一学期)名称:编译技术课程设计题目:算符优先分析法研究院系:班级:学号:学生姓名:指导教师:设计周数:一周成绩:日期:2021年12 月31日1 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2 课程设计的要求1. 文法使用产生式来定义;2. 分别给出每一个非终结符的FIRSTVT和LASTVT集。
3. 画出算符优先关系表;4. 判定给定的文法是否是算符优先文法;5. 给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。
2 系统描述举例如下:本次实验使用Visual Studio 2019软件,利用只规定终结符之间的优先关系的自底向上移进-规约法实现对算符优先分析法的研究,输出非终结符的FIRSTVT和LASTVT集,算符优先关系表和对句子的分析表格,均在DOS窗口显示。
2.1 文法的描述G[S]: S->#E#;E->E+T|T;F-P!F|P;T->T*F|F;P->(E)|i2.2 属性文法的描述表2-1 条件语句及其语义规则3 概要设计3.1 概要设计(体现系统的设计思路和主要功能)主要步骤包括:用户自己输入文法,实质上是算数表达式的计算。
构建每个非终结符的FirstVT()和LastVT()集。
构建优先关系符号表。
构建词法分析的程序。
编写主函数,用户输入文法对语句利用算符优先文法进行判别。
算法的主体思想:用栈存储已经看到的输入符号,用优先关系指导移动归约语法分析器的动作,如果栈顶的终结符和下一个输入符之间的优先关系是<或=,则语法分析器移动,表示还没有发现句柄的右端,如果是>关系,就调用归约。
3.2 开发环境实验采用C++程序语言进行设计开发工具为Visual Studio 20194 详细设计4.1 系统的类图图4-1 文法类图4.2 主要算法的流程图图4-2 求非终结符的FIRSTVT 和LASTVT 集流程图求LASTVT 集的过程与此类似,但符号串的扫描顺序是从后开始若产生式右部第一个字符为非终结符 则直接将其加入first 集中else first[x].insert(str[0]);寻找该非终结符 的first 集 dfs(y);将该非终结符的first 集也加进去for (; it != first[y].end(); it++)first[x].insert(*it);if (isupper(str[0]))若产生式右部第一个字符为非终结符 string& left = VN_set[x].left;string&str = VN_set[x].right[i];产生产生式左部非终结符的FIRSTVT 集图4-3 构造算符优先关系表流程图图4-4 对输入串进行算符优先分析流程图4.3 数据分析与定义char relation[MAX][MAX]; //算符优先关系表vector<char> VT;vector<WF> VN_set; //类型为文法的数组VN_setmap<string, int> VN_dic; //map映射,一条产生式对应的第几条的序号set<char> first[MAX]; //FIRSTVT集set<char> last[MAX]; //LASTVT集4.4 系统界面设计用户输入文法个数和每条产生式的内容后,输出结果格式如下:分为:产生式、FIRSTVT集、;LASTVT集、算符优先关系表和分析过程图4-5 系统输出界面概况5 测试方法和测试结果5.1 测试用例1输入如程序5-1所示。
编译原理课程设计报告

实验要求✧基本内容1)增加单词:保留字ELSE,REPEAT,DOWHILE,RETURN运算符+=,-=,++,--2)修改单词:不等号# 改为<>3)增加条件语句的ELSE子句4)扩充赋值运算:+= 和-=5)扩充语句(Pascal的FOR语句):①FOR <变量>:=<表达式> TO <表达式> DO <语句>②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句>其中,语句①的循环变量的步长为2,语句②的循环变量的步长为-2。
✧选做内容1)增加运算:++ 和--。
2)增加类型:①字符类型;②实数类型。
3)扩充函数:①有返回值和返回语句;②有参数函数。
4)增加一维数组类型(可增加指令)。
5)其他典型语言设施。
设计方案1.概述:源、目标语言:编译程序编绎的源程序是PL0,程序产生的目标代码是一个假想栈式计算机的汇编语言.称为类PCODE指令代码 ,指令格式格式如下:F L A其中F代表功能码,L表示层次差,A表示位移量,不同指令其含义有所区别。
PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
实现工具(平台),运行平台:编译器实现工具和运行平台程序用C++语言编写,在C++ Builder平台下运行。
2.结构设计说明:PL/0的编译过程采用一趟扫描方式,以语法分析为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读入单词时就调用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
编译原理课程设计报告

2011-2012学年第二学期《编译原理》课程设计报告学院:计算机科学与工程学院班级:学生姓名:学号:成绩:指导教师:时间:2012年5 月目录一、课程设计的目的 ---------------------------------------------------------------- - 1 -二、课堂实验及课程设计的内容 -------------------------------------------------- - 1 -2.1、课堂实验内容-------------------------------------------------------------- - 1 -2.2、课程设计内容-------------------------------------------------------------- - 1 -三、visual studio 2008 简介------------------------------------------------------- - 2 -四、问题分析及相关原理介绍 ----------------------------------------------------- - 3 -4.1、实验部分问题分析及相关原理介绍 ---------------------------------- - 3 -4.1.1、词法分析功能介绍及分析------------------------------------- - 3 -4.1.2、语法分析功能介绍及分析------------------------------------- - 3 -4.1.3、语义分析功能介绍及分析------------------------------------- - 4 -4.2、课程设计部分问题分析及相关原理介绍 ---------------------------- - 5 -4.2.1、编译程序介绍 ----------------------------------------------------- - 5 -4.2.2、对所写编译程序的源语言的描述(C语言) -------------- - 6 -4.2.3、各部分的功能介绍及分析 -------------------------------------- - 7 -4.3、关键算法:单词的识别-------------------------------------------------- - 8 -4.3.1、算法思想介绍 ----------------------------------------------------- - 8 -4.3.2、算法功能及分析 -------------------------------------------------- - 8 -五、设计思路及关键问题的解决方法 ------------------------------------------ - 10 -5.1、编译系统------------------------------------------------------------------ - 10 -5.1.1、设计思路 --------------------------------------------------------- - 10 -5.2、词法分析器总控算法--------------------------------------------------- - 12 -5.2.1、设计思路 --------------------------------------------------------- - 12 -5.2.2、关键问题及其解决方法 --------------------------------------- - 13 -六、结果及测试分析-------------------------------------------------------------- - 14 -6.1、软件运行环境及限制--------------------------------------------------- - 14 -6.2、测试数据说明------------------------------------------------------------ - 14 -6.3、运行结果及功能说明--------------------------------------------------- - 16 -6.4、测试及分析说明--------------------------------------------------------- - 16 -七、总结及心得体会 --------------------------------------------------------------- - 17 -7.1、设计过程------------------------------------------------------------------ - 17 -7.2、困难与收获 ------------------------------------------------------------- - 17 -八、参考文献 ------------------------------------------------------------------------ - 18 -一、课程设计的目的通过设计、编写和调试词法分析程序(又称扫描器),了解扫描器的组成结构,不同种类单词的识别方法,加深了对词法分析作用的理解。
编译原理编译器课程设计

编译原理编译器课程设计一、课程目标知识目标:1. 理解编译原理的基本概念,掌握编译器各阶段的工作原理和实现方法;2. 学会使用一种编程语言(如C、Java等)编写简单的编译器程序;3. 掌握词法分析、语法分析、语义分析及目标代码生成的基本技术和策略;4. 了解优化技术在编译器中的应用,提高程序运行效率。
技能目标:1. 能够运用所学知识独立设计并实现一个简单的编译器;2. 培养学生运用编译原理知识解决实际问题的能力;3. 提高学生的编程实践能力和团队协作能力;4. 培养学生查阅资料、分析问题、总结归纳的能力。
情感态度价值观目标:1. 培养学生对编译原理和编译器开发工作的兴趣,激发学生的学习热情;2. 培养学生勇于探索、积极创新的精神,增强克服困难的信心和毅力;3. 培养学生具备良好的编程习惯,遵循职业道德,为我国软件产业的发展贡献自己的力量。
本课程旨在通过编译原理编译器课程设计,使学生掌握编译器的基本原理和技术,提高编程实践能力,培养团队协作精神,激发学生的学习兴趣和创新精神。
课程性质为理论与实践相结合,注重培养学生的实际操作能力。
针对学生的年级特点,课程内容将逐步深入,从基本概念到实际应用,引导学生由浅入深地掌握编译器相关知识。
在教学过程中,教师需关注学生的学习进度,及时调整教学策略,确保课程目标的实现。
通过本课程的学习,学生将具备独立设计和实现简单编译器的能力,为后续相关课程的学习打下坚实基础。
二、教学内容1. 编译原理概述:介绍编译器的基本概念、发展阶段和组成部分,使学生了解编译器在整个软件开发过程中的地位和作用。
教材章节:第一章2. 词法分析:讲解词法分析器的功能、设计方法,以及正则表达式和有限自动机等基本概念。
教材章节:第二章3. 语法分析:介绍语法分析器的作用、设计方法,以及上下文无关文法、LL(1)、LR(1)等分析方法。
教材章节:第三章4. 语义分析:讲解语义分析器的任务、属性文法、语法制导翻译等概念,以及类型检查和符号表管理方法。
扬大课程设计报告-C语言子集编译器

扬州大学编译原理课程设计题目C语言子集编译器班级学号姓名成绩扬州大学信息工程学院一、课程设计目的通过编译原理课程设计,加深对课堂中所讲授的内容的理解,设计一个具有词法分析、语法、语义分析、错误处理的综合程序。
进一步掌握编译程序常用实现的方法和技术,使学生初步具有研究、设计、编制和调试编译程序的能力。
二、课程设计题目实现一个简单的编译器三课程设计要求1.实现一个C语言子集或Pascal语言子集的编译器,工具任选。
2.要求实现的功能:翻译 +,-,*, / 四则运算表达式及布尔表达式,翻译包含if语句,while语句及do-while语句及相互间的嵌套。
四、课程设计语言及选用工具选用语言:Java工具 Eclipse五、课程设计方法1,本课程设计的数据结构设计过程中用到的栈:static Vector<String>DataStack = new Vector<String>(); 输入流栈static Vector<String>targetAnaStack = new Vector<String>(); 输入备份栈static Vector<String>AnalysStack = new Vector<String>(); 分析栈static Vector<String>KeyWordStack = new Vector<String>(); 保留字栈static Vector<String>JiexanStack = new Vector<String>(); 界限符栈static Vector<String>YunsuanfuStack = new Vector<String>(); 运算符栈中间代码的构造:包括标号,符号,第一操作数,第二操作数,和目的操作数class midCode {String sign;String op1;String op2;LoopLastLocation p1;}class LoopLastLocation { //每一个目的操作数都联系着一个对应的跳转标号String LastLocation;Int BiaoHao;}总体构成:跳转标号(操作符,第一操作数,第二操作数,目的操作数或者跳转标号)2,器主要分为四个部分:词法分析、语法分析、中间代码生成和目标代码生成。
编译原理课程设计报告 编译器

《编译技术》课程设计实验报告实验名称:编译器程序说明:下载请好评姓名:向难学号:200812110106班级:计算机系08本一班2010年11月12日目录一、课设要求 (3)二、总体设计思想 (4)三、详细算法设计 (4)四、流程框图 (5)五、函数相关说明 (9)1. 所有函数一览 (9)2. void emit(char *res,char *num1,char *op,char *num2) (9)3. char *newTemp() (10)4. int merge(int p1,int p2) (10)5. void backpatch(int p,int t) (11)6. void fuzhi() (11)7. void tiaojian(int *nChain) (12)8. void xunhuan() (13)六、程序运行结果 (15)七、编译器使用说明 (17)八、心得与体会 (17)九、源程序清单 (18)一、课设要求用C语言对下述文法和单词表定义的语言设计编制一个编译器。
(1)单词符号及种别表(2)语法结构定义<程序> ::= main()<语句块><语句块> ::= ‘{‘<语句串>’}’//程序用括号括起来<语句串>::=<语句>{;<语句>};<语句>::=<赋值语句>|<条件语句>|<循环语句><赋值语句>::=ID=<表达式> //赋值语句用”=”号<条件语句>::=if<条件><语句块> //条件怎么没有括号,囧(自己加1个)<循环语句>::=do <语句块>while <条件><条件>::=<表达式><关系运算符><表达式> //没有布尔运算,还算简单<表达式> ::= <项>{ +<项>|-<项>}<项> ::= <因子>{*<因子>|/<因子>}<因子> ::=ID|num|(<表达式>)num::=( +|-|ε) 数字*(.数字数字* | ε)( e ( +|-|ε) 数字数字*|ε)ID::=字母(字母|d数字)*字母::=a|b|c…|z|A|B|C…|Z数字::=0|1|2…|9<关系运算符> ::= <|<=|>|>=|==|!=二、总体设计思想采用递归下降(自上而下)的语法制导翻译法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
广西大学编译原理课程设计专业:计算机科学与技术姓名:课程:编译原理指导教师:目录一.程序简介与分析---------------------------------------------------------1 二.程序适用围-----------------------------------------------------------1 三.词法分析---------------------------------------------------------------1 四.语法分析---------------------------------------------------------------3 五.语义分析和中间代码生成------------------------------------------------9 六.代码生成--------------------------------------------------------------11 七.流程图----------------------------------------------------------------12 八.实现------------------------------------------------------------------13 九.程序运行结果----------------------------------------------------------13 十.总结------------------------------------------------------------------18 十一.附录(源程序)--------------------------------------------------------19简单的编译程序设计一.程序简介与分析本程序由四个部分组成:词法分析子程序,语法分析子程序,语义分析子程序,目标代码生成程序。
本程序输入一个叫haominjie.txt的c语言源程序,然后对它进行词法,语法,语义分析,并输出汇编代码。
词法分析输入的是c语言源程序,输出的3是具有独立语法意义的单词符号。
语法分析以词法分析产生的编码流为输入,按照SLR(1)分析方法进行语法分析,产生语法树,输出移进和归约的动作,如果源程序不符合文法,则有“语法分析出错”的提示。
语义分析阶段,在语法分析的同时,在归约的时候,给出相应的语义动作,最后输出中间代码四元式和新的符号表,如果有未声明的变量出现,则会提示出出错,并显示出此变量的名称。
代码生成阶段,将语义分析得到的中间代码四元式转化为汇编语言的目标代码并输出。
二.程序适用围本程序的使用围为:整型常量,四则运算(为了简化问题,本程序只考虑加法运算和乘法运算)和布尔表达式以及相应的赋值语句,条件转移语句和循环语句。
三.词法分析根据词法分析的需要,我将源程序中的单词符号分为:保留字,字母(标识符),界符三类,统一用一表表示如下:界符,保留字表程序从源程序文件haominjie.txt中一次读入一个字符,并判断它是不是字母,界符,保留字,空格,换行,结束符号或者非法字符。
流程图如下:词法分析流程图四.语法分析○1.源程序中涉及的文法G[P]定义如下表:○2.上述文法的每个非终结符的FIRST 集和FOLLOW集如下表:FIRST 集 FOLLOW 集P { id } { # }L { id } { ; }D { id } { ; }E {(,id } { },;,+,),#}T {(,id } { },;,+,),*,#}F {(,id } { },;,+,),*,#}B { id } {then,do,and}M { id } { },;}S {id,while,if} { },;}N {id,while,if} { },;}R { { } { # }○3.文法G[P]的项目集部分如下:0. P’→.P 1. P’→P.2. P→.id()L;R3. P→id.()L;R4. P→id(.)L;R5. P→id().L;R6. P→id()L.;R7. P→id()L;.R8. P→id()L;R. 9. L→.L;D10.L→L.;D 11. L→L;.D 12. L→L;D.13.D→.id:int 14. D→id .:int 15. D→id: .int16. D→id:int. 17.E→.E+T 18. E→E.+T19. E→E+.T 20. E→E+T. 21. E→.T22. E→T. 23. T→.T*F 24. T→T.*F25. T→T*.F 26. T→T*F. 27. T→.F28. T→F. 29. F→ (E) 30. F→ (.E)31. F→ (E.) 32. F→ (E). 33. F→.id34. F→id.○4.再由项目集构造文法的DFA活前缀。
为了方便,省去了项目族集的每个状态的项目,直接在状态转换的箭头上标明终结符或非终结符。
对于有规约动作和接受的状态,将其特别标明。
文法G[P]的DFA图如下:*五.语义分析和中间代码生成载语法分析过程中,随着分析的步步进展,根据每个产生式所对应的语义子程序(或语义规则描述的语义动作)进行翻译的办法称作语法制导翻译。
语法制导翻译语法翻译生成的四元式如下:六.代码生成目标代码生成阶段的任务是把中间代码变换成特定机器上的绝对指令代码或可重定位的指令代码或汇编指令代码。
这是编译的最后阶段,它的工作与硬件系统结构和指令含义有关,这个阶段的工作很复杂,涉及到硬件系统功能部件的运用、机器指令的选择、各种数据类型变量的存储空间分配以及寄存器和后缓寄存器的调度等。
本程序生成的目标代码与0x8086微处理器兼容。
下面列举几个简单的四元式与汇编代码的转化列子:○1.(+,A,B,T)→MOV R ,A ;ADD R ,B ;ST R , T○2. ( *, A , B , T ) →MOV R ,A ;MUL R ,B ;ST R , T○3. ( J, _ , _ , L) →JMP L○4. ( J> , A , B , L ) →MOV R , ACMP R , BJB L○5. ( =,A , _ ,T ) →LD R , AST R , T本程序生成的目标代码如下:七.程序流程图编译程序流程图八.实现本程序运行的硬件环境为CPU 2GHZ ,存为4G .软件环境为windows 8.1 系统,Visual C++环境。
九.程序运行结果1.输入源文件路径:2.输出保留字3.输出符号表的容5.输出语法分析的结果(本程序采用自下而上的LR语法分析)6.输出中间代码7.输出目标代码十.总结通过本次实验,对编译程序各阶段有了更深刻更深入的了解,也纠正了自己在某些方面的的错误,丰富了自己关于编译原理方面的知识。
同时也培养了自己热爱思考,勤查资料的习惯。
由于水平本次实验涉及面并不是很全面,我只考虑了c语言的一个子集。
当然本程序的算法在某些地方也还存在一些缺陷。
十一.附录(源程序)本程序输入的c源代码如下:haominjie()a:int;b:int;ccc:int;d:int;{if ccc>b and ccc>a then a=b+a;while ccc>d do a=d;a=(b+ccc)*a+d}本程序的完整源代码如下:#include<cstdio>#include<iostream>#include<cstdlib>#include<fstream>#include<string>#include<cmath>using namespace std;struct token//词法 token结构体{int code;//编码int num;//递增编号token *next;};token *token_head,*token_tail;//token队列struct str//词法 string结构体int num;//编号string word;//字符串容str *next;};str *string_head,*string_tail;//string队列struct ivan//语法产生式结构体{char left;//产生式的左部string right;//产生式的右部int len;//产生式右部的长度};ivan css[20];//语法 20个产生式struct pank//语法 action表结构体{char sr;//移进或归约int state;//转到的状态编号};pank action[46][18];//action表int go_to[46][11];//语法 go_to表struct ike//语法分析栈结构体,双链{ike *pre;int num;//状态int word;//符号编码ike *next;};ike *stack_head,*stack_tail;//分析栈首尾指针struct L//语义四元式的数据结构int k;string op;//操作符string op1;//操作数string op2;//操作数string result;//结果L *next;//语义四元式向后指针L *Ltrue;//回填true链向前指针L *Lfalse;//回填false链向前指针};L *L_four_head,*L_four_tail,*L_true_head,*L_false_head;/*四元式链,true链,false链*/ struct symb//语义输入时符号表{string word;//变量名称int addr;//变量地址symb *next;};symb *symb_head,*symb_tail;//语义符号链表////////////////////////////////词法分析有关函数声明void outdaima() ;void scan();//按字符读取源文件void cifa_main();//词法分析主程序int judge(char ch);//判断输入字符的类型void out1(char ch);//写入token.txtvoid out3(char ch,string word);//写入string.txtvoid input1(token *temp);//插入结点到队列tokenvoid input3(str *temp);//插入结点到队列stringvoid output();//输出三个队列的容void outfile();//输出三个队列的容到相应文件中////////////////////////////////语法分析有关函数声明void yufa_main();//语法分析主程序void yufa_initialize();//初始化语法分析数据结构int yufa_SLR1(int a);//语法分析主体部分int ID1(int a);//给输入字符编号,转化成action表列编号string ID10(int i);//给输入字符反编号int ID2(char ch);//给非终结状态编号,转化成go_to表列编号int ID20(char ch);//给非终结状态编号char ID21(int j);//给非终结状态反编号void add(ike *temp);//给ike分析栈链表增加一个结点void del();//给ike分析栈链表删除一个结点/////////////////////////////////语义分析相关函数的声明void yuyi_main(int m);//语义分析主程序void add_L_four(L *temp);//向四元式链中加一个结点void add_L_true(L *temp);//向true链中加一个结点void add_L_false(L *temp);//向false链中加一个结点void add_symb(symb *temp);//向语义符号表链中加一个结点void output_yuyi();//输出中间代码四元式和最后符号表string newop(int m);//把数字变成字符串string id_numtoname(int num);//把编号转换成相应的变量名int lookup(string m);//变量声明检查/////////////////////////////////全局变量的声明FILE *fp;//文件指针int wordcount;//标志符计数int err;//标志词法分析结果正确或错误int nl;//读取行数int yuyi_linshi;//语义临时变量stringE_name,T_name,F_name,M_name,id_name,id1_name,id2_name,errword;//用于归约时名称传递和未声明变量的输出int id_num,id1_num,id2_num,id_left,id_while,id_then,id_do;//用于记录一些特殊的字符位置信息////////////////////////////////主程序开始int main(){cout<<"************************"<<endl;cout<<"* 说明: *"<<endl;cout<<"* 第一部分:词法分析 *"<<endl;cout<<"* 第二部分:语法分析 *"<<endl;cout<<"* 第三部分:语义分析 *"<<endl;cout<<"* 第四部分:目标代码生成 *"<<endl;cout<<"************************"<<endl;cifa_main();//词法yufa_main();//语法output_yuyi();//语义outdaima(); //代码生成cout<<endl;system("pause");return(0);}//////////////////////////////////词法分析子程序void cifa_main(){token_head=new token;token_head->next=NULL;token_tail=new token;token_tail->next=NULL;string_head=new str;string_head->next=NULL;string_tail=new str;string_tail->next=NULL;//初始化三个队列的首尾指针L_four_head=new L;L_four_head->next=NULL;L_four_tail=new L;L_four_tail->k=0;L_four_tail->next=NULL;L_true_head=new L;L_true_head->Ltrue=NULL;L_false_head=new L;L_false_head->Lfalse=NULL;symb_head=new symb;symb_head->next=NULL;symb_tail=new symb;symb_tail->next=NULL;yuyi_linshi=-1;id_num=0;wordcount=0;//初始化字符计数器err=0;//初始化词法分析错误标志nl=1;//初始化读取行数scan();if(err==0){char m;output();cout<<"词法分析正确完成!"<<endl<<endl<<"如果将结果保存到文件中请输入 y ,否则请输入其它字母:";cin>>m;cout<<endl;if(m=='y'){outfile();cout<<"结果成功保存在token.txt和sting.txt两个文件中,请打开查看"<<endl;cout<<endl;}}}void scan(){cout<<endl;system("pause");cout<<endl;char ch;string word;char document[50];int flag=0;cout<<"请输入源文件路径及名称:";cin>>document;cout<<endl;cout<<"************************"<<endl;cout<<"* 第一部分:词法分析 *"<<endl;cout<<"************************"<<endl;if((fp=fopen(document,"rt"))==NULL){err=1;cout<<"无法找到该文件!"<<endl;return;}while(!feof(fp)){word="";ch=fgetc(fp);flag=judge(ch);if(flag==1)out1(ch);else if(flag==3)out3(ch,word);else if(flag==4 || flag==5 ||flag==6)continue;else{cout<<nl<<"行 "<<"错误:非法字符! "<<ch<<endl;err=1;}}fclose(fp);}int judge(char ch){int flag=0;if(ch=='=' || ch=='+' || ch=='*' || ch=='>' || ch==':' || ch==';' || ch=='{' || ch=='}' || ch=='(' || ch==')')flag=1;//界符else if(('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z'))flag=3;//字母else if(ch==' ')flag=4;//空格else if(feof(fp))flag=5;//结束else if(ch=='\n'){flag=6;//换行nl++;}elseflag=0;//非法字符return(flag);}void out1(char ch){int id;switch(ch){case '=' : id=1;break;case '+' : id=2;break;case '*' : id=3;break;case '>' : id=4;break;case ':' : id=5;break;case ';' : id=6;break;case '{' : id=7;break;case '}' : id=8;break;case '(' : id=9;break;case ')' : id=10;break;//界符编码default : id=0;}token *temp;temp=new token;temp->code=id;temp->num=-1;temp->next=NULL;input1(temp);return;}void out3(char ch,string word){token *temp;temp=new token;temp->code=-1;temp->num=-1;temp->next=NULL;str *temp1;temp1=new str;temp1->num=-1;temp1->word="";temp1->next=NULL;int flag=0;word=word+ch;ch=fgetc(fp);flag=judge(ch);if(flag==1 || flag==4 || flag==5 || flag==6){if(word=="and" || word=="if" || word=="then" || word=="while" || word=="do" || word=="int"){if(word=="and")temp->code=31;else if(word=="if")temp->code=32;else if(word=="then")temp->code=33;else if(word=="while")temp->code=35;else if(word=="do")temp->code=36;else if(word=="int")temp->code=37;//关键字编码input1(temp);if(flag==1)out1(ch);else if(flag==4 || flag==5 || flag==6)return;}else if(flag==1){wordcount++;temp->code=25;temp->num=wordcount;input1(temp);temp1->num=wordcount;temp1->word=word;input3(temp1);out1(ch);}else if(flag==4 || flag==5 || flag==6){wordcount++;temp->code=25;temp->num=wordcount;input1(temp);temp1->num=wordcount;temp1->word=word;input3(temp1);}return;}else if(flag==2 || flag==3)out3(ch,word);//形成字符串else{err=1;cout<<nl<<"行 "<<"错误:非法字符! "<<ch<<endl;return;}}void input1(token *temp){if(token_head->next == NULL){token_head->next=temp;token_tail->next=temp;}else{token_tail->next->next=temp;token_tail->next=temp;}}void input3(str *temp){if(string_head->next == NULL){string_head->next=temp;string_tail->next=temp;}else{string_tail->next->next=temp;string_tail->next=temp;}}void output(){cout<<"token表容如下:"<<endl;token *temp1;temp1=new token;temp1=token_head->next;while(temp1!=NULL){cout<<temp1->code;if(temp1->num == -1){cout<<endl;}else{cout<<" "<<temp1->num<<endl;}temp1=temp1->next;}cout<<"符号表容如下:"<<endl;str *temp3;temp3=new str;temp3=string_head->next;while(temp3!=NULL){cout<<temp3->num<<" "<<temp3->word<<endl;temp3=temp3->next;}}void outfile(){ofstream fout1("token.txt");//写文件ofstream fout3("string.txt");token *temp1;temp1=new token;temp1=token_head->next;while(temp1!=NULL){fout1<<temp1->code;if(temp1->num == -1)fout1<<endl;elsefout1<<" "<<temp1->num<<endl;temp1=temp1->next;}str *temp3;temp3=new str;temp3=string_head->next;while(temp3!=NULL){fout3<<temp3->num<<" "<<temp3->word<<endl;temp3=temp3->next;}}/////////////////////////////////////////语法分析子程序void yufa_main(){if(err==0){system("pause");cout<<endl;cout<<"************************"<<endl;cout<<"* 第二部分:语法分析 *"<<endl;cout<<"************************"<<endl;yufa_initialize();//初始化语法分析数据结构token *temp;temp=new token;temp=token_head->next;int p,q;p=0;q=0;cout<<"语法分析过程如下:"<<endl;while(temp!=NULL){int w;w=ID1(temp->code);p=yufa_SLR1(w);if(p==1) break;if(p==0)temp=temp->next;if(temp==NULL) q=1;}//语法分析if(q==1)while(1){p=yufa_SLR1(17);if(p==3) break;}//最后输入$来完成语法分析}}void yufa_initialize(){stack_head=new ike;stack_tail=new ike;stack_head->pre=NULL;stack_head->next=stack_tail;stack_head->num=0;stack_head->word='!';stack_tail->pre=stack_head;stack_tail->next=NULL;//初始化栈分析链表css[0].left='Q';css[0].right="P";css[1].left='P';css[1].right="id()L;R";css[2].left='L';css[2].right="L;D";css[3].left='L';css[3].right="D";css[4].left='D';css[4].right="id:int";css[5].left='E';css[5].right="E+T";css[6].left='E';css[6].right="T";css[7].left='T';css[7].right="T*F";css[8].left='T';css[8].right="F";css[9].left='F';css[9].right="(E)";css[10].left='F';css[10].right="id";css[11].left='B';css[11].right="B and B";css[12].left='B';css[12].right="id>id";css[13].left='M';css[13].right="id=E";css[14].left='S';css[14].right="if B then M"; css[15].left='S';css[15].right="while B do M"; css[16].left='S';css[16].right="M";css[17].left='N';css[17].right="N;S";css[18].left='N';css[18].right="S";css[19].left='R';css[19].right="{N}";int i,j;for(i=0;i<20;i++){char *css_len;css_len=&css[i].right[0];css[i].len=strlen(css_len);}css[1].len=6;css[4].len=3;css[10].len=1;css[11].len=3;css[12].len=3;css[13].len=3;css[14].len=4;css[15].len=4;//初始化产生式for(i=0;i<46;i++){for(j=0;j<18;j++)action[i][j].sr='#';}//初始化action表for(i=0;i<46;i++){for(j=0;j<11;j++)go_to[i][j]=-1;}//初始化go_to表/****************************以下是给action表和go_to表赋初值************************/action[0][0].sr='s';action[0][0].state=2;action[1][17].sr='';//结束action[2][1].sr='s';action[2][1].state=3;action[3][2].sr='s';action[3][2].state=4;action[4][0].sr='s';action[4][0].state=5;action[5][4].sr='s';action[5][4].state=6;action[6][11].sr='s';action[6][11].state=7;action[7][3].sr='r';action[7][3].state=4; action[8][3].sr='r';action[8][3].state=3; action[9][3].sr='s';action[9][3].state=10; action[10][0].sr='s';action[10][0].state=5; action[10][9].sr='s';action[10][9].state=13; action[11][17].sr='r';action[11][17].state=1; action[12][3].sr='r';action[12][3].state=2; action[13][0].sr='s';action[13][0].state=14; action[13][13].sr='s';action[13][13].state=23; action[13][15].sr='s';action[13][15].state=27; action[14][8].sr='s';action[14][8].state=15; action[15][0].sr='s';action[15][0].state=36; action[15][1].sr='s';action[15][1].state=41; action[16][6].sr='s';action[16][6].state=43; action[16][3].sr='r';action[16][3].state=13; action[16][10].sr='r';action[16][10].state=13; action[17][3].sr='s';action[17][3].state=19; action[17][10].sr='s';action[17][10].state=18; action[18][17].sr='r';action[18][17].state=19; action[19][0].sr='s';action[19][0].state=14; action[19][13].sr='s';action[19][13].state=23; action[19][15].sr='s';action[19][15].state=27; action[20][3].sr='r';action[20][3].state=17; action[20][10].sr='r';action[20][10].state=17; action[21][3].sr='r';action[21][3].state=18; action[21][10].sr='r';action[21][10].state=18; action[22][3].sr='r';action[22][3].state=16; action[22][10].sr='r';action[22][10].state=16; action[23][0].sr='s';action[23][0].state=31;action[24][14].sr='s';action[24][14].state=25; action[25][0].sr='s';action[25][0].state=14; action[26][3].sr='r';action[26][3].state=14; action[26][10].sr='r';action[26][10].state=14; action[27][0].sr='s';action[27][0].state=31; action[28][12].sr='s';action[28][12].state=34; action[28][16].sr='s';action[28][16].state=29; action[29][0].sr='s';action[29][0].state=14; action[30][3].sr='r';action[30][3].state=15; action[30][10].sr='r';action[30][10].state=15; action[31][7].sr='s';action[31][7].state=32; action[32][0].sr='s';action[32][0].state=33; action[33][12].sr='r';action[33][12].state=12; action[33][14].sr='r';action[33][14].state=12; action[33][16].sr='r';action[33][16].state=12; action[34][0].sr='s';action[34][0].state=31; action[35][12].sr='r';action[35][12].state=11; action[35][14].sr='r';action[35][14].state=11; action[35][16].sr='r';action[35][16].state=11; action[36][2].sr='r';action[36][2].state=10; action[36][3].sr='r';action[36][3].state=10; action[36][5].sr='r';action[36][5].state=10; action[36][6].sr='r';action[36][6].state=10; action[36][10].sr='r';action[36][10].state=10; action[37][2].sr='r';action[37][2].state=8; action[37][3].sr='r';action[37][3].state=8; action[37][5].sr='r';action[37][5].state=8; action[37][6].sr='r';action[37][6].state=8;action[38][2].sr='r';action[38][2].state=6; action[38][3].sr='r';action[38][3].state=6; action[38][5].sr='s';action[38][5].state=39; action[38][6].sr='r';action[38][6].state=6; action[38][10].sr='r';action[38][10].state=6; action[39][0].sr='s';action[39][0].state=36; action[39][1].sr='s';action[39][1].state=41; action[40][2].sr='r';action[40][2].state=7; action[40][3].sr='r';action[40][3].state=7; action[40][5].sr='r';action[40][5].state=7; action[40][6].sr='r';action[40][6].state=7; action[40][10].sr='r';action[40][10].state=7; action[41][0].sr='s';action[41][0].state=36; action[41][1].sr='s';action[41][1].state=41; action[42][2].sr='s';action[42][2].state=45; action[42][6].sr='s';action[42][6].state=43; action[43][0].sr='s';action[43][0].state=36; action[43][1].sr='s';action[43][1].state=41; action[44][2].sr='r';action[44][2].state=5; action[44][3].sr='r';action[44][3].state=5; action[44][5].sr='s';action[44][5].state=39; action[44][6].sr='r';action[44][6].state=5; action[44][10].sr='r';action[44][10].state=5; action[45][2].sr='r';action[45][2].state=9; action[45][3].sr='r';action[45][3].state=9; action[45][5].sr='r';action[45][5].state=9; action[45][6].sr='r';action[45][6].state=9; action[45][10].sr='r';action[45][10].state=9;go_to[0][0]=1;go_to[4][1]=8;go_to[4][9]=9;go_to[10][1]=12;go_to[1 0][2]=11;go_to[13][7]=22;go_to[13][8]=21;go_to[13][10]=17;go_to[15][3]=16;go_to[15][4]=38;go_to[15][5]=37;go_to[19][7]=20;g o_to[19][8]=20;go_to[23][6]=24;go_to[25][7]=26;go_to[27][6]=28;go_to[29][7]=30;go_to[34][6]=35;go_to[39][5]=40;go_to[41][3]=42;g o_to[41][4]=38;go_to[41][5]=37;go_to[43][4]=44;go_to[43][5]=37;/****************************action表和go_to表赋初值完毕************************/}int ID1(int i)//按action表,给输入字符编号{int j;j=-1;if(i==25) {j=0;id_num++;}//设置变量名称标志if(i==1) {j=8,id_left=id_num;}//设置产生试左边变量名称标志if(i==2) j=6;if(i==3) j=5;if(i==4) j=7;if(i==5) j=4;if(i==6) j=3;if(i==7) j=9;if(i==8) j=10;if(i==9) j=1;if(i==10) j=2;if(i==31) j=12;if(i==32) j=13;if(i==33) {j=14;id_then=L_four_tail->k+1;}//设置if语句中then位置标志if(i==35) {j=15;id_while=L_four_tail->k+1;}//设置while语句中while 位置标志if(i==36) {j=16;id_do=L_four_tail->k+1;}//设置while语句中do位置标志if(i==37) j=11;return(j);}string ID10(int i)//反编号输入字符{string ch;if(i==0) ch="id";if(i==1) ch="(";if(i==2) ch=")";if(i==3) ch=";";if(i==4) ch=":";if(i==5) ch="*";if(i==6) ch="+";if(i==7) ch=">";if(i==8) ch="=";if(i==9) ch="{";if(i==10) ch="}";if(i==11) ch="int";if(i==12) ch="and";if(i==13) ch="if";if(i==14) ch="then";if(i==15) ch="while";if(i==16) ch="do";if(i==17) ch="$";return(ch);}int ID2(char ch)//按go_to表给非终结符编号{int j;j=-1;if(ch=='P') j=0;if(ch=='D') j=1;if(ch=='R') j=2;if(ch=='E') j=3;if(ch=='T') j=4;if(ch=='F') j=5;if(ch=='B') j=6;if(ch=='M') j=7;if(ch=='S') j=8;if(ch=='L') j=9;if(ch=='N') j=10;return(j);}int ID20(char ch)//给非终结符编号{int j;j=-1;if(ch=='P') j=100;if(ch=='D') j=101;if(ch=='R') j=102;if(ch=='E') j=103;if(ch=='T') j=104;if(ch=='F') j=105;if(ch=='B') j=106;if(ch=='M') j=107;if(ch=='S') j=108;if(ch=='L') j=109;if(ch=='N') j=1010;return(j);}char ID21(int j)//反编号非终结符{char ch;if(j==100 || j==0) ch='P';if(j==101 || j==1) ch='D';if(j==102 || j==2) ch='R';if(j==103 || j==3) ch='E';if(j==104 || j==4) ch='T';if(j==105 || j==5) ch='F';if(j==106 || j==6) ch='B';if(j==107 || j==7) ch='M';if(j==108 || j==8) ch='S';if(j==109 || j==9) ch='L';if(j==1010 || j==10) ch='N';return(ch);}void add(ike *temp)//加一个结点{if(stack_head->next==stack_tail) {temp->pre=stack_head;temp->next=stack_tail;stack_head->next=temp;stack_tail->pre=temp;}else{temp->pre=stack_tail->pre;temp->next=stack_tail;stack_tail->pre->next=temp;stack_tail->pre=temp;}}void del()//删除一个结点{stack_tail->pre->pre->next=stack_tail;stack_tail->pre=stack_tail->pre->pre;}int yufa_SLR1(int w){/*cout<<"当前输入符号:"<<ID10(w)<<" ";*/int i,flag=0,state_temp;//flag错误标志,0正常移进,1错误,2归约,3结束char sr_temp;sr_temp=action[stack_tail->pre->num][w].sr;//动作state_temp=action[stack_tail->pre->num][w].state;//状态变化if(sr_temp=='#')//错误动作{flag=1;err=3;cout<<"语法分析出错!"<<endl;}else if(sr_temp=='s')//移进动作{ike *temp;temp=new ike;temp->next=NULL;temp->pre=NULL;temp->word=w;temp->num=state_temp;add(temp);cout/*<<"动作(移进):"*/<<sr_temp<<state_temp<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID10(stack_tail->pre->word)*/<<endl;flag=0;}else if(sr_temp=='r')//归约动作{int p=ID2(css[state_temp].left);int q=css[state_temp].len;for(i=0;i<q;i++)del();ike *temp;temp=new ike;temp->next=NULL;temp->pre=NULL;temp->word=ID20(css[state_temp].left);temp->num=go_to[stack_tail->pre->num][p];//查go_to表add(temp);cout/*<<"动作(归约):"*/<<sr_temp<<state_temp<<" "<<css[state_temp].left<<"→"<<css[state_temp].right<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID21(stack_tail->pre->word)*/<<endl;flag=2;yuyi_main(state_temp);//在产生树的同时进行语义分析}else if(sr_temp=='')//结束动作{cout<<"END"/*<<"动作(归约):"<<sr_temp<<state_temp*/<<" "<<css[state_temp].left<<"→"<<css[state_temp].right<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID21(stack_tail->pre->word)*/<<endl;flag=3;cout<<"语法分析正确完成!"<<endl;}else//其他意外情况{flag=1;err=3;cout<<"语法分析出错!"<<endl;}return(flag);}/////////////////////////////////////////语义分析子程序void yuyi_main(int m){L *temp;int k;k=1;temp=new L;temp->op=" ";temp->op1=" ";temp->op2=" ";temp->result="";temp->next=NULL;temp->Ltrue=NULL;temp->Lfalse=NULL;if(m==4)//变量声明时加入符号表链{symb *Stemp;Stemp=new symb;id_name=id_numtoname(id_num);Stemp->word=id_name;Stemp->next=NULL;add_symb(Stemp);}if(m==5)//归约E→E+T{temp->op="+";temp->op1=E_name;temp->op2=T_name;yuyi_linshi++;//申请临时变量E_name="t"+newop(yuyi_linshi);temp->result=E_name;add_L_four(temp);//加一个四元式结点}if(m==6)//归约E→T。