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

合集下载

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

编译原理词法分析,语法分析实验报告

编译原理词法分析,语法分析实验报告

char left[50];
/* 左部 */
char right[50][50];
/* 右部 */
char first[50][50],follow[50][50];
/* 各产生式右部的 FIRST 和左部的 FOLLOW 集合 */
char first1[50][50];
/* 所有单个符号的 FIRST 集合 */
int i,j,k,result=1,mark=0;
char temp[20];
temp[0]=c;
temp[1]='\0';
merge(empt,temp,1);
if(in(c,empty)==1)
return(1);
for(i=0;;i++)
{
if(i==count)
return(0);
if(left[i]==c)
}
/*******************************************
将单个符号或符号串并入另一符号串 ********************************************/
void merge(char *d,char *s,int type)
{
/*d 是目标符号串, s 是源串, type=1,源串中的‘ ^ ’一并并入目串;
int count=0;
/* 分解的产生式的个数 */
int number;
/* 所有终结符和非终结符的总数 */
char start;
/* 开始符号 */
char termin[50];
/* 终结符号 */
char non_ter[50];

编译原理实验词法分析实验报告

编译原理实验词法分析实验报告

编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。

本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。

二、实验环境本次实验使用的编程语言为_____,开发工具为_____。

三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。

单词符号通常包括关键字、标识符、常量、运算符和界符等。

词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。

在本次实验中,我们采用了状态转换图法。

状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。

通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。

四、实验步骤1、定义单词符号的类别和编码首先,确定实验中要识别的单词符号种类,如关键字(if、else、while 等)、标识符、整数常量、浮点数常量、运算符(+、、、/等)和界符(括号、逗号等)。

为每个单词符号类别分配一个唯一的编码,以便后续处理。

2、设计状态转换图根据单词符号的词法规则,绘制状态转换图。

例如,对于标识符的识别,起始状态为“起始状态”,当输入为字母时进入“标识符中间状态”,在“标识符中间状态”中,若输入为字母或数字则继续保持该状态,直到遇到非字母数字字符时结束识别,确定为一个标识符。

3、编写词法分析程序根据状态转换图,使用所选编程语言实现词法分析器。

在程序中,通过不断读取输入字符,根据当前状态进行转移,并在适当的时候输出识别到的单词符号。

4、测试词法分析程序准备一组包含各种单词符号的测试用例。

将测试用例输入到词法分析程序中,检查输出的单词符号是否正确。

五、实验代码以下是本次实验中实现词法分析器的核心代码部分:```include <stdioh>include <ctypeh>//单词符号类别定义typedef enum {KEYWORD,IDENTIFIER,INTEGER_CONSTANT,FLOAT_CONSTANT,OPERATOR,DELIMITER} TokenType;//关键字列表char keywords ={"if","else","while","for","int","float","void"};//状态定义typedef enum {START,IN_IDENTIFIER,IN_INTEGER,IN_FLOAT,IN_OPERATOR} State;//词法分析函数TokenType getToken(char token, int tokenLength) {State state = START;int i = 0;while (1) {char c = getchar();switch (state) {case START:if (isalpha(c)){state = IN_IDENTIFIER;tokeni++= c;} else if (isdigit(c)){state = IN_INTEGER;tokeni++= c;} else if (c =='+'|| c ==''|| c ==''|| c =='/'|| c =='('|| c ==')'|| c ==';'|| c ==','){state = IN_OPERATOR;tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else if (c == EOF) {tokeni ='\0';tokenLength = i;return -1;} else {tokeni ='\0';tokenLength = i;return -2;}break;case IN_IDENTIFIER:if (isalpha(c) || isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;//检查是否为关键字for (int j = 0; j < sizeof(keywords) / sizeof(keywords0); j++){if (strcmp(token, keywordsj) == 0) {return KEYWORD;}}return IDENTIFIER;}break;case IN_INTEGER:if (isdigit(c)){tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return INTEGER_CONSTANT;}break;case IN_FLOAT:if (isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return FLOAT_CONSTANT;}break;case IN_OPERATOR: tokeni ='\0';tokenLength = i;return OPERATOR; break;}}}int main(){char token100;int tokenLength;TokenType tokenType;while ((tokenType = getToken(token, &tokenLength))!=-1) {switch (tokenType) {case KEYWORD:printf("Keyword: %s\n", token);break;case IDENTIFIER:printf("Identifier: %s\n", token);break;case INTEGER_CONSTANT:printf("Integer Constant: %s\n", token);break;case FLOAT_CONSTANT:printf("Float Constant: %s\n", token);break;case OPERATOR:printf("Operator: %s\n", token);break;case DELIMITER:printf("Delimiter: %s\n", token);break;}}return 0;}```六、实验结果对准备的测试用例进行输入,得到的词法分析结果如下:测试用例 1:```int main(){int num = 10;float pi = 314;if (num > 5) {printf("Hello, World!\n");}}```词法分析结果:```Keyword: int Identifier: main Delimiter: (Delimiter: ){Identifier: num Operator: =Integer Constant: 10;Identifier: float Identifier: pi Operator: =Float Constant: 314;Keyword: ifDelimiter: (Identifier: numOperator: >Integer Constant: 5){Identifier: printfDelimiter: (String: "Hello, World!\n" Delimiter: );}```测试用例 2:```for (int i = 0; i < 10; i++){double result = i 25;```词法分析结果:```Keyword: for Delimiter: (Keyword: int Identifier: i Operator: =Integer Constant: 0;Identifier: i Operator: <Integer Constant: 10;Identifier: i Operator: ++)Identifier: doubleIdentifier: resultOperator: =Identifier: iOperator:Float Constant: 25;}```通过对多个测试用例的分析,词法分析器能够正确识别出各种单词符号,实验结果符合预期。

词法分析器实验报告

词法分析器实验报告

词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。

本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。

二、实验目标本实验的目标是设计和实现一个能够对C语言代码进行词法分析的程序。

该程序能够将源代码分解成关键字、标识符、常量、运算符等各种词法单元,并输出其对应的词法类别。

三、实验方法1. 设计词法规则:根据C语言的词法规则,设计相应的正则表达式来描述各种词法单元的模式。

2. 实现词法分析器:利用编程语言(如Python)实现词法分析器,将源代码作为输入,根据词法规则将其分解成各种词法单元,并输出其类别。

3. 测试和调试:编写测试用例,对词法分析器进行测试和调试,确保其能够正确地识别和输出各种词法单元。

四、实验过程1. 设计词法规则:根据C语言的词法规则,我们需要设计正则表达式来描述各种词法单元的模式。

例如,关键字可以使用'|'操作符将所有关键字列举出来,标识符可以使用[a-zA-Z_][a-zA-Z0-9_]*的模式来匹配,常量可以使用[0-9]+的模式来匹配等等。

2. 实现词法分析器:我们选择使用Python来实现词法分析器。

首先,我们需要读取源代码文件,并将其按行分解。

然后,针对每一行的代码,我们使用正则表达式进行匹配,以识别各种词法单元。

最后,我们将识别出的词法单元输出到一个结果文件中。

3. 测试和调试:我们编写了一系列的测试用例,包括各种不同的C语言代码片段,以测试词法分析器的正确性和鲁棒性。

通过逐个测试用例的运行结果,我们可以发现和解决词法分析器中的问题,并进行相应的调试。

五、实验结果经过多次测试和调试,我们的词法分析器能够正确地将C语言代码分解成各种词法单元,并输出其对应的类别。

例如,对于输入的代码片段:```cint main() {int a = 10;printf("Hello, world!\n");return 0;}```我们的词法分析器将输出以下结果:```关键字:int标识符:main运算符:(运算符:)运算符:{关键字:int标识符:a运算符:=常量:10运算符:;标识符:printf运算符:(常量:"Hello, world!\n"运算符:)运算符:;关键字:return常量:0运算符:;```可以看到,词法分析器能够正确地将代码分解成各种词法单元,并输出其对应的类别。

词法分析器的实验报告

词法分析器的实验报告

词法分析器的实验报告词法分析器的实验报告引言:词法分析器是编译原理中的重要组成部分,它负责将源代码中的字符序列转换为有意义的词法单元,为后续的语法分析提供基础。

本实验旨在设计和实现一个简单的词法分析器,并对其进行测试和评估。

实验设计:1. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。

例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。

2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。

有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。

3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。

代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。

实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。

- 运算符:包括+、-、*、/等。

- 分隔符:包括括号()和逗号,。

- 标识符:以字母开头,由字母和数字组成的字符串。

2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。

该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。

- 数字状态:用于识别和输出数字。

- 运算符状态:用于识别和输出运算符。

- 分隔符状态:用于识别和输出分隔符。

- 标识符状态:用于识别和输出标识符。

3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。

代码主要包括以下功能:- 读取源代码文件。

- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。

- 识别和输出词法单元。

实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。

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

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

计算机专业类课程实验报告课程名称:编译原理学院:计算机科学与工程专业:计算机科学与技术学生姓名:***学号:*************指导教师:***日期:2015年6月5日电子科技大学计算机学院实验中心电子科技大学实验报告实验一一、实验名称:词法分析器的设计与实现二、实验学时:4三、实验内容和目的:实验内容:求n!的极小语言的源程序作为词法分析的输入程序,根据给定的文法对其进行词法分析并将单词符号与种别组成的二元式按指定格式输出到out.dyd文件中,同时将词法错误输出到error.err文件中。

其中二元式文件out.dyd 有如下要求:(1)二元式形式:单词符号⋃种别(2)每行后加上“⋃⋃⋃...⋃EOLN⋃24”(3)文件结尾加上“⋃⋃⋃...⋃EOF⋃25”出错文件error.err中错误信息格式如下:***LINE:行号⋃⋃错误性质实验目的:通过设计并实现一个词法分析器,了解和掌握词法分析程序设计的原理及相应的程序设计方法,同时提高编程能力。

四、实验原理:1、编译程序要求对高级语言编写的源程序进行分析和合成,生成目标程序。

词法分析是对源程序进行的首次分析,实现词法分析的程序为词法分析程序。

像用自然语言书写的文章一样,源程序是由一系列的句子组成的,句子是由单词符号按一定的规则构成的,而单词符号又是由字符按一定规则构成,因此,源程序实际上是由满足程序语言规范的字符按照一定的规则组合起来构成的一个字符串。

2、词法分析的功能是从左到右逐个地扫描源程序字符串,按照词法规则识别出单词符号作为输出,对识别过程中发现的词法错误,输出相关信息。

3、单词符号是程序语言最基本的语法符号,为便于语法分析,通常将单词符号分为五类(标识符,基本字,常数,运算符,界符),而本次实验中单词符号与其对应的种别如下图所示:4、状态转换图是有限有向图,是设计词法分析器的有效工具。

图中的节点代表状态,节点间的有向边代表状态之间的转换关系,有向边上标记的字符表示状态转换的条件。

编译原理实验报告——词法分析器(内含源代码)

编译原理实验报告——词法分析器(内含源代码)

编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。

该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。

二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。

四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。

int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。

void GetChar(char *ch); //将下一个输入字符读到ch中。

void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。

void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。

int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。

void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。

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

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

山东大学编译技术课程设计班级软件一班学号**********XX姓名软件一班万岁指导老师贺老师二零一一年三月一、目的<<编译技术>>是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。

从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。

二、任务及要求基本要求:1.词法分析器产生下述小语言的单词序列这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。

所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。

例如,下面的写法是绝对禁止的:IF(5)=x其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。

也就是说,对于关键字不专设对应的转换图。

但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。

当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。

再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。

例如,一个条件语句应写为IF i>0 i= 1;而绝对不要写成IFi>0 i=1;因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。

这个小语言的单词符号的状态转换图,如下图:2.语法分析器能识别由加+ 减- 乘* 除/ 乘方^ 括号()操作数所组成的算术表达式,其文法如下:E→E+T|E-T|TT→T*F|T/F|FF→P^F|Pp→(E)|i使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。

3.中间代码生成器产生上述算术表达式的中间代码(四元式序列)三、实现过程说明给出各题目的详细算法描述,数据结构和函数说明,流程图。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

山东大学编译技术课程设计班级软件一班学号**********XX姓名软件一班万岁指导老师贺老师二零一一年三月一、目的<<编译技术>>是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。

从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。

二、任务及要求基本要求:1.词法分析器产生下述小语言的单词序列这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。

所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。

例如,下面的写法是绝对禁止的:IF(5)=x其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。

也就是说,对于关键字不专设对应的转换图。

但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。

当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。

再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。

例如,一个条件语句应写为IF i>0 i= 1;而绝对不要写成IFi>0 i=1;因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。

这个小语言的单词符号的状态转换图,如下图:2.语法分析器能识别由加+ 减- 乘* 除/ 乘方^ 括号()操作数所组成的算术表达式,其文法如下:E→E+T|E-T|TT→T*F|T/F|FF→P^F|Pp→(E)|i使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。

3.中间代码生成器产生上述算术表达式的中间代码(四元式序列)三、实现过程说明给出各题目的详细算法描述,数据结构和函数说明,流程图。

1、词法分析器的流程图2、语法分析器主程序图3、中间代码生成器流程图:四、源程序清单词法分析器#include "stdafx.h"#include "Word.h"//构造函数,对数据成员初始化,并将关键字以及运算符读入Word::Word(){//打开关键字文件fstream keywordfile("keyword.txt");if(!keywordfile){cout<<"error ! can't open keywordfile!"<<endl;system("pause");exit(1);}//设置临时变量将关键字、符号文件中的内容存储string tempword;int tempencode;string tempre;int tempvalue;//开始读关键字文件while(!(keywordfile.eof())){ keywordfile>>tempword>>tempencode>>tempre>>tempvalue;keywordlist.push_back(tempword);keywordencode.push_back(tempencode);keywordre.push_back(tempre);keywordcodevalue.push_back(tempvalue);}//关闭关键字文件keywordfile.close();for(int i=0;i<keywordlist.size();i++){cout<<setw(16)<<keywordlist[i]<<setw(16)<<keywordencode[i]<<setw(12)<<key wordre[i]<<setw(12)<<keywordcodevalue[i]<<endl;}fstream signwordfile("signword.txt");if(!signwordfile){ cout<<"error ! can't open signwordfile!"<<endl;system("pause");exit(1);}//开始读符号文件while(!(signwordfile.eof())){signwordfile>>tempword>>tempencode>>tempre>>tempvalue;signlist.push_back(tempword);signencode.push_back(tempencode);signre.push_back(tempre);signcodevalue.push_back(tempvalue);}//关闭符号文件signwordfile.close();for(int i=0;i<signlist.size();i++){cout<<setw(16)<<signlist[i]<<setw(16)<<signencode[i]<<setw(12)<<signre[i] <<setw(12)<<signcodevalue[i]<<endl;}}//将token中的字符串与character中的字符连接作为token中新的字符串void Word::concatentation(){for(int i=0;i<100;i++){if(token[i]==NULL){token[i]=s;break;}}}//判断character中的字符是否为字母和数字的布尔函数,是则返回true,否则返回false bool Word::letter(){ if(s<='z' && s>='a' )return true;else if(s<='Z' && s>='A')return true;elsereturn false;}bool Word::digit(){ if(s<='9' && s>='0')return true;return false;}//按token数组中的字符串中的前五项(即判别其是否为保留字),若是保留字则返回它的编码int Word::reserve(){int leng;//记录token数组中单词的长度for(int i=0;i<100;i++)//计算token数组中单词的长度{if(token[i]==NULL){leng=i;break;}}for(int i=0;i<keywordlist.size();i++){for(int j=0;j<keywordlist[i].length();j++){if(keywordlist[i][j]!=token[j])//若某个字符不等则终止此次循环break;if(j+1==keywordlist[i].length())//若比较字符全部相等,则判断两者是否长度相等{if(leng==keywordlist[i].length()){return i+1;}elsereturn 0;}}}return 0;}//将标识符登录到符号表中或将常数登录到常数表中void Word::buildlist(){//设置临时变量将标识符的助记符保存string tempword;int tempencode;string tempre;//标识符助记int tempvalue;int tempconstre;//常数助记s=token[0];if(letter())//第一个字符如果为字母,则将标识符登录到符号表中{ fstream chartostring("convert.txt");if(!chartostring){cout<<"Error! Can't open convert file"<<endl;system("pause");}for(int i=0;i<100;i++){if(token[i]==NULL)break;else{chartostring<<token[i];}}chartostring<<endl;chartostring.close();chartostring.open("convert.txt");if(!chartostring){cout<<"Error! Can't open convert file"<<endl;system("pause");}chartostring>>tempre;chartostring.close();indentityre.push_back(tempre);tempword="标识符";tempencode=6;tempvalue=indentityre.size();indentitylist.push_back(tempword);indentityencode.push_back(tempencode);indentitycodevalue.push_back(tempvalue);fstream indentityfile("indentityword.txt");if(!indentityfile){ cout<<"Error! Can't open indentityword file"<<endl;system("pause");}//先将文件指针移到最后去,再写入一个endlindentityfile.seekg(0,ios::end);indentityfile<<tempword<<setw(8)<<tempencode<<setw(12)<<tempre<<setw(12)<< tempvalue;indentityfile.seekg(0,ios::end);indentityfile<<endl;indentityfile.close();}else//token中存储的是常数{//将token中的字符数字转换为int类型fstream chartoint("convert.txt");if(!chartoint){cout<<"Error! Can't open convert file"<<endl;system("pause");}for(int i=0;i<100;i++){ if(token[i]==NULL)break;else{chartoint<<token[i];}}chartoint<<endl;chartoint.close();chartoint.open("convert.txt");if(!chartoint){ cout<<"Error! Can't open convert file"<<endl;system("pause");exit(1);}chartoint>>tempconstre;chartoint.close();constlist.push_back(tempword);tempword="常数";tempencode=7;tempvalue=indentityre.size();constencode.push_back(tempencode);constre.push_back(tempconstre);constvalue.push_back(tempvalue);fstream constdigit("constdigit.txt");if(!constdigit){cout<<"Error! Can't open constdigit file!"<<endl;system("pause");exit(1);}//先将文件指针移到最后去,再写入一个endlconstdigit.seekg(0,ios::end);constdigit<<tempword<<setw(8)<<tempencode<<setw(12)<<tempconstre<<setw(12) <<tempvalue;constdigit.seekg(0,ios::end);constdigit<<endl;constdigit.close();cout<<setw(16)<<tempword<<setw(16)<<tempencode<<setw(12)<<tempconstre<<set w(12)<<tempvalue<<endl;}}//出现非法字符,显示错误信息void Word::error(){cout<<"Error! Error word!"<<endl;system("pause");}void Word::signinfor(){//按token数组中的字符串中的前五项(即判别其是否为保留字),若是保留字则返回它的编码int leng;//记录token数组中单词的长度for(int i=0;i<100;i++)//计算token数组中单词的长度{if(token[i]==NULL){leng=i;break;}}for(int i=0;i<signlist.size();i++){for(int j=0;j<signlist[i].length();j++){if(signlist[i][j]!=token[j])//若某个字符不等则终止此次循环break;if(j+1==signlist[i].length())//若比较字符全部相等,则判断两者是否长度相等{if(leng==signlist[i].length()){cout<<setw(16)<<signlist[i]<<setw(16)<<signencode[i]<<setw(12)<<signre[i]< <setw(12)<<signcodevalue[i]<<endl;}}}}}//词法分析的函数void Word::run(){cout<<setw(16)<<"单词符号"<<setw(16)<<"种别编码"<<setw(12)<<"助记符"<<setw(12)<<"内码值"<<endl;fstream file("word.txt");if(!file){cout<<"error,can't open file"<<endl;system("pause");exit(1);}file.unsetf(ios::skipws);while(s!='#' && !file.eof()){for(int i=0;i<100;i++){token[i]=NULL;}file>>s;while(s==' '){file>>s;}switch(s){case 'a';case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':while(letter()||digit()){concatentation();//将当前读入的字符送入token数组file>>s;//继续读字符,直到字符不为数字或字母为止}//扫描指针回退一个字符file.seekg(-1,ios::cur);code=reserve();if(!code){ buildlist();}else{cout<<setw(16)<<keywordlist[code-1]<<setw(16)<<keywordencode[code-1]<<setw (12)<<keywordre[code-1]<<setw(12)<<keywordcodevalue[code-1]<<endl;}break;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':while(digit()){concatentation();//将当前读入的字符送入token数组file>>s;//继续读字符,直到字符不为数字为止}//扫描指针回退一个字符file.seekg(-1,ios::cur);buildlist();break;case '+':concatentation();signinfor();break;case '-':concatentation();signinfor();break;case '*':concatentation();signinfor();break;case '<':concatentation();file>>s;if(s!='='){//扫描指针回退一个字符file.seekg(-1,ios::cur);signinfor();}else{concatentation();signinfor();}break;case '=':concatentation();file>>s;if(s!='='){//扫描指针回退一个字符file.seekg(-1,ios::cur);signinfor();}else{concatentation();signinfor();}break;case ';':concatentation();signinfor();break;case '#':cout<<endl;cout<<endl;cout<<setw(16)<<"词法分析结束!"<<endl;system("pause");exit(1);default:error();}}file.close();}void main(){Word word;word.run();system("pause");}运行结果:语法分析器源程序:#include<iostream.h> #include<string.h>#include<stdio.h> typedef struct{char R;char r;int flag;}array;typedef struct{char E;char e;}charLode;typedef struct{charLode *base;int top;}charstack;char str[80][80],arr[80][80],brr[80][80];array F[20];int m,kk,p,ppp,FF=1;char r[10];int crr[20][20],FLAG=0;char ccrr1[1][20],ccrr2[20][1];void Initstack(charstack &s)//定义栈{s.base=new charLode[20];s.top=-1;}void push(charstack &s,charLode w){s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}void pop(charstack &s,charLode &w){w.E=s.base[s.top].E;w.e=s.base[s.top].e;s.top--;}int IsEmpty(charstack s){if(s.top==-1)return 1;else return 0;}int IsLetter(char ch){if(ch>='A'&&ch<='Z')return 1;else return 0;}//judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法int judge1(int n){int j=3,flag=0;for(int i=0;i<=n;i++)while(str[i][j]!='\0'){char a=str[i][j];char b=str[i][j+1];if(IsLetter(a)&&IsLetter(b)){flag=1;break;}else j++;}if(flag==1)return 0;elsereturn 1;}//judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法void judge2(int n){for(int i=0;i<=n;i++)if(str[i][3]=='~'||judge1(n)==0||FLAG==1)//'~'代表空字{cout<<"文法G不是算符优先文法!"<<endl;FF=0;break;}if(i>n)cout<<"文法G是算符优先文法!"<<endl;}//search1是查看存放终结符的数组r中是否含有重复的终结符int search1(char r[],int kk,char a){for(int i=0;i<kk;i++)if(r[i]==a)break;if(i==kk) return 0;else return 1;}//createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体void createF(int n){int k=0,i=1;char g;char t[10];//t数组用来存放非终结符t[0]=str[0][0];while(i<=n){if(t[k]!=str[i][0]){k++;t[k]=str[i][0];g=t[k];i++;}else i++;}kk=0;char c;for(i=0;i<=n;i++){ int j=3;while(str[i][j]!='\0'){c=str[i][j];if(IsLetter(c)==0){if(!search1(r,kk,c))r[kk]=c;kk++;//r数组用来存放终结符}j++;}}m=0;for(i=0;i<k;i++)for(int j=0;j<kk-1;j++){F[m].R=t[i];F[m].r=r[j];F[m].flag=0;m++;}}//search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1 void search(charLode w){for(int i=0;i<m;i++)if(F[i].R==w.E&&F[i].r==w.e){F[i].flag=1;break;}}void FirstVT(int n)//求FirstVT{charstack sta;charLode w;int i=0;Initstack(sta);while(i<=n){int k=3;w.E=str[i][0];char a=str[i][k];char b=str[i][k+1];if(!IsLetter(a))//产生式的后选式的第一个字符就是终结符的情况{w.e=a;push(sta,w);search(w);i++;}else if(IsLetter(a)&&b!='\0'&&!IsLetter(b))//产生式的后选式的第一个字符是非终结符的情况{w.e=b;push(sta,w);search(w);i++;}else i++;}charLode ww;while(!IsEmpty(sta)){pop(sta,ww);for(i=0;i<=n;i++){w.E=str[i][0];if(str[i][3]==ww.E&&str[i][4]=='\0'){w.e=ww.e;push(sta,w);search(w);break;}}}p=0;int k=1;i=1;while(i<m){if(F[i-1].flag==1){arr[p][0]=F[i-1].R;arr[p][k]=F[i-1].r;}while(F[i].flag==0&&i<m)i++;if(F[i].flag==1){if(F[i].R==arr[p][0])k++;else {arr[p][k+1]='\0';p++;k=1;} i++;}}}void LastVT(int n)//求LastVT{charstack sta;charLode w;for(int i=0;i<m;i++)F[i].flag=0;i=0;Initstack(sta);while(i<=n){int k=strlen(str[i]);w.E=str[i][0];char a=str[i][k-1];char b=str[i][k-2];if(!IsLetter(a)){w.e=a;push(sta,w);search(w);i++;}else if(IsLetter(a)&&!IsLetter(b)){w.e=b;push(sta,w);search(w);i++;}else i++;}charLode ee;while(!IsEmpty(sta)){pop(sta,ee);for(i=0;i<=n;i++){w.E=str[i][0];if(str[i][3]==ee.E&&str[i][4]=='\0'){w.e=ee.e;push(sta,w);search(w);}}}int k=1;i=1;ppp=0;while(i<m){if(F[i-1].flag==1){brr[ppp][0]=F[i-1].R;brr[ppp][k]=F[i-1].r;}while(F[i].flag==0&&i<m)i++;if(F[i].flag==1){if(F[i].R==arr[ppp][0])k++;else {brr[ppp][k+1]='\0';ppp++;k=1;} i++;}}}void createYXB(int n)//构造优先表{int i,j;for(j=1;j<=kk;j++)ccrr1[0][j]=r[j-1];for( i=1;i<=kk;i++)ccrr2[i][0]=r[i-1];for(i=1;i<=kk;i++)for(j=1;j<=kk;j++)crr[i][j]=0;int I=0,J=3;while(I<=n){if(str[I][J+1]=='\0'){I++;J=3;}else{while(str[I][J+1]!='\0'){char aa=str[I][J];char bb=str[I][J+1];if(!IsLetter(aa)&&!IsLetter(bb))//优先及等于的情况,用1值表示等于{for(i=1;i<=kk;i++){if(ccrr2[i][0]==aa)break;}for(j=1;j<=kk;j++){if(ccrr1[0][j]==bb)break;}if(crr[i][j]==0)crr[i][j]=1;else {FLAG=1;I=n+1;}J++;}if(!IsLetter(aa)&&IsLetter(bb)&&str[I][J+2]!='\0'&&!IsLetter(str[I][J+2]))//优先及等于的情况{for(i=1;i<=kk;i++){if(ccrr2[i][0]==aa)break;}for(int j=1;j<=kk;j++){if(ccrr1[0][j]==str[I][J+2])break;}if(crr[i][j]==0)crr[i][j]=1;else {FLAG=1;I=n+1;}}if(!IsLetter(aa)&&IsLetter(bb))//优先及小于的情况,用2值表示小于{for(i=1;i<=kk;i++){if(aa==ccrr2[i][0])break;}for(j=0;j<=p;j++){if(bb==arr[j][0])break;}for(int mm=1;arr[j][mm]!='\0';mm++){for(int pp=1;pp<=kk;pp++){if(ccrr1[0][pp]==arr[j][mm])break;}if(crr[i][pp]==0)crr[i][pp]=2;else {FLAG=1;I=n+1;}}J++;}if(IsLetter(aa)&&!IsLetter(bb))//优先及大于的情况,用3值表示大于{for(i=1;i<=kk;i++){if(ccrr1[0][i]==bb)break;}for(j=0;j<=ppp;j++){if(aa==brr[j][0])break;}for(int mm=1;brr[j][mm]!='\0';mm++){for(int pp=1;pp<=kk;pp++){if(ccrr2[pp][0]==brr[j][mm])break;}if(crr[pp][i]==0)crr[pp][i]=3;else {FLAG=1;I=n+1;}}}}}}}//judge3是用来返回在归约过程中两个非终结符相比较的值int judge3(char s,char a){int i=1,j=1;while(ccrr2[i][0]!=s)i++;while(ccrr1[0][j]!=a)j++;if(crr[i][j]==3) return 3;else if(crr[i][j]==2)return 2;else if(crr[i][j]==1)return 1;else return 0;}void print(char s[],char STR[][20],int q,int u,int ii,int k)//打印归约的过程{cout<<u<<" ";for(int i=0;i<=k;i++)cout<<s[i];cout<<" ";for(i=q;i<=ii;i++)cout<<STR[0][i];cout<<" ";}void process(char STR[][20],int ii)//对输入的字符串进行归约的过程{cout<<"步骤"<<" "<<"符号栈"<<" "<<"输入串"<<" "<<"动作"<<endl; int k=0,q=0,u=0,b,i,j;char s[40],a;s[k]='#';print(s,STR,q,u,ii,k);cout<<"预备"<<endl;k++;u++;s[k]=STR[0][q];q++;print(s,STR,q,u,ii,k);cout<<"移进"<<endl;{a=STR[0][q];if(!IsLetter(s[k])) j=k;else j=k-1;b=judge3(s[j],a);if(b==3)//大于的情况进行归约{while(IsLetter(s[j-1]))j--;for(i=j;i<=k;i++)s[i]='\0';k=j;s[k]='N';u++;print(s,STR,q,u,ii,k);cout<<"归约"<<endl;}else if(b==2||b==1)//小于或等于的情况移进{k++;s[k]=a;u++;q++;print(s,STR,q,u,ii,k);if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')cout<<"接受"<<endl;else cout<<"移进"<<endl;}else{cout<<"出错"<<endl;break;}}if(s[0]=='#'&&s[1]=='N'&&s[2]=='#')cout<<"归约成功"<<endl;else cout<<"归约失败"<<endl;}void main(){int n,i,j;cout<<"请输入你要定义的文法G的产生式的个数n:";cin>>n;for(i=0;i<n;i++){gets(str[i]);j=strlen(str[i]);str[i][j]='\0';}str[i][0]='Q';str[i][1]='-';str[i][2]='>';str[i][3]='#';str[i][4]=str[0][0];str[i][5]='#';str[i][6]='\0';cout<<"你定义的产生式如下:"<<endl;for(i=0;i<=n;i++)cout<<str[i]<<endl;if(judge1(n)==0)//判断文法G是否为算符文法cout<<"文法G不是算符文法!"<<endl;if(judge1(n)==1){cout<<"文法G是算符文法!"<<endl;createF(n);FirstVT(n);LastVT(n);createYXB(n);}judge2(n);//判断文法G是否为算符优先文法if(FLAG==0){for(i=0;i<=p;i++)//打印FirstVT{cout<<"FirstVT("<<arr[i][0]<<")={";for(int l=1;arr[i][l+1]!='\0';l++)cout<<arr[i][l]<<",";cout<<arr[i][l]<<"}"<<endl;}cout<<"FirstVT(Q)={#}"<<endl;for(i=0;i<=ppp;i++)//打印LastVT{cout<<"LastVT("<<arr[i][0]<<")={";for(int l=1;brr[i][l+1]!='\0';l++)cout<<brr[i][l]<<",";cout<<brr[i][l]<<"}"<<endl;}cout<<"LastVT(Q)={#}"<<endl;cout<<"优先表如下:"<<endl;for(i=1;i<kk;i++)//打印优先关系表{cout<<" ";cout<<ccrr1[0][i];}cout<<endl;for(i=1;i<kk;i++){cout<<ccrr2[i][0]<<" ";for(j=1;j<kk;j++){if(crr[i][j]==0)cout<<" ";else if(crr[i][j]==1)cout<<"=";else if(crr[i][j]==2)cout<<"<";else if(crr[i][j]==3)cout<<">";cout<<" ";}cout<<endl;}}if(FF==1){char STR[1][20];cout<<"请输入要规约的字符串:"<<endl; gets(STR[0]);int ii=strlen(STR[0]);STR[0][ii]='#';cout<<"下面是规约的过程:"<<endl; process(STR,ii);}}运算结果:中间代码生成器源程序:/*表达式生成四元式递归子程序法*/#include <stdio.h>#include <string.h>#include <malloc.h>#include <iostream.h>#include <stdlib.h>#define STACK_INIT_SIZE 50 #define STACKINCREMENT 5 #define ERROR 0#define OVERFLOW -2#define TRUE 1#define FALSE 0#define OK 1#define NULL 0void sub_E();void sub_F();void sub_T();void sub_G();void GEQ(char m);void PRINT();typedef struct Stack{char *base;char *top;int stacksize;}Stack;int num=0;char QT[10][4],T='A',c;struct Stack SEM;struct initStack(Stack s){s.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));if(!s.base)exit(OVERFLOW);s.top=s.base;s.stacksize=STACK_INIT_SIZE;return OK;}//初始化堆栈char pop(Stack &s){char e;if(s.top==s.base){printf("栈中已无元素!");exit(ERROR);}e=*--s.top;return e;}//出栈struct push(Stack &s,char e){if(s.top-s.base>=s.stacksize){s.base=(char *)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(char));if(!s.base)exit(OVERFLOW);s.top=s.base+s.stacksize;s.stacksize+=STACKINCREMENT;}*s.top++=e;return OK;}//入栈void main(){initStack(SEM);printf("----表达式应由小写字母、运算符及小括号组成,并以\"#\"结束----\n"); printf("请输入表达式:");c=getchar();sub_E();if(c=='#')PRINT();else{printf("无结束符或漏写运算符!");exit(0);}getchar();}void sub_E(){sub_T();R1: if(c=='+'){c=getchar();sub_T();GEQ('+');goto R1;}else if(c=='-'){c=getchar();sub_T();GEQ('-');goto R1;}else ;}void sub_T(){sub_G();R4: if(c=='*'){c=getchar();sub_F();GEQ('*');goto R4;}else if(c=='/'){c=getchar();sub_F();GEQ('/');goto R4;}}void sub_F(){sub_G();R5: if(c=='^'){c=getchar();sub_G();GEQ('^');goto R5;}}void sub_G(){if(c>='a'&&c<='z'){push(SEM,c);c=getchar();}else if(c=='('){c=getchar();sub_E();if(c==')')c=getchar();else{printf("括号不匹配!");exit(0);}}else{printf("非法符号!");exit(0);}}void GEQ(char m){QT[num][0]=m;QT[num][2]=pop(SEM);QT[num][1]=pop(SEM);QT[num][3]=T;push(SEM,T);num++;T++;}void PRINT(){printf("您输入的表达式所对应的四元式为:\n");for(int i=0;i<num;i++){printf("(");printf("%c",QT[i][0]);if(QT[i][1]<='Z'&&QT[i][1]>='A')printf("\t%c%d",'t',QT[i][1]-'A'+1);elseprintf("\t%c",QT[i][1]);if(QT[i][2]<='Z'&&QT[i][1]>='A')printf("\t%c%d",'t',QT[i][2]-'A'+1);elseprintf("\t%c",QT[i][2]);if(QT[i][3]<='Z'&&QT[i][1]>='A')printf("\t%c%d",'t',QT[i][3]-'A'+1);elseprintf("\t%c",QT[i][3]);printf(")\n");}}六、总结谈谈自己的收获与体会。

相关文档
最新文档