编译原理实验简单词法分析(含源代码和实验结果).doc_第1页
编译原理实验简单词法分析(含源代码和实验结果).doc_第2页
编译原理实验简单词法分析(含源代码和实验结果).doc_第3页
编译原理实验简单词法分析(含源代码和实验结果).doc_第4页
编译原理实验简单词法分析(含源代码和实验结果).doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

附录一 实验报告样式编译原理实验报告实验2 简单词法分析姓名 陈婷婷 学号 1009050121 班级 计科1001班时间: 2012/4/5 地点:文波同 组 人:无指导教师:朱少林实验目的 通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法;掌握词法分析的实现方法;上机调试编出的词法分析程序。实验内容 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 掌握词法分析的实现方法。 上机调试编出的词法分析程序。 为简单起见,假设编译语言为具有下特征的C_minus。该词法分析器要求至少能够识别C_minus中的以下几类单词:a 关键字:else if int return void while共6个,所有的关键字都是保留字,并且必须是小写;b 标识符:识别与C语言词法规定相一致的标识符,通过下列正则表达式定义:ID = letter (letter | digit)*;c 常数:NUM=(+ | - |)digit digit*(.digit digit* |)(e(+ | - |) digit digit* |),letter = a|.|z|A|.|Z|,digit = 0|.|9,包括整数,如123, -123, +123等;小数,如123.45, +123.45, -123.45;科学计数法表示的常数,如+1.23e3,-2.3e-9;d 专用符号:+ - * / = = != = ; , ( ) /* */; 实验环境 软件:VC+6.0 实验前准备1、 方案设计: 准备模拟数据:本实验中使用 “测试文件.c” 程序思想:该实验要识别关键字、标识符、常数、专用符号(分界符、算术运算符和关系运算符)。对于关键字本实验主要识别10个(break、do、else float if int for switch main char) ,使用的数据结构为:struct Key/用于关键字和标识符及常数,由于常数有科学计数法的表示,所以该实验中把常数当做字符串进行检测输出 char name20; int i; int t; ; Key keyword10;/存放10个关键字然后在函数void initial()对Key keyword10进行初始化。函数int search_key(char *teststring, FILE *f)用来将识别到的以字母开头的字符串teststring与定义的关键字一一比较,如果是关键字则把它写入文件f中,否则在检验是否是标识符;如果是关键字则返回1,否则返回0.对与标识符和常数,使用的数据结构是一样的,这是因为识别一个标识符和识别一个常数都是要读入多个字符才能识别一个完整的,而且标识符表和常数表都是在识别过程中建立的,都所以用到的数据结构为:struct Key/用于关键字和标识符及常数 char name20; int i; int t; ; struct key_infor/记录标识符表,常数表的相关信息struct Key *head;int key_length; ;识别到一个以字母开头的符号串后如果不是关键字,就调用void search_table(char *teststring, key_infor *p, FILE *f)与已经识别到的标识符一一比较,如果是新的则赋予新的i值并打印输出到屏幕并且写入f中(只要是标志符就写入文件f中)。Main()中将识别到的标识符(不重复)写入另外的文件中。search_table中关键部分如下:while( jkey_length+; pointj.i=j; pointj.t=6;识别到一个完整的常数则进行与标识符相似的处理,void search_number(char *teststring, key_infor *p, FILE *f)的思想与void search_table(char *teststring, key_infor *p, FILE *f)的基本一致。Main()中将识别到的常数(不重复)写入另外的文件中。如果既不是字母开头也不是数字开头,则调用void search_sign(char x, FILE *file, FILE *f),该函数实现对专用符号的识别,并把识别到的专用符号写入文件f中。该实验有六个输出文件,存放输出结果。其中与标志符相关的有两个,一个存放识别到的所有标识符(有重复,即测试文件中的所有标识符),一个存放不重复的(重复的只存一次),与常数相关的文件类似也2个,另外的的两个分别存放识别到的专用符号和关键字。2、 程序设计#include stdio.h#include stdlib.h#include string.h struct Key/用于关键字和标识符及常数,由于常数有科学计数法的表示,所以该实验中把常数当做字符串进行检测输出 char name20; int i; int t; ; Key keyword10;/存放10个关键字 struct key_infor/记录标识符表,常数表的相关信息struct Key *head;int key_length; ; struct op/用于除关系运算符以外的专用符号 char mark; int ii; int tt; ; op seperateop8 ; op mathop4; struct reop/用于除关系运算符以外的专用符号 char remark3; int iii; int ttt; ; reop relatop8; char a10=,;,.,=,(,),;/分界符 char b4=+,-,*,/;/算术运算符 char signal84=,=,=,!=; void initial()/初始化关键字表 分界符表 算术运算符表 关系运算符表 for(int j=0; j10;j+)/初始化关键字表keywordj.t=1;keywordj.i=j;strcpy(,break);strcpy(,do);strcpy(,else);strcpy(,float);strcpy(,if);strcpy(,int);strcpy(,for);strcpy(,switch);strcpy(,main);strcpy(,char);printf(以下是可以识别的关键字内部表示n);printf(关键字 i值 t值n);for(int k=0;k10;k+)printf(%st,);printf(%dt,keywordk.i);printf(%dn,keywordk.t); for(int m=0;m10;m+)/初始化分界符表 seperateopm.mark=am;seperateopm.ii=m;seperateopm.tt=2; printf(以下是可以识别的分界符内部表示n);printf(分界符 i值 t值n);for(int n=0;n10;n+)printf(%ct,seperateopn.mark);printf(%dt,seperateopn.ii);printf(%dn,seperateopn.tt); for(int p=0;p4;p+)/初始化算术运算符表 mathopp.mark=bp;mathopp.ii=p+16;/先用十进制表示?mathopp.tt=3; printf(以下是可以识别的算术运算符内部表示n);printf(算术运算符 i值 t值n);for(int q=0;q4;q+)printf(%ctt,mathopq.mark);printf(%dt,mathopq.ii);/查如何用十六进制输出?printf(%dn,mathopq.tt); for(int r=0;r8;r+)/初始化关系运算符表 strcpy(relatopr.remark,signalr);relatopr.iii=r;/这里用十进制表示?relatopr.ttt=4; printf(以下是可以识别的关系运算符内部表示n);printf(关系运算符 i值 t值n);for(int s=0;s8;s+)printf(%stt,relatops.remark);printf(%dt,relatops.iii);/查如何用十六进制输出?printf(%dn,relatops.ttt); int search_key(char *teststring, FILE *f)/设置返回值用于确定是否需要检验是不是标识符/检测是否为关键字,如果是则写入关键字文件中int j=0; int i=10;while( jkey_length;/i记录标识符表的长度int j=0; Key *point;point=p-head;while( jkey_length+; pointj.i=j; pointj.t=6;printf(%s是标志符,i=%d,t=%dn,,pointj.i,pointj.t); fprintf(f,%st%5dt%5dn,,pointj.i,pointj.t);/将新的标识符写入标识符文件f中return ;void search_number(char *teststring, key_infor *p, FILE *f)/查填常数表函数,p为指向结构体的指针int i=p-key_length;/i记录常数表的长度int j=0; Key *point;point=p-head;while( jkey_length+; pointj.i=j; pointj.t=5;printf(%s是常数,i=%d,t=%dn,,pointj.i,pointj.t); fprintf(f,%st%5dt%5dn,,pointj.i,pointj.t);/将新的常数写入文件f中return ; Void search_sign(char x, FILE *file, FILE *f) /检测是否为专用符号int j=0;char temp=x;while( j10 & x!=seperateopj.mark)/检测是否为分界符j+;/与定义的8个分隔符一一比较if(j10)/是分隔符printf(%c是分界符,i=%d,t=%dn,seperateopj.mark,seperateopj.ii,seperateopj.tt); fprintf(f,%ct %dt %dn,seperateopj.mark,seperateopj.ii,seperateopj.tt);/将识别到的分隔符写入文件f中 else /不是分界符,就把j赋值0,与算术运算符比较j=0;while( j4&x!=mathopj.mark) j+;/与定义的4个算术运算符一一比较 if(j:x=fgetc(file);if (x=) printf(%s是关系运算符,i=%d,t=%dn,relatop4.remark,relatop4.iii,relatop4.ttt); fprintf(f,%st %dt %dn,relatop4.remark,relatop4.iii,relatop4.ttt);/将识别到的关系运算符写入文件f中 break;elsefseek(file,-1L,SEEK_CUR);x=temp; printf(%s是关系运算符,i=%d,t=%dn,relatop3.remark,relatop3.iii,relatop3.ttt); fprintf(f,%st %dt %dn,relatop3.remark,relatop3.iii,relatop3.ttt);/将识别到的关系运算符写入文件f中break; case)printf(%s是关系运算符,i=%d,t=%dn,relatop5.remark,relatop5.iii,relatop5.ttt); fprintf(f,%st %dt %dn,relatop5.remark,relatop5.iii,relatop5.ttt);/将识别到的关系运算符写入文件f中 break; elsefseek(file,-1L,SEEK_CUR); x=temp;printf(%s是关系运算符,i=%d,t=%dn,relatop0.remark,relatop0.iii,relatop0.ttt); fprintf(f,%st %dt %dn,relatop0.remark,relatop0.iii,relatop0.ttt);/将识别到的关系运算符写入文件f中 break;case=:x=fgetc(file);if(x=)printf(%s是关系运算符,i=%d,t=%dn,relatop6.remark,relatop6.iii,relatop6.ttt); fprintf(f,%st %dt %dn,relatop6.remark,relatop6.iii,relatop6.ttt);/将识别到的关系运算符写入文件f中 break;elsefseek(file,-1L,SEEK_CUR); x=temp;printf(%s是关系运算符,i=%d,t=%dn,relatop2.remark,relatop2.iii,relatop2.ttt); fprintf(f,%st %dt %dn,relatop2.remark,relatop2.iii,relatop2.ttt);/将识别到的关系运算符写入文件f中break;case!:x=fgetc(file); if(x=) printf(%s是关系运算符,i=%d,t=%dn,relatop7.remark,relatop7.iii,relatop7.ttt); fprintf(f,%st %dt %dn,relatop7.remark,relatop7.iii,relatop7.ttt);/将识别到的关系运算符写入文件f中 break; return; void main() char readchar; char teststr20;/存放标识符 char linkstr2=0;/用于把字符readchar连接到teststr initial(); FILE *key_result;/新建并打开关键字结果.txt文件key_result=fopen(关键字结果.txt,w+); fprintf(key_result,关键字t i值 t值n);FILE *table_result;/新建并打开文件table_result=fopen(标识符结果.txt,w+);fprintf(table_result,标识符t i值 t值n);key_infor information;/用于指向符号表Key mark400;/定义符号表最多可以有400个符号information.head=mark;information.key_length=0; key_infor numinformation;/用于指向常数表Key nummark400;/定义符号表最多可以有400个符号numinformation.head=nummark;numinformation.key_length=0;FILE *sign_result;/新建并打开专用符号结果.txt文件sign_result=fopen(专用符号结果.txt,w+); fprintf(sign_result,专用符号ti值tt值n);FILE *number_result;/新建并打开常数结果.txt文件number_result=fopen(常数结果.txt,w+); fprintf(number_result,常数t i值 t值n); FILE *fp; fp=fopen(测试文件.c,r);if (fp=NULL)printf(打开文件失败!);exit(0);/打开测试文件fp readchar=fgetc(fp);while(readchar!=EOF) teststr0=0;if(readchar=a|readchar=A& readchar=Z)/第一个是字母转向关键字与标识符 while(readchar=a|readchar=A& readchar=0& readchar=48&readchar=48&readchar=48&readchar=48&readchar=57) linkstr0=readchar; strcat(teststr,linkstr);/会自动添加0 readchar=fgetc(fp);search_number(teststr, &numinformation,number_result ); else/判断是否为专用运算符 search_sign(readchar, fp, sign_result); readchar=fgetc(fp); fclose(fp);/关闭测试文件 fclose(key_result);/关闭关键字文件fclose(table_result);/关闭标识符文件 fclose(sign_result); FILE *table=fopen(符号表.txt,w+);/新建符号表.txt文件 fprintf(table,标识符t i值 t值n); if(table=NULL) printf(文件打开失败!);exit (0); int i=0; while(iinformation.key_length) fprintf(table,%st%5dt%5dn,,marki.i,marki.t);/把识别到的标识符写入符号表.txt文件 i+; fclose(table); FILE *NUMBER=fopen(常数表.txt,w+);/新建常数表.txt文件 fprintf(NUMBER,常数t i值 t值n); if(NUMBER=NULL) printf(文件打开失败!);exit (0); int p=0; while(pnuminformation.key_length) fprintf(NUMBER,%st%5dt%5dn,,nummarkp.i,nummarkp.t);/把识别到的标识符写入符号表.txt文件 p+; fclose(NUMBER); 实验步骤将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见下图。图 词法分析程序流程图标识符的正规式定义和确定的有限自动机见实验一常数的正规式定义:NUM=(+ | - |)digit digit*(.digit digit* |)(e(+ | - |) digit digit* |),letter = a|.|z|A|.|Z|,digit = 0|.|9化简后的确定的有限自动机如下:实验结果及其分析: 关键字结果.txt(用于存放识别到的关键字)内容如下:关键字 i值 t值int 5 1int 5 1int 5 1int 5 1char 9 1int 5 1char 9 1char 9 1main 8 1char 9 1int 5 1char 9 1if 4 1else 2 1int 5 1char 9 1char 9 1int 5 1for 6 1if 4 1 标识符结果.txt(存放识别到的所有标识符) 标识符 i值 t值include 0 6stdio 1 6h 2 6qq 3 6temp 4 6temp 4 6s 5 6search 6 6str 7 6c 8 6void 9 6str 7 6c 8 6m 10 6i 11 6printf 12 6please 13 6input 14 6a 15 6string 16 6gets 17 6str 7 6puts 18 6please 13 6input 14 6the 19 6you 20 6search 6 6c 8 6getchar 21 6m 10 6search 6 6str 7 6c 8 6m 10 6printf 12 6can 22 6not 23 6find 24 6printf 12 6the 19 6c 8 6you 20 6search 6 6is 25 6d 26 6n 27 6m 10 6search 6 6str 7 6c 8 6i 11 6i 11 6str 7 6i 11 6i 11 6str 7 6i 11 6c 8 6return 28 6i 11 6return 28 6 符号表.txt(存放识别到的标识符,没有重复) 标识符 i值 t值include 0 6stdio 1 6h 2 6qq 3 6temp 4 6s 5 6search 6 6str 7 6c 8 6void 9 6m 10 6i 11 6printf 12 6please 13 6input 14 6a 15 6string 16 6gets 17 6puts 18 6the 19 6you 20 6getchar 21 6can 22 6not 23 6find 24 6is 25 6d 26 6n 27 6return 28 6 常数结果.txt(存放识别到的所有常数) 常数 i值 t值1.2e+1 0 5123.45 1 5123.45 1 5123.45 1 5123 2 5123 2 5123 2 53 3 51.23e3 4 52.3e-9 5 580 6 580 6 51 7 580 6 50 8 50 8 51 7 5常数表.txt(存放不重复的常数) 常数 i值 t值1.2e+1 0 5123.45 1 5123 2 53 3 51.23e3 4 52.3e-9 5 580 6 51 7 50 8 5专用符号结果.txt(存放识别到的所有专用符号)专用符号i值t值 3 4; 1 2= 4 4; 1 2 5 4; 1 2= 3 2; 1 2 3 4; 1 2= 3 2= 3 2; 1 2, 0 2+ 16 3, 0 2- 17 3; 1 2, 0 2- 17 3, 0 2+ 16 3; 1 2+ 16 3- 17 3; 1 2( 4 2 8 2 9 2, 0 2) 5 2; 1 2( 4 2) 5 2 6 2 8 2 9 2, 0 2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论