编译原理语法分析实验报告
编译原理实验报告(词法分析器语法分析器)

函数 int f(char c) 和 int g(char c) , 判断运算符之间的优先关系 , 根据不同情况作各种不同操作 。 流程
图如下 :
word 完美格式
专业资料
输入算数表达式,以 #结束 初始化 loptr[1]= ’#’ 用 get()取一个待分析字符 s
Optr[1] 和 s 是否同时为 #
。
2 、而且对词法分析和语法分析在实践中的应用有了深入的掌握
。
3 、 更加熟悉了构造词法分析程序和语法分析程序的手工方式的相关原理
, 能够实现对词
法分析程序所提供的单词符号序列进行相应的语法检查和结构分析
,达到了学以致用的目的 。
word 完美格式
word 完美格式
专业资料
case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
while(letter(s)||digit(s)) {token[j]=s; j=j+1; get(); } retract();k=lookup(token); if(k==0)
-
9
*
10
<=
11
<
11
==
11
=
12
;
13
word 完美格式
助记符 while
if else switch case
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 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中保存,并记录他们的位置。
编译原理-词法语法分析实验报告

编译原理词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();void scanner_example (FILE *fp);main(){FILE *fp;fp=fopen("D:\\1.txt","r");//打开文件scanner_example (fp);scaner();}void scanner_example (FILE *fp){do{ch=fgetc (fp);prog[p++]=ch;}while (ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}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')){ while((ch>='0')&&(ch<='9')){ sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;case '-':token[m++]=ch;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;token[m++]=ch;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图所示:五、总结:词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
编译原理语法分析实验报告

编译原理语法分析实验报告编译原理实验报告一、实验目的本实验的主要目的是熟悉编译原理中的语法分析算法及相关知识,并通过实际编码实现一个简单的语法分析器。
二、实验内容1.完成一个简单的编程语言的语法定义,并用BNF范式表示;2.基于给定的语法定义,实现自顶向下的递归下降语法分析器;3.实验所用语法应包含终结符、非终结符、产生式及预测分析表等基本要素;4.实现语法分析器的过程中,需要考虑文法的二义性和优先级等问题。
三、实验步骤1.设计一个简单的编程语言的语法,用BNF范式进行表达。
例如,可以定义表达式文法为:<exp> ::= <term> { + <term> , - <term> }<term> ::= <factor> { * <factor> , / <factor> }<factor> ::= <digit> , (<exp>) , <variable><digit> ::= 0,1,2,3,4,5,6,7,8,9<variable> ::= a,b,c,...,z2. 根据所设计的语法,构建语法分析器。
首先定义需要用到的终结符、非终结符和产生式。
例如,终结符可以是+、-、*、/、(、)等,非终结符可以是<exp>、<term>、<factor>等,产生式可以是<exp> ::= <term> + <term> , <term> - <term>等。
3.实现递归下降语法分析器。
根据语法的产生式,编写相应的递归函数进行递归下降分析。
递归函数的输入参数通常是一个输入字符串和当前输入位置,输出结果通常是一个语法树或语法分析错误信息。
4.在语法分析的过程中,需要处理语法的二义性和优先级问题。
编译原理语法分析实验报告

//输出转化后
的文法规则串
{
printf("%s\n",text[i]);
}
for(i=0;i<x;i++) /*求每个终结符的推导结果(去掉"->"后的转化文
法,用于最后的规约)*/
{ string[i][0]=text[i][0];
for(j=3,l=1;text[i][j]!='\0';j++,l++)
表1-2 G[S]的算符优先关系矩阵表
#
i
+
*
(
)
#
i
+
*
(
)
二.程序设计
1.总体设计
求FIRSTVT模块 求LASTVT模块 识别终结符模块
读入文法规则 创建文法关系表模块
求下标模块
2.子程序设计
识别终结符模块
读取语法分析串 输入串分析模块 图2-1 总体设计图
求FIRSTVT模块 求LASTVT模块
编译原理语法分析器实验报告

西安邮电大学编译原理实验报告学院名称:计算机学院****:***实验名称:语法分析器的设计与实现班级:计科1405班学号:04141152时间:2017年5月12日一.实验目的1.熟悉语法分析的过程2.理解相关文法分析的步骤3.熟悉First集和Follow集的生成二.实验要求对于给定的文法,试编写调试一个语法分析程序:要求和提示:1)可选择一种你感兴趣的语法分析方法(LL(1)、算符优先、递归下降、SLR(1)等)作为编制语法分析程序的依据。
2)对于所选定的分析方法,如有需要,应选择一种合适的数据结构,以构造所给文法的机内表示。
3)能进行分析过程模拟。
如输入一个句子,能输出与句子对应的语法树,能对语法树生成过程进行模拟;能够输出分析过程每一步符号栈的变化情况。
设计一个由给定文法生成First集和Follow集并进行简化的算法动态模拟三.实验内容1.文法:E->TE’E’->+TE’|εT->FT’T’->*FT’|εF->(E)|i:2.程序描述(LL(1)文法)本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。
基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。
然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。
若不为“#”且不与当前输入符号一样,则出错。
3.判断是否LL(1)文法要判断是否为LL(1)文法,需要输入的文法G有如下要求:具有相同左部的规则的SELECT集两两不相交,即:SELECT(A→?)∩SELECT(A→?)= ?如果输入的文法都符合以上的要求,则该文法可以用LL(1)方法分析。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理语法分析实验报告-班级:XXX学号:XXX姓名:XXX年月日1、摘要:用递归子程序法实现对pascal的子集程序设计语言的分析程序2、实验目的:通过完成语法分析程序,了解语法分析的过程和作用3、任务概述实验要求:对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用4、实验依据的原理递归子程序法是一种自顶向下的语法分析方法,它要求文法是LL(1)文法。
通过对文法中每个非终结符编写一个递归过程,每个过程的功能是识别由该非终结符推出的串,当某非终结符的产生式有多个候选式时,程序能够按LL(1)形式唯一地确定选择某个候选式进行推导,最终识别输入串是否与文法匹配。
递归子程序法的缺点是:对文法要求高,必须满足LL(1)文法,当然在某些语言中个别产生式的推导当不满足LL(1)而满足LL(2)时,也可以采用多向前扫描一个符号的办法;它的另一个缺点是由于递归调用多,所以速度慢占用空间多,尽管这样,它还是许多高级语言,例如PASCAL,C等编译系统常常采用的语法分析方法。
为适合递归子程序法,对实验一词法分析中的文法改写成无左递归和无左共因子的,,,如下:<程序>?<程序首部><分程序>。
<程序首部>?PROGRAM标识符;<分程序>?<常量说明部分><变量说明部分><过程说明部分> <复合语句> <常量说明部分>?CONST<常量定义><常量定义后缀>;|ε<常量定义>?标识符=无符号整数<常量定义后缀>?,<常量定义><常量定义后缀> |ε<变量说明部分>?VAR<变量定义><变量定义后缀> |ε<变量定义>?标识符<标识符后缀>:<类型>;<标识符后缀>?,标识符<标识符后缀> |ε<变量定义后缀>?<变量定义><变量定义后缀> |ε<类型>?INTEGER | LONG<过程说明部分>?<过程首部><分程序>;<过程说明部分后缀>|ε<过程首部>?PROCEDURE标识符<参数部分>;<参数部分>?(标识符: <类型>)|ε<过程说明部分后缀>?<过程首部><分程序>;<过程说明部分后缀>|ε<语句>?<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句>|<写语句>|<复合语句>|ε<赋值或调用语句>?标识符<后缀><后缀>?:=<表达式>|(<表达式>)|ε<条件语句>?IF<条件>THEN<语句><当型循环语句>?WHILE<条件>DO <语句><读语句>?READ(标识符<标识符后缀>)<写语句>?WRITE(<表达式><表达式后缀>)<表达式后缀>?,<表过式><表达式后缀>|ε<复合语句>?BEGIN<语句><语句后缀>END<语句后缀>?;<语句><语句后缀>|ε<条件>?<表达式><关系运算符><表达式>|ODD<表达式><表达式>?+<项><项后缀>|-<项><项后缀>|<项><项后缀><项后缀>?<加型运算符><项><项后缀>|ε<项>?<因子><因子后缀><因子后缀>?<乘型运算符><因子><因子后缀>|e<因子>?标识符|无符号整数|(<表达式>)<加型运算符>?+|-<乘型运算型>?*|/<关系运算符>? =|<>|<|<=|>|>=5、程序设计思想为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。
由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。
在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。
语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。
也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。
出错时,可以根据读字符的位置判断出错的位置。
表2-1为非终结符和函数名对照表。
表2-1 非终符和函数名对照表非终结符函数名非终结符函数名 <程序> <程序首部> program proghead <分程序> <常量说明部分> block consexpl <常量定义> <变量说明部分> consdefi varexl <常量定义后缀> <变量定义> conssuff vandefi <变量定义后缀> <>过程说明部分> varsuff procdefi <类型> <过程首部> typeil procedh <过程说明部分后缀> <赋值或调用语句> procsuff assipro <语句> <后缀> sentence suffix <条件语句> <读语句> ifsent read <当型循环语句> <标识符后缀> whilsent idsuff <写语句> <复合语句> write compsent <表达式后缀> <语句后缀> exprsuff sentsuff <条件> <项后缀> conditio termsuff <表达式> <项> express term <因子后缀> <参数部分> factsuff argument <因子> <加型运算符> factor addoper <乘型运算符> <关系运算符> muloper respoper 表2-2为词法分析中的内码单词对照表。
表2-2 内部码对照表内码单词内码单词内码单词内码单词 1 PROGRAM 2 CONST 3 VAR 4 INTEGER 5 LONG 6 PROCEDURE 7 IF 8 THEN 9 WHILE 10 DO 11 READ 12 WRITE 13 BEGIN 14 END 15 ODD 16 + 17 - 18 * 19 / 20 = 21 <> 22 < 23 <= 24 > 25 >= 26 . 27 , 28 ; 29 : 30 := 31 ( 32 )无符号整数标识符 33 34 35 #6、实验结果分析样例1:正确的pascal子集程序代码PROGRAM test;CONST b=3;VAR x:INTEGER;y:LONG; PROCEDURE c(d:INTEGER); BEGINd(5);x:=d+4;y:=b*2+2;END;BEGINWHILE x<10 DO x:=x+b;IF x>5 THEN x:=2*x-b;END.运行结果1:样例2:错误的pascal子集程序代码test;CONST b=3;VAR x:INTEGER;y:; PROCEDURE c(d:INTEGER); BEGINd(5);x:=d+4;y:=b*2+;END;BEGINWHILE x<10 DO x:=x+b; IF x>5 x:=2*x-b;END运行结果2:7、总结通过本次实验,我能够用递归子程序法设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,更加了解了语法分析的过程和作用。
附件:LEX代码:%{#include <stdio.h>#include <stdlib.h>#include <string.h>FILE *fp;int line = 1;%}delim [" "\t]whitespace {delim}+ backspace [\n]program [pP][rR][oO][gG][rR][aA][mM]const [cC][oO][nN][sS][tT] var [vV][aA][rR]integer [iI][nN][tT][eE][gG][eE][rR]long [lL][oO][nN][gG] procedure [pP][rR][oO][cC][eE][dD][uU][rR][eE] if [iI][fF]then [tT][hH][eE][nN] while [wW][hH][iI][lL][eE] do [dD][oO]read [rR][eE][aA][dD] write [wW][rR][iI][tT][eE] begin[bB][eE][gG][iI][nN] end [eE][nN][dD]odd [oO][dD][dD]add \+minus -multiply \*div \/equal =m21 <>m22 <m23 <=m24 >m25 >=m27 ,m26 \.m28 ;m29 :m30 :=m31 \(m32 \)constant ([0-9])+identfier [A-Za-z]([A-Za-z]|[0-9])*%%{program} {fprintf(fp,"%d %d\n",1,line);} {const} {fprintf(fp,"%d%d\n",2,line);} {var} {fprintf(fp,"%d %d\n",3,line);} {integer}{fprintf(fp,"%d %d\n",4,line);} {long} {fprintf(fp,"%d %d\n",5,line);} {procedure} {fprintf(fp,"%d %d\n",6,line);} {if} {fprintf(fp,"%d%d\n",7,line);} {then} {fprintf(fp,"%d %d\n",8,line);} {while}{fprintf(fp,"%d %d\n",9,line);} {do} {fprintf(fp,"%d %d\n",10,line);} {read} {fprintf(fp,"%d %d\n",11,line);} {write} {fprintf(fp,"%d%d\n",12,line);} {begin} {fprintf(fp,"%d %d\n",13,line);} {end}{fprintf(fp,"%d %d\n",14,line);} {odd} {fprintf(fp,"%d %d\n",15,line);} {add} {fprintf(fp,"%d %d\n",16,line);} {minus} {fprintf(fp,"%d%d\n",17,line);} {multiply} {fprintf(fp,"%d %d\n",18,line);} {div} {fprintf(fp,"%d %d\n",19,line);} {equal} {fprintf(fp,"%d %d\n",20,line);} {m21} {fprintf(fp,"%d %d\n",21,line);} {m22} {fprintf(fp,"%d%d\n",22,line);} {m23} {fprintf(fp,"%d %d\n",23,line);} {m24}{fprintf(fp,"%d %d\n",24,line);} {m25} {fprintf(fp,"%d %d\n",25,line);} {m26} {fprintf(fp,"%d %d\n",26,line);} {m27} {fprintf(fp,"%d%d\n",27,line);} {m28} {fprintf(fp,"%d %d\n",28,line);} {m29}{fprintf(fp,"%d %d\n",29,line);} {m30} {fprintf(fp,"%d %d\n",30,line);} {m31} {fprintf(fp,"%d %d\n",31,line);} {m32} {fprintf(fp,"%d%d\n",32,line);} {constant} {__int64 maxnum=0xffffffff;if(strlen(yytext)>10)printf("line %d constant error:'%s'\n",line,yytext);elsefprintf(fp,"%d %d\n",33,line);}{identfier} {if(strlen(yytext)>20){printf("line %d identfier error:'%s'\n",line,yytext);}elsefprintf(fp,"%d %d\n",34,line);}{whitespace} { }{backspace} { if(strcmp(yytext,"\n")==0){line++;}}%%void main(){yyin=fopen("example.txt","r");fp=fopen("data.txt","w");fclose(fp);fp=fopen("data.txt","a");yylex(); /* start the analysis*/fclose(yyin);fclose(fp);}int yywrap(){return 1;}主程序代码:#include<string>#include<iostream>#include<fstream>#include"lex.yy.c"using namespace std;int token[2000][2] = {NULL}; int h = 0;int i,j,p=0;void program();void block();void consdefi();void conssuff(); void varsuff(); void typeil(); void procsuff(); void sentence(); void ifsent(); void whilsent(); void write(); void exprsuff(); void conditio(); void express(); void factsuff(); void factor(); void muloper(); void proghead(); void consexpl(); voidvarexl(); void vandefi(); void procdefi(); void procedh(); void assipro(); void suffix(); void read();void idsuff(); void compsent(); void sentsuff(); void termsuff(); void term();void argument(); void addoper(); void respoper();void program() {proghead();block();if (token[h][0] ==26){h++;if (token[h][0] == 0){printf("语法分析完成\n");}}else{p=1;printf("第%d行缺少.\n",token[h-1][1]);}return;}void proghead(){if (token[h][0] == 1){h++;if (token[h][0] == 34){h++;if (token[h][0] == 28){h++;}else{p=1;printf("第%d行缺少;\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少PROGRAM\n", token[h][1]); if (token[h][0] == 34){h++;if (token[h][0] == 28){h++;}}}}void block() {consexpl();varexl();procdefi();compsent();return;}void consexpl() {if (token[h][0] != 6 && token[h][0] != 3 && token[h][0] != 13) {if (token[h][0] == 2){h++;consdefi();conssuff();if (token[h][0] == 28){h++;}else{p=1;printf("第%d行缺少;\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少CONST\n", token[h][1]); consdefi();conssuff();if (token[h][0] == 28){h++;}}}return;}void consdefi(){if (token[h][0] == 34){h++;if (token[h][0] == 20){h++;if (token[h][0] == 33){h++;}else{p=1;printf("第%d行缺少无符号整数\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少=\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]);if (token[h][0] == 20){h++;if (token[h][0] == 33){h++;}}}return;}void conssuff(){if (token[h][0] != 6 && token[h][0] != 3 && token[h][0] != 13) {if (token[h][0] == 28)return;if (token[h][0] == 27){h++;consdefi();conssuff();}else{p=1;printf("第%d行缺少,\n", token[h-1][1]);consdefi();conssuff();}}return;}void varexl(){if (token[h][0] != 6 && token[h][0] != 13) {if (token[h][0] == 3){h++;vandefi();varsuff();}else{p=1;printf("第%d行缺少VAR\n", token[h][1]); vandefi();varsuff();}}return;}void vandefi(){if (token[h][0] == 34){h++;idsuff();if (token[h][0] == 29){h++;typeil();if (token[h][0] == 28){h++;}else{p=1;printf("第%d行缺少;\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少:\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]); idsuff();if (token[h][0] == 29){h++;typeil();if (token[h][0] == 28){h++;}}}return;}void idsuff(){if (token[h][0] == 4 || token[h][0] == 5){return;}if (token[h][0] != 32 && token[h][0] != 29){if (token[h][0] == 27){h++;if (token[h][0] == 34){h++;idsuff();}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少,\n", token[h-1][1]);}}return;}void varsuff() {if (token[h][0] != 6 && token[h][0] != 13){vandefi();varsuff();}return;}void typeil() {if (token[h][0] == 4||token[h][0]==5){h++;}else{p=1;printf("第%d行缺少INTEGER或LONG\n", token[h-1][1]); }return;}void procdefi(){if (token[h][0] != 13){procedh();block();if (token[h][0] == 28){h++;procsuff();}else{p=1;printf("第%d行缺少;\n", token[h-1][1]); }}return;}void procedh(){if (token[h][0] == 6){h++;if (token[h][0] == 34){h++;argument();if (token[h][0] == 28){h++;}else{p=1;printf("第%d行缺少;\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少PROCEDURE\n", token[h][1]); if (token[h][0] == 34){h++;argument();if (token[h][0] == 28){h++;}}}return;}void read(){if (token[h][0] == 11){h++;if (token[h][0] == 31){h++;if (token[h][0] == 34){h++;idsuff();if (token[h][0] == 32){h++;}else{p=1;printf("第%d行缺少)\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少(\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少READ\n", token[h-1][1]); exit(0);}return;}void ifsent(){if (token[h][0] == 7){h++;conditio();if (token[h][0] == 8){h++;sentence();}else{p=1;printf("第%d行缺少THEN\n", token[h-1][1]); sentence();}}else{p=1;printf("第%d行缺少IF\n", token[h-1][1]); exit(0);}return;}void assipro(){if (token[h][0] == 34){h++;suffix();}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]);}return;}void procsuff(){if (token[h][0] != 13){procedh();block();if (token[h][0] == 28){h++;procsuff();}else{p=1;printf("第%d行缺少;\n", token[h-1][1]); }}return;}void sentence(){if (token[h][0] != 14 && token[h][0] != 28){if (token[h][0] == 34){assipro();}else if (token[h][0] == 7) {ifsent();}else if (token[h][0] == 9) {whilsent();}else if (token[h][0] == 11) {read();}else if (token[h][0] == 12) {write();}else if (token[h][0] == 13) {compsent();}}return;}void suffix(){if (token[h][0] != 14 && token[h][0] != 28) {if (token[h][0] == 30){h++;express();}else if (token[h][0] == 31){h++;express();if (token[h][0] == 32){h++;}else{p=1;printf("第%d行缺少)\n", token[h-1][1]);}}else{p = 1; printf("第%d行缺少(\n", token[h - 1][1]); }}return;}void whilsent(){if (token[h][0] == 9){h++;conditio();if (token[h][0] == 10){h++;sentence();}else{p=1;printf("第%d行缺少DO\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少WHILE\n", token[h-1][1]); exit(0);}return;}void write(){if (token[h][0] == 12){h++;if (token[h][0] == 31){h++;express();exprsuff();if (token[h][0] == 32){h++;}else{p=1;printf("第%d行缺少)\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少(\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少WRITE\n", token[h-1][1]); exit(0);}return;}void compsent(){if (token[h][0] == 13){h++;sentence();sentsuff();if (token[h][0] == 14){h++;}else{p=1;printf("第%d行缺少END\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少BEGIN\n", token[h-1][1]); sentence();sentsuff();if (token[h][0] == 14){h++;}}return;}void exprsuff() {if (token[h][0] != 32){if (token[h][0] == 27){h++;express();exprsuff();}else{p=1;printf("第%d行缺少,\n", token[h-1][1]); }}return;}void sentsuff() {if (token[h][0] == 28){h++;if (token[h][0] != 14){sentence();sentsuff();}}else{p=1;printf("第%d行缺少;\n", token[h-1][1]);}return;}void conditio() {if (token[h][0] == 15){h++;express();}else{express();respoper();express();}return;}void termsuff() {if (token[h][0] != 21 && token[h][0] != 22 && token[h][0] != 23 && token[h][0] != 24 && token[h][0] != 25 && token[h][0] != 32 && token[h][0] != 28&& token[h][0] != 14 && token[h][0] != 8 && token[h][0] != 10 && token[h][0] !=34){addoper();term();termsuff();}}void express() {if (token[h][0] == 16||token[h][0]==17) {h++;term();termsuff();}else{term();termsuff();}}void term(){factor();factsuff();}void factsuff(){if (token[h][0] != 21 && token[h][0] != 22 && token[h][0] != 23 && token[h][0] != 24 && token[h][0] != 25 && token[h][0] != 32 && token[h][0] != 28&& token[h][0] != 14 && token[h][0] != 16 && token[h][0] != 17 && token[h][0] !=8 && token[h][0] != 10 && token[h][0] != 34){muloper();factor();factsuff();}}void argument(){if (token[h][0] != 28){if (token[h][0] == 31){h++;if (token[h][0] == 34){h++;if (token[h][0] == 29){h++;typeil();if (token[h][0] == 32){h++;}else{p=1;printf("第%d行缺少)\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少:\n", token[h-1][1]);}}else{p=1;printf("第%d行缺少标识符\n", token[h-1][1]); }}else{p=1;printf("第%d行缺少(\n", token[h-1][1]); }}return;}void factor(){if (token[h][0] != 33 && token[h][0] != 34) {if (token[h][0] == 31){h++;express();if (token[h][0] == 32){h++;}else{p=1;printf("第%d行缺少)\n", token[h-1][1]); }}else{p = 1; printf("第%d行缺少标识符或无符号整数\n", token[h - 1][1]); }}else{h++;}return;}void addoper(){if (token[h][0] == 16 || token[h][0] == 17){h++;}else{p=1;printf("第%d行缺少+或-\n", token[h-1][1]);}return;}void muloper(){if (token[h][0] == 18 || token[h][0] == 19){h++;}else{p=1;printf("第%d行缺少*或/\n", token[h-1][1]);}return;}void respoper(){if (token[h][0] == 21 || token[h][0] == 22 || token[h][0] == 23 || token[h][0] == 25|| token[h][0] == 24){h++;}else{p=1;printf("第%d行缺少关系运算符\n", token[h-1][1]);}return;}void main(){mainf();FILE *p1 = fopen("data.txt", "r");if (!p1){printf("文件打开失败~\n");}else{printf("文件打开成功~\n语法分析开始\n"); }i = 0;while (!feof(p1)){for (j = 0; j < 2; j++){fscanf(p1, "%d", &token[i][j]);}i++;}fclose(p1);program();if (p == 0){printf("Success!\n"); }else{printf("Fail!\n");}}。