1、每调用此函数一次,从当前待编译文件中识别出一单词,并给出其类型和值。关于PL/0的说明参见第二章(清华大学吕映芝编)。2、生成一工程文件,调用1中生成的函数Getsym(),对一指定的文件进行词法分析,要求分析出单词的类型和值,对于词法错误之处,要给出错误所在位置。并将分析结果存入一文件Mydata.dat中。3、实验前请仔细阅读实验预习提示,提示中程序仅供参考。4、本实验建议上机时间4-6学时。(3)实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。本实验中,采用的是一符一种别码的
2、方式。2、单词的EBNF(扩展巴科斯范式)表示下面是对PL/0进行词法分析所用到的部份EBNF。标识符:= |下划线无符号整数加法运算符= +减法运算符= -.大于关系运算符= 大于等于关系运算符=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a+”,当前字符为,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符+,这时可知应将解释为大于运算符。但此时,超前读了一个字符+,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。4、工程文件结构由于在
3、以后的实验中,还会用到本次实验的结果。为提高代码的复用性,必须采用模块化设计的方法。本例中,用到了自编的四个文件,即Basedata.h,Symbol.h,Symbol.c,Testsym.c。其中,两个.h头文件中存放的是一些宏定义和自定义数据类型,Symbol.h中还存放有词法分析器要用到的一些自定义函数的声明。在Symbol.c中存放的是对这些函数的定义部份。Testsym.c中存放的是主函数部份,在此处调用词法分析器对待分析PL/0文件进行分析。现建一工程文件,名为test.prj,将文件Basedata.h,Symbol.h,Symbol.c,Testsym.c加入工程文件中,编译链
4、接后生成可执行文件Test.exe,运行之即可对指定的源文件进行词法分析。5、参考源程序1Basedata.h#ifndef _BASETYPE_H#define _BASETYPE_H#define FALSE 0#define TRUE 1#define SPACE 0x20#define BACKSPACE 0x08#define ENTER 0x0d#define ESC 0x1b#define TABLE 0x09 #define ENDFILE -1#endif2Symbol.h #ifndef _SYMBOL_H#define _SYMBOL_H#include stdlib.h
5、#define WORDLEN 13 /保留字个数#define MAXIDLEN 50 /标识符最长长度#define SYMBOLNUM 32 /种别码个数typedef enum SYMBOL NOL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH, ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN, RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES, BEGINSYM,ENDSYM,IFSYM,THENSYM,WHILESYM, WRITESYM,READSYM,DOSYM,CALLSYM,CONSTSYM,
6、VARSYM,PROCSYM SYMBOL;/定义种别码void Getchar(void);/取下一个字符void Getbc(void);/如当前字符为白字符,则读字符至不为白字符时停止void Concat(void);/将当前字符加入token字void Retract(void);/回退一字符int Reserve(void);/判断token字中单词是否是保留字int Getsym(void);/从当前文件中识别出一单词,并给出其类型和值void Errorsym(void);/打印错误信息3Symbol.c#include basedata.hsymbol.hconio.hstr
7、ing.hctype.hchar *WORDWORDLEN=BEGIN,CALLCONSTDO, ENDIFODDPROCEDUREREADTHENVARWHILEWRITE ;/保留字字符串表,用于将保留字种别码转为字符串输出SYMBOL WSYMWORDLEN=BEGINSYM,CALLSYM,CONSTSYM, DOSYM,ENDSYM,IFSYM,ODDSYM, PROCSYM,READSYM,THENSYM, VARSYM,WHILESYM,WRITESYM;/保留字种别码表char* SNAMESYMBOLNUM= NOLIDENTNUMBERPLUSMINUSTIMES SLAS
8、HODDSYMEQLNEQLSSLEQGTRGEQLPARENRPARENCOMMASEMICOLONPERIODBECOMESBEGINSYMENDSYMIFSYMTHENSYMWHILESYMWRITESYMREADSYMDOSYMCALLSYMCONSTSYMVARSYMPROCSYM;/单词字符串表,用于将保留字种别码转为字符串输出SYMBOL sym;/最近已识的单词种别码char tokenMAXIDLEN+1;/最近已识别的单词int num;/最近已识别的数字值char ch;/最近已识别的字符int col=1,row=1;/当前行和列值FILE *fd;/指向待编译文件ex
9、tern FILE *fout;/指向存放结果文件void Getchar(void) ch=fgetc(fd); if(ch!=EOF & ch!=n) col+; return;void Getbc(void) while(ch=SPACE |ch=TABLE |ch= if(ch=) 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);i
10、nt Reserve(void) int i,j; char temp60; j=strlen(token); for(i=0;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; Getbc();/滤掉白字符 strcpy(token,); if(isalpha(ch) /以字母开头则是标识符 num=0; Concat(); while(isalnum(ch) Co
11、ncat(); 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) /以数字开头则为无符号整数 while(isdigit(ch) flag=FALSE; while(isalnum(ch) /end of flag=FALSE/回退 if(flag)/若是无符号整数,则将整
12、数值存于num中 sym=NUMBER;num=atoi(token); /end of if isdigit switch (ch) case +Concat();sym=PLUS;break;-sym=MINUS;*sym=TIMES;/sym=SLASH;(sym=LPAREN;)sym=RPAREN;sym=EQL;#sym=NEQ;/* ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN, RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,*/,sym=COMMA;.sym=PERIOD;sym=SEMICOLON; Concat()
13、;Getchar(); if(ch!)/若后不跟,则回退 sym=GTR;Retract(); else Concat();sym=GEQ; break; sym=LSS;sym=LEQ; flag=FALSE;sym=BECOMES; default :flag=FALSE; /end of switch else char /end of else char return flag; 4Testsym.cextern char *WORDWORDLEN;extern int WSYMWORDLEN;extern char* SNAMESYMBOLNUM;extern SYMBOL sym;
14、/last readed word type;extern char tokenMAXIDLEN+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)n%10
15、s %10s %d,token,SNAMEsym,num); else if(ch!=EOF)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(); re
16、turn ; /将fd指针指向待分析源文件 if (fout = fopen(mydata.dat, wtCannot open input file.n /将fout指向文件mydata.datvoid Quit(void) fclose(fd); fclose(fout);实验二熟悉FLEX使用方法(1) 实验目的1、掌握FLEX基本使用方法2、掌握如何将通过FLEX生成的C语言模块加入到自已的程序中(2) 实验要求1、编制FLEX源程序,分别统计文本文件a.txt中出现的标识符和整数个数,并显示之。标识符定义为字母开头,后跟若干个字母,数字或下划线。整数可以带+或-号,也可不带,且不以0
17、开头。非单词和非整数则忽略不记,将之滤掉不显示。2、编制一FLEX源程序,分别求出文件hh.c中字母,数字,回车符的个数。3、思考:若main函数不在FLEX中实现,应该如何实现?4、本次实验建议学时2学时。参见附录一。在看懂的基础上将之调试通过。实验三用FLEX自动生成PL/0词法分析器熟练掌握FLEX,并通过其生成一个词法分析器1、通过FLEX生成一词法分析器函数int Getsym(),其功能同实验一中词法分析器函数类似。2、生成一工程文件,调用1中生成的函数Getsym(),对一指定的文件进行词法分析,要求分析出单词的类型和值。3、本实验建议学时4学时。1、FLEX可自动生成函数int
18、 yylex(),则int Getsym()可通过调用yylex()实现。2、由于FLEX生成的C程序模块lex.yy.c过于复杂,基本不可读,所以不要直接修改它,可将它看成一个“黑箱”,即不需要清楚知道其内部结构,只需要知道其接口即可。可通过修改FLEX源程序间接修改之。关于lex.yy.c中常用变量和函数,在附录中有详细说明。3、编制一FLEX源程序,不妨取名为sym.l,通过FLEX生成lex.yy.c,并将之加入到工程文件中。生成一工程文件,不妨取名为test.prj,将文件Symbol.c,lex.yy.c,testsym.c加入之。源程序参考如下: 同实验一中Basedata.h#
19、define WORDLEN 13 /*保留字个数*/#define MAXIDLEN 50 /*标识符最长长度*/#define SYMBOLNUM 32 /*种别码个数*/ NOL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH, BEGINSYM,ENDSYM,IFSYM,THENSYM,WHILESYM, WRITESYM,READSYM,DOSYM,CALLSYM,CONSTSYM, VARSYM,PROCSYM SYMBOL;/*定义种别码*/*判断token字中单词是否是保留字*/*从当前文件中识别出一单词,并给出其类型和值*/void MyError(void);/*打印错误信息*/3symbol.cBasedata.hSymbol.hchar *WORDWOR
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1