1、词法分析程序构造原理与实现技术 编译原理实验报告编译原理实验 词法分析程序构造原理与实现技术目录引言 3一、实验目的 3二、实验环境 3三、实验内容 3四、实验要求 4五、程序功能描述 45.1 输入输出 45.2大小写不敏感 55.3识别大多数常用程序字符 55.4注释的处理 55.5 错误检查和处理 5六、主要数据结构 6七、程序结构描述 67.1各单词符号的类别编码 67.2程序总体以及局部执行图 67.3设计方法 87.4函数定义及函数之间的调用关系 8八、程序测试 8代码附录 12引言本课程开展研究性教学的目的是,在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握
2、编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。一、实验目的1. 解决正则文法到状态转换图的转化问题2. 掌握正则文法及其状态转换图的基本概念,正则表达式及有限自动机的基本概念3. 深入理解理论对实践的指导作用:基本原理、实现技术和方法的正确运用4. 掌握正规文法构造相应的状态转换图的基本方法和正则表达式构造有限自动机的基本方法及不确定有限自动机确定化的基本方法5. 完成词法分析程序的设计与编写二、实验环境软件:操作系统:WINDOWS 8 应用软件:VC6.0三、实验内容1、教学安排
3、内容:完成以下正则文法所描述的 Pascal 语言子集单词符号的词法分析程序。字母字母数字数字数字+ * ; ()=* = : /该语言的保留字:begin end if then else for do while and or not2、在此基础上,我自己新完善了一下词法分析处理: 1)新增保留字:return break main 2)扩充可识别的标识符文法:字母数字3)新增可识别的经常使用的符号:如 = != n(t)(r)%s(%d)(%f) 等,以及数组(形如a )还有程序经常出现的,等四、实验要求1. 给出各单词符号的类别编码;2. 词法分析程序应能发现输入串中的错误;3. 词法
4、分析作为单独一遍编写,词法分析结果为二元式序列组成的中间文件;4. 设计两个测试用例(尽可能完备),并给出测试结果。五、程序功能描述5.1 输入输出输入:将事先准备好的代码录入txt中,程序将改*.txt进行词法分析 输出:在命令行中以二元组(类别码,TOKEN)显示 5.2大小写不敏感将纯字母组合中的大写字母转换成小写后,在保留字数组中查找是否是系统保留字 5.3识别大多数常用程序字符能够识别C语言中常见的n r t, %s %d %f,单引号,双引号, 逻辑运算符以及形如a的数组的符号等。5.4注释的处理1. 当输入文件中出现了/*的字符串之后,程序会自动忽略之后的输入字符串,直到遇*/,
5、但程序会输出/*2. 当输入文件中出现了/的字符串之后,程序会自动忽略之后的输入字符串,直到遇回车字符后,则判断为注释结束,但程序会输出/5.5错误检查和处理当输入串为未定义的字符时,在输出文件中显示“Error!”,如输入¥六、主要数据结构主要是利用数组,进行保留字的查询与将符合某个正则文法的字符归结到一起。七、程序结构描述7.1各单词符号的类别编码单词符号类别码单词符号类别码begin1:=23end2+24if3-25then4*26else5/27for6;28do7(29while8)30and931or1032not11数组(形如a)33return12#34break13.35m
6、ain14,36ID标识符15形如n,37INT整型16形如%s381739=18!40=19!=4120=422143=22/ | /*44 | 457.2程序总体以及局部执行图总体流程图:词法分析流程图:7.3设计方法1. 预定义好各单词符号的类别,包括保留字2. 用数组来存储识别过程中的单词字符3. 循环一个一个字符的读取与分析,若开头是字母,则判断为标识符,并将其转换为小写,然后读取完后,进行保留字比较,若是,则输出保留字的二元组;不是则输出标识符的二元组4. 开头不是字母的而是数字的,则继续读取,直到数字全读完,输出类别是整型的二元组5. 若不属于以上2中类型,则转到其他字符的判别,
7、查找宏定义中的字符,找到则输出其二元组,没有找到,则进行出错输出。7.4函数定义及函数之间的调用关系main函数中,调用fopen函数,将文本文件打开,在调用scanner_example函数进行词法分析,在分析过程中,调用lookup函数进行保留字查找,用out函数进行二元组的输出,用report_error函数来进行出错检查八、程序测试测试文件1:#includechar TOKEN20;char TOKEN120;/*sjsj*/if(strcmp(temp,keywordi)=0)/hksk x=i+1; return x; break; ¥void main() FILE *fp;
8、char filename10;/*sdsfsfs*/ while(1) printf( n r t); scanf(%s,filename); fp=fopen(filename,r);/122344 scanner_example(fp); fclose(fp); 运行截图:测试文件2:#include #include /*=宏定义部分=*/#define ID 15 /标识符#define INT 16 /整型#define LT 17 /void main() FILE *fp; char filename10; while(1) printf(n); scanf(%s,filena
9、me); fp=fopen(filename,r);/*以只读的方式打开文本文件*/ scanner_example(fp); fclose(fp); 截图:代码附录/*=头文件部分=*/#include#include#include#include #include /*=宏定义部分=*/#define ID 15 /标识符#define INT 16 /整型#define LT 17 /#define LE 18 /=#define EQ 19 /=#define NE 20 /#define GT 21 /#define GE 22 /=#define DE 23 /:=#define
10、 ADD 24 /+#define SUB 25 /-#define MUL 26 /*#define DIV 27 /#define SE 28 /;#define BL 29 /(#define BR 30 /)#define HL 31 /#define HR 32 /#define SZ 33 /形如a#define TS 34 /#define PO 35 /.#define CO 36 /,#define TX 37 /形如n#define Tx 38 /形如%s#define QU 39 / #define TH 40 /!#define BD 41 /!=#define DY
11、42 /=#define SQ 43 / #define X 44 / / #define XX 45 / /* char TOKEN20;char TOKEN120;char* keyword14=begin,end,if,then,else,for,do,while,and,or,not,return,break,main;/*=函数声明部分=*/int lookup(char *);void out(int,char *);voidscanner_example(FILE *);voidreport_error(void);/*=函数实现部分=*/*-查找保留字-*/int lookup
12、(char *temp) inti,x=15; for(i=0;i14;i+) if(strcmp(temp,keywordi)=0) x=i+1; return x; return x;/*-输出二元式-*/void out(inta,char *temp) printf( %d , %s )n,a,temp);/*-报错-*/voidreport_error(void) printf(Error!n);/*-词法分析-*/voidscanner_example(FILE *fp) charch; charstr3; inti,c; while(1) ch=fgetc(fp); if(ch=
13、EOF) break; else if(ch= |ch= ) /*跳过程序中的空格字符*/ / else if (isalpha(ch) /*开头是字母的统一归到标识符或者保留字一类*/ TOKEN0=tolower(ch); /*将大写字符转换成小写*/ TOKEN10=ch; ch=fgetc(fp); i=1; while(isalnum(ch) /*将标识符完整的读到数组TOKEN中*/ TOKENi=tolower(ch); /*将大写字符转换成小写*/ TOKEN1i=ch; i+; ch=fgetc(fp); TOKENi=0; TOKEN1i=0; if(!feof(fp) f
14、seek(fp,-1,1); c=lookup(TOKEN); if(c=15) while(1) ch=fgetc(fp); if(ch=EOF) out(ID,TOKEN1);break; else if(ch= ) out(ID,TOKEN1);break; else if(ch=) /*识别数组*/ TOKEN1i=ch; ch=fgetc(fp); i+; while(isalnum(ch) TOKEN1i=ch; i+; ch=fgetc(fp); if(ch=) TOKEN1i=ch; out(SZ,TOKEN1); break; else if(ch=_) /*识别带有下标的标
15、识符*/ TOKEN1i=ch; ch=fgetc(fp); i+; while(isalnum(ch) TOKEN1i=ch; i+; ch=fgetc(fp); TOKEN1i=0; fseek(fp,-1,1); out(ID,TOKEN1); break; else out(ID,TOKEN1);break; else out(c,TOKEN1); else if(isdigit(ch) /*识别纯数字*/ TOKEN0=ch; ch=fgetc(fp); i=1; while(isdigit(ch) TOKENi=ch;i+; ch=fgetc(fp); TOKENi=0; fsee
16、k(fp,-1,1); out(INT,TOKEN); else switch(ch)/*识别单字符分界符、双字符分界符以及一些程序中经常用到的逻辑运算符,注释(注释-统一忽略)等*/ case +: out(ADD,+);break; case -: out(SUB,-);break; case *: out(MUL,*);break; case ;: out(SE,;);break; case (: out(BL,();break; case ): out(BR,);break; case : out(HL,);break; case : out(HR,);break; case #: o
17、ut(TS,#);break; case .: out(PO,.);break; case ,: out(CO,);break; case : out(QU,);break; case : out(SQ,);break; case !:ch=fgetc(fp); /*读到!的时候,再读一个字符,如果是=,则判断为逻辑运算符!=,否则判断为普通的!*/ if(ch=)out(BD,!=); else fseek(fp,-1,1); /*多读的那一个字符要退回去,避免将下一个读错*/ out(TH,!); break; case :ch=fgetc(fp); /*读到的时候,再读一个字符,如果是n
18、或t或r,则判断为回车、换行或者制表n 或r 或t*/ str0=; if(ch=n|ch=t|ch=r) str1=ch;str2=0;out(TX,str);break; case %:ch=fgetc(fp); /*读到%的时候,再读一个字符,如果是s或d或f,则判断为输出的类型 %s 或%d 或%f*/ str0=%; if(ch=s|ch=d|ch=f) str1=ch;str2=0;out(Tx,str);break; case /: ch=fgetc(fp); /*读到/的时候,再读一个字符,如果是*,则判断为注释,跳过,一直读到结束为止;如果是/,则也为注释,读到回车就结束*/
19、 if(ch=*) out(XX,/*); while(1) ch=fgetc(fp); if(ch=*) ch =fgetc(fp); if(ch=/) break; else if(ch=/) out(X,/); while(1) ch=fgetc(fp); if(ch =n) break; else fseek(fp,-1,1); /*多读的那一个字符要退回去,避免将下一个读错*/ out(DIV,/); break; case: ch=fgetc(fp); /*读到的时候,再读一个字符,如果是=,则判断为关系运算符=,否则判断为*/ if(ch=) out(LE,)out (NE,);
20、 else fseek(fp,-1,1); /*多读的那一个字符要退回去,避免将下一个读错*/ out(LT,: ch=fgetc(fp); /*读到的时候,再读一个字符,如果是=,则判断为关系运算符=,否则判断为*/ if(ch=)out(GE,=); else fseek(fp,-1,1); /*多读的那一个字符要退回去,避免将下一个读错*/ out(GT,); break; case: ch=fgetc(fp); /*读到:的时候,再读一个字符,如果是=,则判断为定义:=,否则判断为:*/ if(ch=) out(DE,:=); break; casen:break; default:report_error(); break; return;void main() FILE *fp; char filename10; while(1) printf(n); printf(请输入要打开的文件名:); scanf(%s,filename); fp=fopen(filename,r);/*以只读的方式打开文本文件*/ scanner_example(fp); fclose(fp);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1