编译原理实验-词法分析器(共11页).doc
精选优质文档-倾情为你奉上洛阳理工学院实验报告院部计算机系班级B学号姓名课程名称编译原理实验日期2018.6.4实验名称词法分析器成绩实验目的:加深对词法分析过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析;能够使自己编写的程序对简单的程序片段进行词法分析。实验条件:装有Windows操作系统,Microsoft Visual C+ 6.0。实验内容:自定义一种程序设计语言,或选择已有的一种高级语言(C语言),编制它的词法分析程序。实验要求:1.对单词的构成规则有明确的定义2.编写的程序能够正确识别源程序中的单词符号3.识别出的单词以<种别码,值>的形式保存在符号表中4.词法分析中源程序和分析后的符号表均保存在.txt文件中5.有一定的检查错误的能力。遇到错误时可显示“Error”,然后跳过错误部分继续显示。6. 实验报告包括以下内容(1)编程思路、流程图、源代码(2)上机调试时发现的问题,以及解决的过程(3)所使用的测试数据及结果(4)心得体会实验步骤1.给出目标语言的所有单词符号及种别编码、单词符号的状态转换图。2.依次读入源程序,对源程序进行单词切分和识别,直到源程序结束。3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中。4.对不正确的单词,做出错误处理。实验内容:1.编程思路:1.1、实现预处理功能源程序中可能包含有对程序执行无意义的符号,要求将其剔除。首先编制一个源程序的输入过程,从键盘、文件或文本框输入若干行语句,依次存入输入缓冲区(字符型数据);然后编制一个预处理子程序,去掉输入串中的回车符、换行符和跳格符等编辑性文字;把多个空白符合并为一个;去掉注释。 1.2、实现词法分析功能输入:所给文法的源程序字符串。输出:将每个单词或数字以及他对应的种别码和类型输出到文件中。具体实现时,可以将单词的二元组用结构进行处理。1.3、待分析的C语言子集的词法1)关键字 "char","int","if","else","var" ,"return","break","do","while","for","double","float","short"2)运算符和界符 + - * / < <> <= > >= = ; ( ) | & #3)空格由空白、制表符和换行符组成空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。1.4、各种单词符号对应的种别码表1 各种单词符号的种别码单词符号种别码char1int2if3else4var5return6break7do8while9for10double11float12short13标识符14数字15符号16-401.5、 词法分析程序的主要算法思想算法的基本任务是从文件中读出字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号,并输出到文件中。2.流程图:2.1主程序流程图是否输入串结束输入编译后的文件名调用分析子程序结束开始输入打开的文件名关闭文件文件为空?是输入串结束是主函数流程图2.2分析函数流程图否否是否是符号字母数字否是返回0变量初始化忽略空格是否文件结束获取一个单词获取数字在文件中写入当前单词以及对应的关键字种别码获取一个完整符号返回开始在文件中写入当前单词以及对应的符号种别码在文件中写入当前单词以及对应的符号种别码在文件中写入当前单词以及标识符种别码12将当前单词添加到标识符表中存在于数字表存在于标识符表存在于符号表存在于关键字表是将当前数字添加到数字表中将当前符号添加到符号表中是分析函数流程图3.源代码:#include<stdio.h>#include<conio.h>#include<math.h>#include<string.h>#include<stdlib.h>int i, row = 0, line = 0;char a1000; /程序int number1000100; /常数表char mark1005; /标识符表FILE *fin,*fout;/词法分析int wordanalysis() if (ai >= 'A'&&ai <= 'Z')|(ai>='a'&&ai<='z') /分析标识符和关键字 char word10; char keyWord100100 = "char","int","if","else","var" ,"return","break","do","while","for","double","float","short" /关键字表 int n = 0; wordn+ = ai+; /若字符为AZ或09,则继续读取 while (ai >= 'A'&&ai <= 'Z') | (ai >= '0' && ai <= '9')|(ai>='a'&&ai<='z') wordn+ = ai+; wordn = '0' i-; /判断该标识符是否为关键字 for (n = 0; n < 100; n+) if (strcmp(word, keyWordn) = 0) fprintf(fout,"%st(%d)t关键字n", keyWordn, n + 1); return 3; /判断该标识符是否存在标识符表中 int m = 0; if (line != 0) int q = 0; while (q<line) if (strcmp(word, markq+) = 0) fprintf(fout,"%st(14,%d)t标识符n", word, q); return 3; /将该标识符保存到标识符表中 strcpy(markline, word); fprintf(fout,"%st(14, %d)t标识符n", word, line + 1); line+; return 3; else if (ai >= '0' && ai <= '9') /分析常数 char x100; int n = 0, sum; xn+ = ai+; /判断字符是否是09 while (ai >= '0' && ai <= '9') xn+ = ai+; xn = '0' i-; int num = atoi(x); /将字符串转换成int型 /判断该常数是否存在于常数表中 if (row != 0) int y; for (y = 0; y < 1000; y+) int w = numbery0; sum = 0; int d; for (d = 1; d <= numbery0; d+) w = w - 1; sum = sum + numberyd * pow(2, w); if (num = sum) fprintf(fout,"%dt(15,%d)n", num, y + 1); return 3; int z = num, c = num; int m = 0; do /计算是几位二进制数 z = z / 2; m+; while (z != 0); for (n = m; n > 0; n-) /将二进制保存于常数表中 numberrown = c % 2; c = c / 2; numberrow0 = m; int line = row; fprintf(fout,"%dt(15,%d)n", num, line + 1); row+; return 3; else /分析符号 switch (ai) case ' ': case 'n': return -1; case '#': return 0; case '=':fprintf(fout,"=t(16)n"); return 3; case '<': i+; if (ai = '=') fprintf(fout,"<= t(17)n"); return 3; else if (ai = '>') fprintf(fout,"<>t(18)n"); return 3; else i-; fprintf(fout,"<t(19)n"); return 3; case '>': i+; if (ai = '=') fprintf(fout,">=t(20)n"); return 3; else i-; fprintf(fout,">t(21)n"); return 3; case '+': fprintf(fout,"+t(22)n"); return 3; case '-': fprintf(fout,"-t(23)n"); return 3; case '*': fprintf(fout,"*t(24)n"); return 3; case '/': i+; if(ai!='/') i-; fprintf(fout,"/t(25)n"); return 3; else while(1) if(ai+='n') return -1; fprintf(fout,"/t(35)n");return 3; case ':': fprintf(fout,":t(26)n"); return 3; case '': fprintf(fout,"t(27)n"); return 3; case '(': fprintf(fout,"(t(28)n"); return 3; case ')': fprintf(fout,")t(29)n"); return 3; case '': fprintf(fout,"t(30)n"); return 3; case '': fprintf(fout,"t(31)n"); return 3; case '': fprintf(fout,"t(32)n"); return 3; case '': fprintf(fout,"t(33)n"); return 3; case '|': fprintf(fout,"|t(34)n"); return 3; case '"': fprintf(fout,""t(35)n");return 3; case ',': fprintf(fout,",t(36)n"); return 3; case ''': fprintf(fout,"'t(37)n"); return 3;/单引号 case '&': i+; if(ai!='&') i-; fprintf(fout,"&t(38)n"); return 3; else fprintf(fout,"&&t(39)n");return 3; case '': fprintf(fout,"t(40)n"); return 3; int main()printf("*C语言实现编译原理词法分析器*nn");printf("n"); int l = 0;int m; i = 0;char input100,output100;/输入文件和输出文件的路径和文件名 printf("请输入词法分析输入的文件名(包括路径):");scanf("%s",input);printf("请输入词法分析输出的文件名(包括路径):");scanf("%s",output);fin=fopen(input,"r");fout=fopen(output,"w");if(fin=NULL)printf("打开词法分析输入文件有错n");return(1);if(fout=NULL)printf("打开词法分析输出文件有错n");return(2);/返回错误代码2printf("n-开始进行词法分析-n"); while (!feof(fin) al+ = fgetc(fin); al = '#' do m = wordanalysis(); switch (m) case -1:i+; break; case 0: i+; break; case 3: i+; break; while (m != 0);fclose(fin); fclose(fout); printf("n-词法分析执行完毕-n"); _getch(); return 0;4.上机调试时发现的问题,以及解决的过程:1)文件读取错误。运行程序后,输入文件路径后,显示“打开词法分析输入文件有错”。解决:我看了下程序,没发现什么明显错误,然后看了文件名111.txt,也是对的,点开文件属性,发现文件名显示的是111.txt.txt,意识到机房电脑默认没显示后缀,自己起名字的时候多加了一个.txt;2)运行过程中强行停止。解决:检查了一下程序,发现关键字表数组下标溢出,后来改了循环的条件。3)运行不能正常停止。解决:MS-DOS命令窗口未关闭的时候,检查输出文件是否存在,发现存在但是打开为空,然后关闭运行窗口后再打开发现输出结果已经写入了文件,只是没有执行fclose()所以打开后看不到内容。4)某些关键字被作为标识符输出。解决:检查程序发现关键字表不够完整,所以不能输出不存在于关键字表中的种别码,然后完善了关键字表。5)单词、数字、符号重复出现时,序号不一致。解决:增加了一个标识符表、数字表以及符号表,判断过词性时,先判断一下是否存在于其词性表中,然后在输出。5.所使用的测试数据及结果:5.1测试数据:5.2运行效果5.3输出结果实验总结:通过这次实验,我利用C语言做出了词性分析的程序,理解了该知识点以及学科之间的融合渗透,全面系统的理解了词性分析的具体过程。把死板的课本知识变得生动有趣,激发了学习的积极性。我学会了遇到问题独立思考,增强了自己整体的学习能力,把学过的计算机编译原理和C语言的知识强化,能够把课堂上学的知识通过自己设计的程序表示出来,加深了对理论知识的理解。专心-专注-专业