编译原理实验报告
- 格式:doc
- 大小:148.00 KB
- 文档页数:12
编译原理实验报告一、实验目的和要求本次实验旨在对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语法分析器的词法规则和语法规则。
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理语法分析试验报告语法分析是编译原理中的重要内容之一,主要用于对源程序进行语法检查,判断其是否符合给定的语法规则。
本次试验通过使用ANTLR工具,对C语言的子集进行了语法分析的实现。
一、实验目的:1.了解语法分析的基本概念和方法;2.使用ANTLR工具生成语法分析器;3.掌握ANTLR工具的基本使用方法;4.实现对C语言子集的语法分析。
二、实验内容:本次试验主要内容是使用ANTLR工具生成C语言子集的语法分析器,并对给定的C语言子集进行语法分析。
三、实验步骤:1.学习ANTLR工具的基本概念和使用方法;2.根据C语言子集的语法规则,编写ANTLR的语法文件(.g文件);3.使用ANTLR工具生成语法分析器;4.编写测试代码,对给定的C语言子集进行语法分析。
四、实验结果:经过以上的步骤,得到了一个完整的C语言子集的语法分析器,并且通过测试代码对给定的C语言子集进行了语法分析。
五、实验总结:通过本次实验,我对语法分析有了更深入的了解,掌握了使用ANTLR工具生成语法分析器的基本方法,同时也巩固了对C语言的基本语法规则的理解。
在实验过程中,遇到了一些问题,例如在编写ANTLR的语法文件时,对一些特殊语法规则的处理上有些困惑,但通过查阅资料和与同学的探讨,最终解决了这些问题。
本次试验对于我的学习有很大的帮助,我了解到了编译原理中的重要内容之一,也更深入地理解了语法分析的基本原理和方法。
通过实验,我发现使用ANTLR工具能够更方便地生成语法分析器,大大提高了开发效率。
总之,本次试验让我对编译原理中的语法分析有了更深入的了解,并且提高了我的编程能力和分析问题的能力。
在今后的学习和工作中,我将继续深入研究编译原理相关的知识,并应用到实际项目中。
编译原理语法分析实验报告第一篇:编译原理语法分析实验报告实验2:语法分析1.实验题目和要求题目:语法分析程序的设计与实现。
实验内容:编写语法分析程序,实现对算术表达式的语法分析。
要求所分析算术表达式由如下的文法产生。
E→E+T|E-T|TT→T*F|T/F|F F→id|(E)|num实验要求:在对输入表达式进行分析的过程中,输出所采用的产生式。
方法1:编写递归调用程序实现自顶向下的分析。
方法2:编写LL(1)语法分析程序,要求如下。
(1)编程实现算法4.2,为给定文法自动构造预测分析表。
(2)编程实现算法4.1,构造LL(1)预测分析程序。
方法3:编写语法分析程序实现自底向上的分析,要求如下。
(1)构造识别所有活前缀的DFA。
(2)构造LR分析表。
(3)编程实现算法4.3,构造LR分析程序。
方法4:利用YACC自动生成语法分析程序,调用LEX自动生成的词法分析程序。
实现(采用方法1)1.1.步骤:1)对文法消除左递归E→TE'E'→+TE'|-TE'|εT→FT'T'→*FT'|/FT'|εF→id|(E)|num2)画出状态转换图化简得:3)源程序在程序中I表示id N表示num1.2.例子:a)例子1 输入:I+(N*N)输出:b)例子2 输入:I-NN 输出:第二篇:编译原理实验报告编译原理实验报告报告完成日期 2018.5.30一.组内分工与贡献介绍二.系统功能概述;我们使用了自动生成系统来完成我们的实验内容。
我们设计的系统在完成了实验基本要求的前提下,进行了一部分的扩展。
增加了声明变量类型、类型赋值判定和声明的变量被引用时作用域的判断。
从而使得我们的实验结果呈现的更加清晰和易懂。
三.分系统报告;一、词法分析子系统词法的正规式:标识符(|)* 十进制整数0 |(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)* 八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和分隔符 +| * | / | > | < | = |(|)| <=|>=|==;对于标识符和关键字: A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε综上正规文法为: S—〉I1|I2|I3|A4|A5 I1—〉0|A1 A1—〉B1C1|ε C1—〉E1D1|ε D1—〉E1C1|εE1—〉0|1|2|3|4|5|6|7|8|9 B1—〉1|2|3|4|5|6|7|8|9 I2—〉0A2 A2—〉0|B2 B2—〉C2D2 D2—〉F2E2|ε E2—〉F2D2|εC2—〉1|2|3|4|5|6|7 F2—〉0|1|2|3|4|5|6|7 I3—〉0xA3 A3—〉B3C3 B3—〉0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f C3—〉(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)|C3|εA4—〉+ |-| * | / | > | < | = |(|)| <=|>=|==; A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε状态图流程图:词法分析程序的主要数据结构与算法考虑到报告的整洁性和整体观感,此处我们仅展示主要的程序代码和算法,具体的全部代码将在整体的压缩包中一并呈现另外我们考虑到后续实验中,如果在bison语法树生成的时候推不出目标的产生式时,我们设计了报错提示,在这个词的位置出现错误提示,将记录切割出来的词在code.txt中保存,并记录他们的位置。
编译原理实验报告班级姓名:学号:自我评定:实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。
例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。
输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。
输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。
例如,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。
对于变量和常数,CLASS字段为相应的类别码;VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。
对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。
另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。
三、实现方法与环境词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。
其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。
一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵同控制程序便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。
构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。
编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。
词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。
二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
编译原理实验报告实验一词法分析器的设计与实现 (1)1)实验目的 (1)2)实验内容 (1)3)实验要求 (1)4)实验原理 (1)5)实验步骤 (1)6)状态转化图及词法分析程序 (2)7)测试 (7)实验二语法分析器的设计与实现 (9)1)实验目的 (9)2)实验内容 (9)3)实验要求 (9)4)实验原理 (9)5)实验步骤 (9)6)语法分析程序 (10)7)测试 (16)编译原理实验报告专业:计算机科学与技术学生姓名:学号: 48完成时间:2020年11月25日实验一词法分析器的设计与实现1)实验目的①掌握正规式、状态转换图、C语言单词符号的划分及词法分析器的实现②掌握词法分析程序的作用和接口。
2)实验内容设计及实现C语言程序的词法分析器。
3)实验要求①对任给的一个C语言源程序,能够虑掉空格、回车换行符、tab键及注释。
②识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以二元式形式输出。
并构造符号表。
③输出有词法错误的单词及所在行号。
4)实验原理根据扫描到的单词符号的第一个字符的种类,分别转到相应的程序进行处理。
这些程序的功能就是识别以相应字符开头的各类单词符号。
5)实验步骤①根据C语言各类单词的正规式,构造能识别各类单词的状态转换图。
②根据状态转换图,构造识别各类单词的词法分析器。
6)状态转化图及词法分析程序#include ""#include ""#include ""FILE *fp;int id;void main(){char cbuffer;char alphaprocess(char buffer);char digitprocess(char buffer);char otherprocess(char buffer);if ((fp=fopen("","r"))==NULL) /*以只读方式打开文件"",NULL在文件中已被定义为0*/printf("error");else{cbuffer=fgetc(fp); /*文件不为空则从文件中取字符*/while (cbuffer!=EOF) /*EOF文件结束标志*/{if(cbuffer==' '||cbuffer=='\n') /*掠过空格和回车符*/{cbuffer=fgetc(fp);id=4;}else if(isalpha(cbuffer))cbuffer=alphaprocess(cbuffer); /*检查cbuffer是否为字母,是则调用alphaprocess()函数*/else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer); /*检查cbuffer是否为数字0~9,是则调用digitprocess()函数*/else cbuffer=otherprocess(cbuffer); /*非上述两者则调用otherprocess()函数*/}}}char alphaprocess(char buffer){int search(char searchchar[],int wordtype); /*函数声明*/int atype;int i=-1;char alphatp[20]; /*字符数组存储从文件中读取的字符*/while((isalpha(buffer))||(isdigit(buffer))||buffer=='_') /*标识符的组成成分*/{alphatp[++i]=buffer; /*将当前读取的字符存如数组*/buffer=fgetc(fp); /*读取下一个字符*/}alphatp[i+1]='\0'; /*字符串以'\0'作为结束标志*/atype=search(alphatp,1); /*调用函数,判断当前字符串是否为关键字*/if(atype!=0) /*是关键字则输出该关键字,编号为1,并输出该关键字在关键字表中的位子*/{printf("(%s, (1,%d))\n",alphatp,atype);id=1; /*关键字的ID为1*/}else{printf("(%s ,2)\n",alphatp); /*为标识符时,编号为2*/id=2; /*标识符的ID为2*/}return(buffer);}/*判断字符串是否为关键字*/int search(char searchchar[],int wordtype){char * key[32]={"auto","break","case","char","const","continue","default","d o", "double","else","enum","extern","float","for","goto","if","int","long ", "register","return","short","signed","sizeof","static","struct", "volatile","while","switch","typedef","union","unsigned","void"};/*设置数组指针存储c语言中的32个关键字*/int i;int p;switch (wordtype){case 1:for (i=0;i{if (strcmp(key[i],searchchar)==0) /*比较字符串,为关键字则定位该关键字的序号*/{ p=i+1; break; }else p=0;}return(p);}}char digitprocess(char buffer){int i=-1;char digittp[20];while ((isdigit(buffer))||buffer=='.'||buffer=='e'||buffer=='E')//考虑数字为小数和指数时的情况{digittp[++i]=buffer;buffer=fgetc(fp); /*同上*/}digittp[i+1]='\0';printf("(%s ,3)\n",digittp); /*输出该数字,编号为3*/ id=3; /*设置ID 为3*/return(buffer);}char otherprocess(char buffer){int n=0;char ch[20];ch[0]=buffer;ch[1]='\0';if(ch[0]=='%'||ch[0]=='\\'){ buffer=fgetc(fp);ch[1]=buffer;ch[2]='\0';printf("(%s ,5)\n",ch);id=4;buffer=fgetc(fp);return(buffer);}if(ch[0]=='&'){buffer=fgetc(fp);if(buffer!='&')printf("(%s ,5)\n",ch);id=4;return(buffer);}if(buffer=='&'){ch[1]=buffer;ch[2]='\0';printf("(%s ,4)\n",ch);id=3;buffer=fgetc(fp);return(buffer);}}if(ch[0]==','||ch[0]==';'||ch[0]=='{'||ch[0]=='}'||ch[0]=='('||ch[0]= =')') {printf("(%s ,5)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='*'||ch[0]=='/')printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='='||ch[0]=='!'||ch[0]==''){buffer=fgetc(fp);if(buffer=='=') /*防止'==','!=','='符号的分离*/ { ch[1]=buffer;ch[2]='\0';printf("(%s ,4)\n",ch);}else{printf("(%s ,4)\n",ch);id=4;return(buffer);}buffer=fgetc(fp);id=4;return(buffer);-全文完-。
编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
实验3 语义分析实验报告一、实验目的二、通过上机实习, 加深对语法制导翻译原理的理解, 掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求四、采用递归下降语法制导翻译法, 对算术表达式、赋值语句进行语义分析并生成四元式序列。
五、算法思想1.设置语义过程。
(1)emit(char *result,char *ag1,char *op,char *ag2)该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:struct{ char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];(2) char *newtemp()该函数回送一个新的临时变量名, 临时变量名产生的顺序为T1, T2, …char *newtemp(void){ char *p;char m[8];p=(char *)malloc(8);k++;itoa(k,m,10);strcpy(p+1,m);p[0]=’t’;return(p);}六、 2.函数lrparser 在原来语法分析的基础上插入相应的语义动作: 将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>#include<stdlib.h>struct{char result[12];char ag1[12];char op[12];char ag2[12];}quad;char prog[80],token[12];char ch;int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针, m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scaner();char *factor(void);char *term(void);char *expression(void);int yucu();void emit(char *result,char *ag1,char *op,char *ag2);char *newtemp();int statement();int k=0;void emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad.result,result);strcpy(quad.ag1,ag1);strcpy(quad.op,op);strcpy(quad.ag2,ag2);cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl;}char *newtemp(){char *p;char m[12];p=(char *)malloc(12);k++;itoa(k,m,10);strcpy(p+1,m);p[0]='t';return (p);}void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; default: syn=-1;break;}}int lrparser(){//cout<<"调用lrparser"<<endl;int schain=0;kk=0;if(syn==1){scaner();schain=yucu();if(syn==6){scaner();if(syn==0 && (kk==0))cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else{cout<<"缺begin!"<<endl;kk=1;}return(schain);}int yucu(){// cout<<"调用yucu"<<endl;int schain=0;schain=statement();while(syn==26){scaner();schain=statement();}return(schain);}int statement(){//cout<<"调用statement"<<endl;char *eplace,*tt;eplace=(char *)malloc(12);tt=(char *)malloc(12);int schain=0;switch(syn){case 10:strcpy(tt,token);scaner();if(syn==18){scaner();strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else{cout<<"缺少赋值符!"<<endl;kk=1;}return(schain);break;}return(schain);}char *expression(void){char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt =(char *)malloc(12);strcpy(eplace,term ()); //调用term分析产生表达式计算的第一项eplacewhile((syn==15)||(syn==16)){if(syn==15)strcpy(tt,"+");else strcpy(tt,"-");scaner();strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *term(void){// cout<<"调用term"<<endl;char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==13)||(syn==14)){if(syn==13)strcpy(tt,"*");else strcpy(tt,"/");scaner();strcpy(ep2,factor()); //调用factor分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *factor(void){char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){strcpy(fplace,token); //将标识符token的值赋给fplacescaner();}else if(syn==11){itoa(sum,fplace,10);scaner();}else if(syn==27){scaner();fplace=expression(); //调用expression分析返回表达式的值if(syn==28)scaner();else{cout<<"缺)错误!"<<endl;kk=1;}}else{cout<<"缺(错误!"<<endl;kk=1;}return(fplace);}void main(){p=0;cout<<"**********语义分析程序**********"<<endl;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();}七、结果验证1、给定源程序begin a:=2+3*4; x:=(a+b)/c end#输出结果2、源程序begin a:=9; x:=2*3-1; b:=(a+x)/2 end#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
学生学号实验课成绩武汉理工大学学生实验报告书实验课程名称编译原理开课学院计算机科学与技术学院指导老师姓名饶文碧学生姓名学生专业班级—学年第学期实验课程名称:编译原理实验项目名称单词的词法分析实验成绩实验者专业班级组别同组者实验日期第一部分:实验分析与设计(可加页)一、实验内容描述(问题域描述)完成对某一种常用高级语言(如Pascal、C语言、PL/0语言)的各类单词进行词法分析,即对源程序从左到右进行扫描,对组成源程序的字符串拼接成为单词;并把其转换成属性字输出。
实验要求:(1)选择常用高级程序设计语言(如 Pascal、C语言、PL/0语言)的源程序作为词法分析对象。
(2)根据教学要求和学生具体情况,从上列语言之一中选取它的一个适当大小的子集,可以选取一类典型单词,也可以尽可能使各种类型的单词都能兼顾到。
其基本要求是:对源程序从左到右进行扫描,对组成源程序的字符串拼接成为单词,并把其转换成属性字输出。
二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或者算法描述)#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>char *table[7]={" ","main","int","if","then","else","return"},TOKEN[20],ch;//定义关键字int lookup(char *TOKEN){ //关键字匹配函数int m,i;for(i=1;i<6;i++){if((m=strcmp(TOKEN,table[i]))==0)return(i);}return(0);}void out(int c,char *TOKEN){ //输出函数printf("(%d,%s)\n",c,TOKEN);}void scanner(FILE *fp){ //扫描函数char TOKEN[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符 指针fp并自动指向下一个字符 if(isalpha(ch)){ //判断该字符是否是字母TOKEN[0]=ch;ch=fgetc(fp);i=1;while(isalnum(ch)){ //判断该字符是否是字母或数字 TOKEN[i]=ch;i++;ch=fgetc(fp);}TOKEN[i]='\0';fseek(fp,-1,1); //回退一个字符c=lookup(TOKEN);if(c==0)out(6,TOKEN); //输出标识符else out(c,TOKEN); //输出关键字}elseif(isdigit(ch)){ //判断是否是数字TOKEN[0]=ch;ch=fgetc(fp);i=1;while(isdigit(ch)){TOKEN[i]=ch;i++;ch=fgetc(fp);}TOKEN[i]='\0';fseek(fp,-1,1);out(7,TOKEN);}else{TOKEN[0]=ch;switch(ch){case'{':out(17,TOKEN);break;case'}':out(18,TOKEN);break;case',':out(14,TOKEN);break;case';':out(15,TOKEN);break;case'<':ch=fgetc(fp);TOKEN[1]=ch;if(ch=='='){out(9,TOKEN);}else if(ch=='>'){out(11,TOKEN);}else {fseek(fp,-1,1);out(8,TOKEN);}break;case'=':out(10,TOKEN);break;case'>':ch=fgetc(fp);TOKEN[1]=ch;if(ch=='=') out(13,TOKEN);else {fseek(fp,-1,1);out(12,TOKEN);}break;default:printf("error!\n");break;}}}void main(){ FILE *fp;if((fp=fopen("D:\\ZHT.txt","r"))==NULL){//读取文件内容,并返回文件指针,该指针指向文件的第一个字符 fprintf(stderr,"error opening.\n");exit(1);}do{ch=fgetc(fp);if(ch=='#') //文件以#结尾作为扫描结束条件break;if(ch==' ') //如果是空格,自动跳到下个字符scanner(fp);else{fseek(fp,-1,1); //如果不是空格,则回退一个字符并扫描 scanner(fp);}}while(ch!='#');return(0);}三、主要仪器设备及耗材VC6.0第二部分:实验调试与结果分析(可加页)一、调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)在扫描源程序字符串时 一旦识别出关键字、分隔符、标识符、无符号常数中之一即以单词形式 各类单词均采用相同的结构,即二元式编码形式输出。
每次调用词法分析程序它均能自动继续扫描下去形成下一个单词,直至整个源程序全部扫描完毕,并形成相应的单词串形式的源程序。
二、实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)三、实验小结、建议及体会1、通过本次实验对词法分析的过程有了进一步的了解,并把理论知识应用于试验。
2、在编写程序过程中也遇到了很多困难,不过最终通过老师同学的帮助得到了解决。
为以后编程积累了一些小知识。
3、程序实现功能很有限,以后会继续改进。
实验课程名称:编译原理实验项目名称赋值语句的翻译程序设计实验成绩实验者专业班级组别同组者实验日期第一部分:实验分析与设计(可加页)一、实验内容描述(问题域描述)对于常用高级语言(如Pascal、C语言)的源程序从左到右进行扫描,把其中赋值语句用所学过的语法分析方法进行语法分析,采用最有代表性的语义分析方法将其转换为中间代码形式表示输出。
实验要求(1)选择最有代表性的语法分析方法,如算符优先法(或简单优先法)、递归下降分析法、LL分析法和LR分析法之一进行语法分析。
(2)选择对各种常见程序语言都通用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
(3)选择最有代表性的语义分析方法,如语法制导翻译方法进行语义翻译工作。
(4)实习时间为4~6小时。
二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或者算法描述)void main(){int g,h,i,j,l,p,y,z,count;int a[10]; //状态栈int ni[10]; //存放输出逆波兰式的参数char b[10]; //符号栈char str[10]; //放输入的表达式char c1;int top1,top2,top3,top,topn,m,n;char x;char copy[10]; //放Si,ri,看移进还是归约char copy1[10];char vt[6]={'+','*','i','(',')','#'}; //存放非终结符char vn='E';//存放终结符char *LR[4]={"E->E+E","E->E*E","E->(E)","E->i"}; //存放产生式};top1=0;top2=0;top3=0;top=0;topn=0;a[0]=0;y=a[0];b[0]='#';count=0;z=0;cout<<"文法G[E]:"<<endl;cout<<'\t'<<"(1) E::=E+E"<<endl;cout<<'\t'<<"(2) E::=E*E"<<endl;cout<<'\t'<<"(3) E::=(E)|i"<<endl;cout<<"文法G[E]合法句子举例: i+i*i"<<endl;cout<<"*************************************************************"<< endl;cout<<"请输入符号串:"<<endl;cin>>str;l = strlen(str);str [ l ] = '#';for(i=l+1;i<10;i++){str[i]=NULL;}cout<<endl<<'\t'<<'\t'<<"符号串"<<str<<" 分析过程如下:"<<endl;cout<<"-----------------------------------------------------------------"<<endl;cout<< "步骤" << '\t' << "状态栈" << '\t' << '\t' << "符号栈" << '\t' << '\t' << "输入串" << '\t' <<'\t'<< "ACTION "<<'\t'<<"GOTO"<<endl;do{y=z;m=0;n=0; //y,z指向状态栈栈顶g=top;j=0;x=str[top];count++;cout<<count <<'\t';while(m<=top1){ //输出状态栈cout<<a[m];m=m+1;}cout<<'\t'<<'\t';while(n<=top2){ //输出符号栈cout<<b[n];n=n+1;}cout<<'\t'<<'\t';str[top-1] = ' ';cout<<str; //输出输入串cout<<'\t'<<'\t';while(x!=vt[j]&&j<=6) j++; //vt[6]={'+','*','i','(',')','#'}存放终结符 if(j==6&&x!=vt[j]){cout<<endl<<"-----------------------------------------------------------------"<<endl;cout<<endl<<"输入字符串不是该文法的一个句子!"<<endl;cout<<endl<<"按任意数字或字母键,回车退出!"<<endl;cin>>i;return;}if(action[y][j]==NULL){cout<<endl<<"-----------------------------------------------------------------"<<endl;cout<<endl<<"输入字符串不是该文法的一个句子!"<<endl;cout<<endl<<"按任意数字或字母键,回车退出!"<<endl;cin>>i;return;}else//cout<<"y="<<y<<"j="<<j<<" "<<action[y][j];strcpy(copy,action[y][j]);if(copy[0]=='S'){ //处理移进z=copy[1]-'0';top1=top1+1;top2=top2+1;a[top1]=z; //a[10]状态栈b[top2]=x; //b[10]符号栈 x=str[top]top=top+1;i=0;while(copy[i]!='#'){cout<<copy[i];i++;}cout<<endl;}//cout<<"y="<<y<<"j="<<j<<" "<<action[y][j];if(copy[0]=='r'){ //处理归约i=0;while(copy[i]!='#'){cout<<copy[i];i++;}h=copy[1]-'0';ni[topn]=h;topn=topn+1;h=h-1;strcpy(copy1,LR[h]);//*LR[4]={"E->E+E#","E->E*E#","E->(E)#","E->i#"}存放产生式 //while(copy1[0]!=vn[0]) k++; //vn[1]={'E'}存放非终结符 l=strlen(LR[h]);top1=top1-l+3;y=a[top1];//cout<<"top1="<<top1;//y=h-1;p=goto1[y];top2=top2-l+4;top1=top1+1;a[top1]=p;b[top2]=copy1[0];z=p;cout<<'\t';cout<<p<<endl;}}while(action[y][j]!="acc");cout<<"acc"<<endl;cout<<endl<<"-------------------------------------------------------------"<<endl;cout<<endl<<"输入字符串是该文法的一个句子!"<<endl; cout<<"中间代码的逆波兰式如下:"<<endl;for(i=0;i<10;i++){if(ni[i]==1)cout<<"EEE+="<<endl;if(ni[i]==2)cout<<"EEE*="<<endl;if(ni[i]==3)cout<<"EE()="<<endl;if(ni[i]==4)cout<<"iE="<<endl;}cout<<endl<<"按任意数字或字母键,回车退出!"<<endl;cin>>i;}三、主要仪器设备及耗材VC6.0第二部分:实验调试与结果分析(可加页)一、调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)用LR分析法完成此次文法分析的关键在于构造该文法的分析表,以及如何运用该分析表完成移入和归约的过程,从而完成整个文法的分析。