1、96778997973编译原理实验指导书新前言编译原理是计算机科学与技术、软件工程等专业的主干课和必修课,由于这门课程相对抽象且内容较复杂,一直是比较难学的一门课程。在编译原理的学习过程中,实验非常重要,只有通过上机实验,才能使学生对比较抽象的课程内容产生一个具体的感性认识。但是,目前国内市场上很少有较详细且比较适合我院实际的实验指导书,为此,我们特编了这份指导书,希望能对我院的编译原理教案工作有所帮助。本书实验环境主要为C环境(由于兼容性问题,建议使用Turboc2.0及一个词法分析器自动生成工具FLEX和一个语法分析器自动生成工具BISON。书中给出的参考源程序也是C源程序,但由于实验者熟
2、悉精通的语言工具不尽相同,因而强求采用统一的编程语言编程是不现实的。实验者在掌握了编译程序各个阶段的功能和原理之后,不难借助使用其他自己熟悉的语言实现相关功能。实验者在实验过程中应该侧重写出自己在算法分析、设计思路、实现功能或程序代码等方面的特色,写出设计和实现过程中遭遇到的难点和解决办法,可以不拘泥于实验指导给出的参考性设计思路,尽可能在深度和广度上加以拓展。只有这种各具特色的实验报告,才将更有利于体现实验者在创新思维和动手能力上的差异。通过这些实验,能使学生对这些部份的工作机理有一个详细的了解,达到“知其然,且知其所以然”的目的。并可在C环境下对自动生成工具生成的词法、语法分析器进行编译调
3、试。由于手工生成词法和语法分析器的工作量太大,在实际中常用自动生成工具来完成之。这些工具中最著名的当属贝尔实验室的词法分析器生成工具LEX和语法分析器生成工具YACC。它们现已成为UNIX的标准应用程序同UNIX一起发行。与此同时GNU推出与LEX完全兼容的FLEX,与YACC完全兼容的BISON。这两个程序都在Internet上以源代码的形式免费发行,所以很容易在其它操作系统下重新编译安装。我们实验采用的就是for dos的FLEX和BISON。本书有关的编译工具及其源程序例子,可到BISON的网站上下载。关于FLEX和BISON的用法简介,参见附录,如需更详细的介绍,请参阅编译工具中帮助文
4、件。关于实验学时和安排,任课教师可根据实际情况,选做其中的一部份。由于这门课实验难度较大,所以希望任课教师在实验前安排好学生的预习工作。在上机前要求学生写好实验预习报告。本书中c程序均在Turboc2.0下调试通过.LEX和YACC源程序均在FLEX和BISON下调试通过.由于编者水平有限,本书中必然存在着不少缺点,在此恳请大家给予批评和指正,我们将尽力纠正。在此特对关心支持编写本书的院系领导表示感谢。本书中关于LEX和YACC的部份大量参考引用了何炎祥老师主编,华中理工大学出版社出版的编译原理一书,在此表示衷心的感谢。周鹏杨亚会 梅琴 赵榕2006年8月实验一词法分析器设计【实验目的】1 掌
5、握生成词法分析器的方法,加深对词法分析原理的理解。2 掌握设计、编制并调试词法分析程序的思想和方法。3 本实验是高级语言程序设计、数据结构和编译原理中词法分析原理等知识的综合。【实验内容及要求】1 选择一种熟悉的高级语言 int x,a,b。 float y,c,d。x = a + b。y=c / d。if(xyx = 10。elsey=100。将该源程序的源文件经词法分析后输出以二元组形式表示的单词符号序列。3 编写的程序具有一定的查错能力。提交的实验报告中要有实验名称、实验目的、实验内容、实验程序清单、调试过程和运行结果,程序的主要部分作出功能说明,并有实验收获体会或改进意见等内容。4 实
6、验前请仔细阅读实验预习提示,提示中程序仅供参考。5 本实验建议学时数为4学时。【实验预习提示】1.词法分析器的功能和输出格式词法分析器的功能是输入以字符串表示的源程序,输出单词符号或单词符号序列。词法分析器的单词符号常常表示成以下的二元组(单词的种别码,单词符号的属性值。本实验中,采用的是一符一种种别码的方式。2.调试程序文法的EBNF扩展巴科斯范式)表示如下:= main(:= ;:=|:= =:= ifthen:= while:= := +|:= *|/:= |:= :=:= |:= |=|=|=|!=:= A|B|C|Z|a|b|c|z (要求不区分大小写:= 0|1|2|3|4|5|6
7、|7|8|93.“超前搜索”方法词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a+”,当前字符为,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符+,这时可知应将解释为大于运算符。但此时,超前读了一个字符+,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。4.词法分析程序主程序的算法思想 算法的基本思想是根据扫描到单词符号的第一个字符的种类,拼写出相应的单词符号,其实现的基本任务是从字符串表示的源程序中识别出相应的具有独立意义的单词符号。主程序示意图如图1.1
8、所示。图1.1 词法分析主程序示意图其中设置初始值包括两个方面:1)关键字表的初值关键字作为特殊标识符处理,把它们预先安排在一张表中,称这张表为关键字表,当扫描程序识别出标识符时,查关键字表,若能查找到匹配的单词,则该单词是关键字,否则为一般标识符。关键字表为一个字符串数组,其描述为:char *KEY_WORDS8=“main”,”int”, ”char”,”if”,”else”,”while”,”for”。2)程序中需要用到的主要变量为syn,token和sum。5.参考部分源程序1globals.h /*本头文件定义分析器需要的一些数据结构和宏等*/#ifndef _GLOBALS_H#
9、define _GLOBALS_H #include#include#include#define _SYN_MAIN 1#define _SYN_INT 2#define _SYN_CHAR 3#define _SYN_IF 4#define _SYN_ELSE 5#define _SYN_FOR 6#define _SYN_WHILE7/*以上为关键字的单词种别码*/#define _SYN_ID 10 /*标识符的单词种别码*/#define _SYN_NUM 11 /*整数的单词种别码*/#define _SYN_PLUS 13 /* 算术运算符“+”的单词种别码 */#define
10、_SYN_MINUS 14/* 算术运算符“-”的单词种别码 */#define _SYN_TIMES 15/* 算术运算符“*”的单词种别码 */#define _SYN_DIVIDE 16/* 算术运算符“/”的单词种别码 */#define _SYN_ASSIGN 17 /* = */#define _SYN_SEMICOLON 18 /* 。 */#define _SYN_LT 20 /* */#define _SYN_NE 21 /* != */#define _SYN_LE 22 /* */#define _SYN_ME 24 /* = */#define _SYN_EQ 25 /
11、* = */#define _SYN_LPAREN 28 /* ( */#define _SYN_RPAREN 29 /* */#define _SYN_OVER 0 /* # 即源程序结束标志*/#define MAXLENGTH 255/* 一行允许的字符个数 */union WORDCONTENT /*存放单词内容的联合*/ char T1MAXLENGTH。 int T2。 char T3。typedef struct WORD /*单词二元组*/ int syn。 union WORDCONTENT value。WORD。#endif2scan.h/*本头文件定义词法分析器的接口*/
12、#ifndef _SCAN_H#define _SCAN_H#define _TAB_LEGNTH 4/*一个TAB占用的空格数*/#define _KEY_WORD_END waiting for expanding /*关键字结束标志*/void Scaner(void。 /*函数scaner得到源程序里的下一个单词符号*/#endif3Symbol.c#include basedata.h#include symbol.h#include #include #include char *WORDWORDLEN=BEGIN,CALL,CONST,DO,END,IF,ODD,PROCEDUR
13、E, READ,THEN,VAR,WHILE, WRITE 。/保留字字符串表,用于将保留字种别码转为字符串输出SYMBOL WSYMWORDLEN=BEGINSYM,CALLSYM,CONSTSYM,DOSYM,ENDSYM,IFSYM,ODDSYM, PROCSYM,READSYM,THENSYM,VARSYM,WHILESYM,WRITESYM。/保留字种别码表char* SNAMESYMBOLNUM=NOL,IDENT,NUMBER,PLUS,MINUS,TIMES, SLASH,ODDSYM,EQL,NEQ,LSS,LEQ,GTR, GEQ,LPAREN,RPAREN,COMMA,S
14、EMICOLON, PERIOD,BECOMES,BEGINSYM,ENDSYM,IFSYM, THENSYM,WHILESYM,WRITESYM,READSYM, DOSYM,CALLSYM,CONSTSYM,VARSYM,PROCSYM。/单词字符串表,用于将保留字种别码转为字符串输出SYMBOL sym。/最近已识的单词种别码char tokenMAXIDLEN+1。/最近已识别的单词int num。/最近已识别的数字值char ch。/最近已识别的字符int col=1,row=1。/当前行和列值FILE *fd。/指向待编译文件extern FILE *fout。/指向存放结果文件v
15、oid Getchar(void ch=fgetc(fd。 if(ch!=EOF & ch!=n col+。 return。void Getbc(void while(ch=SPACE |ch=TABLE |ch=n if(ch=n row+。col=1。 Getchar(。 /为空字符则一直读至不为空字符void Retract(void fseek(fd,-1l,SEEK_CUR。 col-。void Concat(void char temp2。 temp0=ch。temp1=0。 strcat(token,temp。int Reserve(void int i,j。 char temp
16、60。 j=strlen(token。 for(i=0。i tempi=toupper(tokeni。/将当前token字以大写形式存入temp中 tempi=0。 for(i=0。i if(!strcmp(WORDi,temp break。/判断当前token是否是保留字 if(i=WORDLEN i=-1。 return i。void Errorsym(void fprintf(fout, There is error row: %5d, col: %5d, row,col。int Getsym(void int k。 int flag=TRUE。 Getchar(。 Getbc(。/滤掉
17、白字符 strcpy(token,。 if(isalpha(ch /以字母开头则是标识符 num=0。 Concat(。 Getchar(。 while(isalnum(ch Concat(。 Getchar(。 Retract(。/由于超前搜索了,所以回退一个字符 k=Reserve(。/判断此标识符是否是保留字 if(k!=-1 sym=WSYMk。/将保留字种别码存入sym中 else sym=IDENT。/将一般标识符种别码存入sym中 /end else k!=-1。 /end of if isalpha else if(isdigit(ch /以数字开头则为无符号整数 Concat
18、(。 Getchar(。 while(isdigit(ch Concat(。 Getchar(。 if(isalpha(ch flag=FALSE。 while(isalnum(ch Concat(。 Getchar(。 /end of flag=FALSE Retract(。/回退 if(flag/若是无符号整数,则将整数值存于num中 sym=NUMBER。num=atoi(token。 /end of if isdigit else num=0。 switch (ch case +:Concat(。sym=PLUS。break。 case -:Concat(。sym=MINUS。brea
19、k。 case *:Concat(。sym=TIMES。break。 case /:Concat(。sym=SLASH。break。 case (:Concat(。sym=LPAREN。break。 case :Concat(。sym=RPAREN。break。 case =:Concat(。sym=EQL。break。 case #:Concat(。sym=NEQ。break。/*ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN, RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,*/ case ,:Concat(。sym=COMMA。br
20、eak。 case .:Concat(。sym=PERIOD。break。 case 。:Concat(。sym=SEMICOLON。break。 case : Concat(。Getchar(。 if(ch!=/若后不跟=,则回退 sym=GTR。Retract(。 else Concat(。sym=GEQ。 break。 case 。Getchar(。 if(ch!= sym=LSS。Retract(。 else Concat(。sym=LEQ。 break。 case :Concat(。Getchar(。 if(ch!= flag=FALSE。Retract(。 else Concat(
21、。sym=BECOMES。 break。 default :Concat(。flag=FALSE。break。 /end of switch else char /end of else char return flag。 4Testsym.c#include basedata.h#include symbol.h#include extern char *WORDWORDLEN。extern int WSYMWORDLEN。extern char* SNAMESYMBOLNUM。extern SYMBOL sym。/last readed word type。extern char toke
22、nMAXIDLEN+1。/last readed wordextern int num。/last readed num。extern char ch。/last readed char。extern int col,row。extern FILE *fd。FILE *fout。void Init(void。void Quit(void。void main( int flag。 Init(。 fprintf(fout,n TOKEN SYM NUM。 do flag=Getsym(。 if(flag fprintf(fout,n%10s %10s %d,token,SNAMEsym,num。
23、else if(ch!=EOF fprintf(fout,n%10s,token。 Errorsym(。 while(ch!=EOF。/反复调用Getsym(识别单词,将输出结果存入fout中Quit(。/=void Init(void char temp30。 printf(nPlease input your file name:。 gets(temp。 if (fd = fopen(temp,rt = NULL fprintf(stderr, Cannot open input file %s.n,temp。 getch(。 return 。 /将fd指针指向待分析源文件 if (fou
24、t = fopen(mydata.dat, wt = NULL fprintf(stderr, Cannot open input file.n。 getch(。 return 。 /将fout指向文件mydata.datvoid Quit(void fclose(fd。 fclose(fout。实验二熟悉FLEX使用方法【实验目的】1 掌握FLEX基本使用方法2 掌握如何将通过FLEX生成的C语言模块加入到自已的程序中【实验要求】1编制FLEX源程序,分别统计文本文件a.txt中出现的标识符和整数个数,并显示之。标识符定义为字母开头,后跟若干个字母,数字或下划线。整数可以带+或-号,也可不带
25、,且不以0开头。非单词和非整数则忽略不记,将之滤掉不显示。2编制一FLEX源程序,分别求出文件hh.c中字母,数字,回车符的个数。3 思考:若main函数不在FLEX中实现,应该如何实现?4 本次实验建议学时2学时。【实验预习提示】参见附录一。在看懂的基础上将之调试通过。实验三用FLEX自动生成PL/0词法分析器【实验目的】熟练掌握FLEX,并通过其生成一个词法分析器【实验要求】1 通过FLEX生成一词法分析器函数int Getsym(,其功能同实验一中词法分析器函数类似。2 生成一工程文件,调用1中生成的函数Getsym(,对一指定的文件进行词法分析,要求分析出单词的类型和值。并将分析结果存
26、入一文件Mydata.dat中。3 本实验建议学时4学时。【实验预习提示】FLEX可自动生成函数int yylex(,则int Getsym(可通过调用yylex(实现。1 由于FLEX生成的C程序模块lex.yy.c过于复杂,基本不可读,所以不要直接修改它,可将它看成一个“黑箱”,即不需要清楚知道其内部结构,只需要知道其接口即可。可通过修改FLEX源程序间接修改之。关于lex.yy.c中常用变量和函数,在附录中有详细说明。2 编制一FLEX源程序,不妨取名为sym.l,通过FLEX生成lex.yy.c,并将之加入到工程文件中。3 工程文件结构生成一工程文件,不妨取名为test.prj,将文件Symbol.c,lex.yy.c,testsym.c加入之。源程序参考如下:1Basedata.h同实验一中Basedata.h2Symbol.h#include #include #define WORDLEN 13 /*保留字个数*/#define MAXIDLEN 50 /*标识符最长长度*/#define SYMBOLNUM 32 /*种别码个数*/typedef enum SYMBOL NOL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH, ODDSYM,EQL,NEQ,L
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1