编译原理实验报告-合肥工业大学版
编译原理实验报告

编译原理实验报告一、实验目的和要求本次实验旨在对PL_0语言进行功能扩充,添加新的语法特性,进一步提高编译器的功能和实用性。
具体要求如下:1.扩展PL_0语言的语法规则,添加新的语法特性;2.实现对新语法的词法分析和语法分析功能;3.对扩展语法规则进行语义分析,并生成中间代码;4.验证扩展功能的正确性。
二、实验内容1.扩展语法规则本次实验选择扩展PL_0语言的语句部分,添加新的控制语句,switch语句。
其语法规则如下:<switch_stmt> -> SWITCH <expression> CASE <case_list><default_stmt> ENDSWITCH<case_list> -> <case_stmt> , <case_stmt> <case_list><case_stmt> -> CASE <constant> : <statement><default_stmt> -> DEFAULT : <statement> ,ε2.词法分析和语法分析根据扩展的语法规则,需要对新的关键字和符号进行词法分析,识别出符号类型和记号类型。
然后进行语法分析,建立语法树。
3.语义分析在语义分析阶段,首先对switch语句的表达式进行求值,判断其类型是否为整型。
然后对case语句和default语句中的常量进行求值,判断是否与表达式的值相等。
最后将语句部分生成中间代码。
4.中间代码生成根据语法树和语义分析的结果,生成对应的中间代码。
例如,生成switch语句的跳转表,根据表达式的值选择相应的跳转目标。
5.验证功能的正确性设计一些测试用例,验证新语法的正确性和扩展功能的实用性。
三、实验步骤与结果1.扩展语法规则,更新PL_0语法分析器的词法规则和语法规则。
编译原理实验报告

编译原理实验报告实验⼀词法分析⼀、实验⽬的设计、编制并调试⼀个词法分析程序,加深对词法分析原理的理解。
⼆、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是⼩写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空⽩、制表符和换⾏符组成。
空格⼀般⽤来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码单词符号种别码单词符号种别码bgin 1 :17If 2 := 18Then 3 < 20wile 4 <> 21do 5 <= 22end 6 > 23lettet(letter|digit)* 10 >= 24 dight dight* 11 = 25 + 13 ;26—14 ( 27* 15 ) 28/ 16 # 02.3 词法分析程序的功能:输⼊:所给⽂法的源程序字符串。
输出:⼆元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词⾃⾝字符串;(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表⽰的源程序中识别出具有独⽴意义的单词符号,其基本思想是根据扫描到单词符号的第⼀个字符的种类,拼出相应的单词符号。
3.1 主程序⽰意图:主程序⽰意图如图3-1所⽰。
其中初始包括以下两个⽅⾯:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在⼀张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
合肥工业大学编译原理实验

宣城校区实验报告课程名称编译原理专业班级计算机0001班学生姓名及学号赵保飞 2015216768 指导教师李芒宏实验地点计算机中心楼第四机房2017 ~2018 学年第一学期《编译原理》课程实验报告实验名称词法分析设计姓名赵保飞系院专业计算机科学与技术班级计算机01班学号2015216768实验日期2017.10.18 指导教师李芒宏成绩一、实验目的和要求通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验原理(1)实验数据结构说明K[]String数组-关键字表;s[]char数组—分界符;m[]char数组—算术运算符;r[]String数组—关系运算符;ArrayList型String数组ci—常数;ArrayList型String数组id—标识符(2)实验算法描述(3)算法流程图三、源程序代码和测试结果package lexicalAnalysis;import java.util.*;import java.io.*;public class lexicalAnalysis{static Stringk[]={"for","main","if","while","void","public","static","printf","scanf","asm","do","return","typedef","auto","double","break", "short","using","default","long"};//关键字static char s[]={',',';','(',')','[',']','{','}'};//2分界符static char m[]={'+','-','*','/'};//3算术运算符static String r[]={"<","<=","=",">",">=","<>"};//4关系运算符ArrayList<String>ci=new ArrayList<String>();//5常数ArrayList<String>id=new ArrayList<String>();//6标识符String tempToken="";//临时存放组成一个“词”单位串int pint,row=1,line=1;//当前指针指示,行数,列数char ch;//存放最新读入源程序字符String instring;//存放输入de源程序代码public static void main(String[]args)throws Exception{// TODO Auto-generated method stublexicalAnalysis one=new lexicalAnalysis();System.out.println("单词"+"\t二元序列"+"\t类型"+"\t位置(行,列)");one.readtext();}boolean isdigit(char c){//判断所读字符是否为数字,是则返回ture,否则返回falseif(c>=48&&c<=57)return true;elsereturn false;}boolean isletter(char c){//判断所读字符是否为字母,是则返回true,否则返回falseif((c>64&&c<91)||(c>96&&c<123))return true;elsereturn false;}boolean isline(char c){//判断字符c是否是下划线"_"if(c=='_')return true;elsereturn false;}boolean remove(){//用于在判断关系运算符时,判断是否是要再读一个字符char b=instring.charAt(pint+1);//string类charAt() 方法用于返回指定索引处的字符。
编译原理实验报告

编译原理实验报告班级姓名:学号:自我评定:实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。
例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。
输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。
输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。
例如,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。
对于变量和常数,CLASS字段为相应的类别码;VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。
对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。
另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。
三、实现方法与环境词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。
其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。
一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵同控制程序便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。
构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。
编译原理实验报告

编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。
词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。
二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要课程,旨在让学生了解编译器的基本工作原理以及相关技术。
本次实验旨在通过设计和实现一个简单的编译器,来进一步加深对编译原理的理解,并掌握实际应用的能力。
二、实验环境本次实验使用了Java编程语言及相关工具。
在开始实验前,我们需要安装Java JDK并配置好运行环境。
三、实验内容及步骤1. 词法分析词法分析是编译器的第一步,它将源代码分割成一系列词法单元。
我们首先实现一个词法分析器,它能够将输入的源代码按照语法规则进行切割,并识别出关键字、标识符、数字、运算符等。
2. 语法分析语法分析是编译器的第二步,它将词法分析得到的词法单元序列转化为语法树。
我们使用自顶向下的LL(1)语法分析算法,根据文法规则递归地构建语法树。
3. 语义分析语义分析是编译器的第三步,它对语法树进行检查和转换。
我们主要进行类型检查、语法错误检查等。
如果源代码存在语义错误,编译器应该能够提供相应的错误提示。
4. 代码生成代码生成是编译器的最后一步,它将经过词法分析、语法分析和语义分析的源代码翻译为目标代码。
在本次实验中,我们将目标代码生成为Java字节码。
5. 测试与优化完成以上步骤后,我们需要对编译器进行测试,并进行优化。
通过多个测试用例的执行,我们可以验证编译器的正确性和性能。
四、实验心得通过完成这个编译器的实验,我收获了很多。
首先,我对编译原理的知识有了更深入的理解。
在实验过程中,我深入学习了词法分析、语法分析、语义分析和代码生成等关键技术,对编译器的工作原理有了更系统的了解。
其次,我提高了编程能力。
实现一个完整的编译器需要处理复杂的数据结构和算法,这对我的编程能力是一个很好的挑战。
通过实验,我学会了合理地组织代码,优化算法,并注意到细节对程序性能的影响。
最后,我锻炼了解决问题的能力。
在实验过程中,我遇到了很多困难和挑战,但我不断地调试和改进代码,最终成功地实现了编译器。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告合肥工业大学计算机科学与技术完成日期:2013.6.3实验一词法分析设计一、实验功能:对输入的txt文件内的内容进行词法分析:由文件流输入test.txt中的内容,对文件中的各类字符进行词法分析打印出分析后的结果;二、程序结构描述:(源代码见附录)1、利用Key[]进行构造并存储关键字表;利用optr[]进行构造并存储运算符表;利用separator[]进行构造并存储分界符表;2、bool IsKey(string ss) {}判断是否是关键字函数若是关键字返回true,否则返回false;bool IsLetter(char c) {}判断当前字符是否字母,若是返回true,否则返回false;bool IsDigit(char c) {}判断当前字符是否是数字,若是返回true,否则返回false;bool IsOptr(string ss) {}判断当前字符是否是运算符,若是返回true,否则返回false;bool IsSeparator(string ss) {}判断当前字符是否是分界符,若是返回true,否则返回false;void analyse(ifstream &in) {}分析函数构造;关系运算符通过switch来进行判断;三、实验结果实验总结:词法分析的程序是自己亲手做的,在实现各个函数时花了不少功夫,1、要考虑到什么时候该退一字符,否则将会导致字符漏读甚至造成字符重复读取。
2、在实现行数和列数打印时要考虑到row++和line++应该放在什么位置上才可以,如当读取一个\n时line要增加一,而row需要归0处理,在读取某一字符串或字符后row需要加一;3、对于关系运算符用switch结构进行选择判断即可解决一个字符和两个字符的运算符之间的差异;4、将自己学过的知识应用到实践中是件不怎么容易的事情,只有亲身尝试将知识转化成程序才能避免眼高手低,对于知识的理解也必将更加深刻。
实验二LL(1)分析法一、实验原理:1、写出LL(1)分析法的思想:当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。
实现LL(1)分析的一种有效的方法是使用一张分析表和一个站进行联合控制。
预测分析表是一个M[A,a]形式的矩阵,存储着分析规则;栈STACK用于存放文法符号。
从栈顶取符号,按照分析表给出的规则进行有步骤的分析。
2.实验要求实现的文法:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i二、程序结构:各个模块:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
程序各个部分的实现:(1)Vn[]存储非终结符数组;Vt[]存储终结符数组;char strToken[Length];//存储规约表达式struct LL//ll(1){char *c}分析表的构造字初始化Class stack实现栈的要求功能:初始化,判断空满,入栈出栈等;Run()函数实现LL(1)文法分析的函数:先将表达式字符入栈,#最先入栈底,依次取栈顶符号,查和符号栈和分析表,进行相应的操作。
三、实验结果:测试方法:运行程序,输入需要分析的语句测试结果如下:四、实验总结:1、出现下列两种情况说明遇到了语法错误:(1)栈顶的终结符与当前的输入符号不匹配。
(2)非终结符A处于栈顶,面临输入符号为a,但分析表M中M[A,a]为空。
发现错误后要尽快的从错误中恢复过来使分析能继续进行下去。
2、对于符号的入栈出栈,哪个应该先入栈,栈顶是哪个元素需要搞清楚,不然得到的结果肯定不对。
实验三LR(1)分析法一实验原理LR(1)分析法实验设计思想及算法(1)总控程序,也可以称为驱动程序。
对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
分析器的动作就是由栈顶状态和当前输入符号所决定。
二、程序结构◆LR分析器由三个部分组成:◆其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。
状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。
◆ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。
动作有四种可能:(1)移进:action[i,a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。
(2)归约:action[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A- B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。
(3)接受acc:当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。
(4)报错:当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。
三、实验结果:程序测试:输入需要规约的字符串测试结果:四、实验总结1、与算符优先分析方法比较,用LR分析时,设计特定出错处理子程序比较容易,因为不会发生不正确的归约。
在分析表的每一个空项内,可以填入一个指示器,指向特定的出错处理子程序,第一类错误的处理一般采用插入、删除或修改的办法,但要注意,不能从栈内移去任何那种状态,它代表已成功地分析了程序中的某一部分。
2、LR分析法的归约过程是规范推导的逆过程,所以LR分析过程是一种规范归约过程。
LR 分析法正是给出一种能根据当前分析栈中的符号串(通常以状态表示)和向右顺序查看输入串的K个(K≥0)符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约,因而也就能唯一地确定句柄。
其中LR(0)分析器是在分析过程中不需向右查看输入符号,因而它对文法的限制较大,然而,它是构造其它LR类分析器的基础。
因此,首先应学好LR(0)项目集规范族构造的基本原理和方法。
当K=1时,已能满足当前绝大多数高级语言编译程序实现的需要。
SLR(1)分析是为学习LR(1)分析做准备,LR(1)项目集族的构造是LALR(1)分析器的构造原理和基础。
LALR(1) 分析器是当前大多数高级程序设计语言编译程序所采用的语法分析技术,也是编译程序语法分析器自动构造工具YACC的实现基本原理。
由此,LR(0)、SLR(1)、LALR(1)、LR(1)四种分析器的构造方法都必须深入理解和掌握。
3、经过以上三个实验的锤炼,不得不说自己编译原理这门课的认识又提高了一个阶层,对编译原理的知识运用更加深入,编写过程中遇到不少的问题,结合课本及强大的网络资源,在完成的过程中得到很多收获,不仅来自于对知识点的了解更加深入,更是对自己编程能力的一次很好的锻炼,希望有更多这样实验的机会。
4、本人很希望在完成实验后,老师可以根据自己讲的课本,将自己所写的程序花一段时间来讲解,我想这样会对不会编写的是一种教学,对会了的同学是一种榜样效应,可以让我们有个目标追求,这样我们收获了的也会更加准确与丰富。
附录:实验一源代码:#include<iostream>#include<fstream>#include<string>using namespace std;string key[8]={"do","end","for","if","printf","scanf","then","while"}; string optr[4]={"+","-","*","/"};string separator[6]={",",";","{","}","(",")"};char ch;//判断是否为保留字bool IsKey(string ss) {int i;for(i=0;i<8;i++)if(!strcmp(key[i].c_str(),ss.c_str()))return true;return false;}//字母判断函数bool IsLetter(char c) {if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z')))return true;return false;}//数字判断函数bool IsDigit(char c) {if(c>='0'&&c<='9')return true;return false;}//运算符判断函数bool IsOptr(string ss) {int i;for(i=0;i<4;i++)if(!strcmp(optr[i].c_str(),ss.c_str()))return true ;return false;}//分界符判断函数bool IsSeparator(string ss) {int i;for(i=0;i<6;i++)if(!strcmp(separator[i].c_str(),ss.c_str()))return true;return false;}void analyse(ifstream &in) {string st="";char ch;int line=1,row=0;while((in.get(ch))) {st="";if((ch==' ')||(ch=='\t')){} //空格,tab健elseif(ch=='\n') {line++;row=0; } //换行行数加一处理elseif(IsLetter(ch)) //关键字、标识符的处理{row++;while(IsLetter(ch)||IsDigit(ch)){st+=ch;in.get(ch);}in.seekg(-1,ios::cur);//文件指针(光标)后退一个字节if(IsKey(st)) //判断是否为关键字查询关键字表;cout<<st<<"\t("<<st<<","<<1<<")"<<'\t'<<'\t'<<"关键字"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else //否则为标示符cout<<st<<"\t("<<st<<","<<2<<")"<<'\t'<<'\t'<<"标识符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}elseif(IsDigit(ch)) //无符号整数处理{row++;while(IsDigit(ch)){st+=ch;ch=in.get();}in.seekg(-1,ios::cur);cout<<st<<"\t("<<st<<","<<3<<")"<<'\t'<<'\t'<<"常数"<<'\t'<<"("<<line<<","<<row<<")"<<endl;// break;}else{st="";st+=ch;if(IsOptr(st)) //运算符处理{row++;cout<<st<<"\t("<<st<<","<<4<<")"<<'\t'<<'\t'<<"运算符"<<"("<<line<<","<<row<<")"<<endl;}elseif(IsSeparator(st))//分隔符处理{ row++;cout<<st<<"\t("<<st<<","<<5<<")"<<'\t'<<'\t'<<"分界符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}else{switch(ch){row++;case'=' : {row++;cout<<"="<<"\t("<<"="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}case'>' :{row++;ch=in.get();if(ch=='=')cout<<">="<<'\t'<<"("<<">="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else {cout<<">"<<"\t("<<">"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}} break;case'<' :{row++;ch=in.get();if(ch=='=')cout<<"<="<<'\t'<<"("<<"="<<","<<"6"<<")"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else if(ch=='>') cout<<"<>"<<'\t'<<"("<<"<>"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else{cout<<"<"<<"\t("<<"<"<<","<<"6"<<")"<<"\t"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}}break;default :{row++; cout<<ch<<'\t'<<"\t$无法识别字符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}}}}}}int main(){ifstream in;in.open("test.txt",ios::in);cout<<"关键字1 标识符2 常数3 运算符4 分隔符5关系运算符6"<<endl;if(in.is_open()){analyse(in);in.close();system("pause");}elsecout<<"文件操作出错"<<endl;}实验二源代码:#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char Vn[5]={'E','G','T','S','F'};//非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'};//终结符数组char ch,X;//ch读当前字符,X获取栈顶元素char strToken[Length];//存储规约表达式struct LL//ll(1)分析表的构造字初始化{char*c;};LL E[8]={"TG","TG","error","error","error","error","error","error"}; LL G[8]={"error","error","null","+TG","-TG","error","error","null"}; LL T[8]={"FS","FS","error","error","error","error","error","error"}; LL S[8]={"error","error","null","null","null","*FS","/FS","null"};LL F[8]={"i","(E)","error","error","error","error","error","error"};class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();//删除栈顶元素void out();//输出栈中元素~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}int length(char *c){int l=0;for(int i=0;c[i]!='\0';i++)l++;return l;}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void run(){bool flag=true;//循环条件int step=0,point=0;//步骤、指针int len;//长度cout<<"输入规约的字符串:"<<endl;cin>>strToken;ch=strToken[point++];//读取第一个字符stack s;s.push('#');//栈中数据初始化s.push('E');s.get_top(X);//取栈顶元素cout<<"步骤\t"<<"分析栈\t"<<"剩余输入串\t\t"<<"所用产生式\t"<<"动作"<<endl;cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"初始化"<<endl;while(flag){if((X==Vt[0])||(X==Vt[1])||(X==Vt[2])||(X==Vt[3])||(X==Vt[4])||(X==Vt[5])||(X==Vt[6])) //判断是否为终结符(不包括#){if(X==ch)//终结符,识别,进行下一字符规约{s.pop();s.get_top(X);ch=strToken[point++];cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"GETNEXT(I)"<<endl;}else{flag=false;}}else if(X=='#')//规约结束{if(X==ch){cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<ch<<'\t'<<"结束"<<endl;s.pop();flag=false;}else{flag=false;}}else if(X==Vn[0]) //非终结符E{for(int i=0;i<8;i++)//查分析表if(ch==Vt[i]){if(strcmp(E[i].c,"error")==0)//出错{flag=false;}else{ //对形如X->X1X2的产生式进行入栈操作s.pop();len=length(E[i].c)-1;for(int j=len;j>=0;j--)s.push(E[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<E[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<E[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[1]) //同上,处理G{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(G[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(G[i].c,"error")==0){flag=false;}else{s.pop();len=length(G[i].c)-1;for(int j=len;j>=0;j--)s.push(G[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<G[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<G[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[2]) //同上处理T{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(T[i].c,"error")==0){flag=false;}else{s.pop();len=length(T[i].c)-1;for(int j=len;j>=0;j--)s.push(T[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<T[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<T[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[3])//同上处理S{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(S[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(S[i].c,"error")==0){flag=false;}else{s.pop();len=length(S[i].c)-1;for(int j=len;j>=0;j--)s.push(S[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<S[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<S[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[4]) //同上处理F{for(int i=0;i<7;i++)if(ch==Vt[i]){if(strcmp(F[i].c,"error")==0){flag=false;}else{s.pop();len=length(F[i].c)-1;for(int j=len;j>=0;j--)s.push(F[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<F[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<F[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else //出错处理{flag= false;}}}int main(){cout<<"实验二"<<endl;run();system("pause");return 0;}实验三源代码:#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char ch,Y;//全局变量,ch用于读当前字符,Y用于获取栈顶元素char strToken[Length];//存储规约表达式bool flag=true;//循环条件int point=0,step=1;//步骤、指针class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();void out();//输出栈中元素void out1();~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack l,r;//l代表符号栈,r代表状态栈stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}void stack::out1(){for(int i=0;i<count;i++)cout<<int(data[i]);cout<<'\t';}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void Goto(int i,char c)//状态转换函数,对应于表中GOTO {if(i==0){if(c=='E'){r.push(1);cout<<",GOTO(0,E)=1入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(0,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(0,F)=3入栈"<<endl;}elseflag=false;}else if(i==4){if(c=='E'){r.push(8);cout<<",GOTO(4,E)=8入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(4,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(4,F)=3入栈"<<endl;}elseflag=false;}else if(i==6){if(c=='T'){r.push(9);cout<<",GOTO(6,T)=9入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(6,F)=3入栈"<<endl;}elseflag=false;}else if(i==7){if(c=='F'){r.push(10);cout<<",GOTO(7,F)=10入栈"<<endl;}elseflag=false;}elseflag=false;}void Action0()//状态0时{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为( ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action1()//状态1{if(ch=='+')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[1,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch=='#')//分析成功{flag=false;cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"Acc:分析成功"<<endl;}elseflag=false;}void Action2() //状态2{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[2,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('E');print(point-1,strToken);cout<<"r2: E→T归约";r.pop();r.get_top(Y);Goto(int(Y),'E');}elseflag=false;}void Action3()//状态3{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('T');print(point-1,strToken);cout<<"r4: T→F归约";r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action4_6_7(int x)//状态4,6,7{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为(,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action5()//状态5{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('F');print(point-1,strToken);cout<<"r6: F→i归约";r.pop();r.get_top(Y);Goto(int(Y),'F');}elseflag=false;}void Action8()//状态8{if(ch=='+')//下一个操作符为+ ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch==')')//下一个操作符为),移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,)]=S11,状态11入栈"<<endl;r.push(11);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action9()//状态9{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[9,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('E');print(point-1,strToken);cout<<"r1: E→E+T归约";r.pop();r.pop();r.pop();r.get_top(Y);}elseflag=false;}void Action10()//状态10{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('T');print(point-1,strToken);cout<<"r3: T→T*F归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action11()//状态11{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('F');print(point-1,strToken);cout<<"r5: F→(E)归约";r.pop();r.pop();r.pop();r.get_top(Y);}elseflag=false;}void run()//规约{cout<<"请输入要规约的字符串:"<<endl;cin>>strToken;cout<<"步骤\t"<<"状态栈\t"<<"符号栈\t"<<"输入串\t\t"<<"动作说明"<<endl;ch=strToken[point++];//读取第一个字符l.push('#');r.push(0);r.get_top(Y);while(flag)//循环规约{if(int(Y)==0)Action0();else if(int(Y)==1)Action1();else if(int(Y)==2)Action2();else if(int(Y)==3)Action3();else if((int(Y)==4)||(int(Y)==6)||(int(Y)==7))Action4_6_7(int(Y));else if(int(Y)==5)Action5();else if(int(Y)==8)Action8();else if(int(Y)==9)Action9();else if(int(Y)==10)Action10();else if(int(Y)==11)Action11();elseflag=false;r.get_top(Y);}}int main(){cout<<"实验三"<<endl;run();system("pause");return 0;}。