收藏 分销(赏)

C语言的词法分析器.doc

上传人:二*** 文档编号:4519552 上传时间:2024-09-26 格式:DOC 页数:23 大小:166KB
下载 相关 举报
C语言的词法分析器.doc_第1页
第1页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

1、南华大学计算机科学与技术学院 实验报告1. 实验目的及要求1、 目的通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。2、 要求l 根据具体情况,由同学们自己选取C语言的一个适当大小的子集(可取一类典型单词,也可以尽可能使各种类型的单词都兼顾到);在实习前一定要制出相应的表。l 实验时间:4-8学时l 检查内容及时间:A)完整的实验报告。 B)在机器上调试成功的源程序。3、 软件、硬件环境l Visual studio 2010 ,Windows 7操作系统l 计算机一台2.实验步骤l 分析对于单词

2、符号我们将其分成四类:保留字、标识符、常数和界符,每类单词符号均可使用一张表格表示在词法分析过程中,保留字和界符这两个表格的内容是固定不变的(由语言确定),源程序字符串只能从其中选取,而标识符、常数这两表是在分析过程中不断形成的对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是、或中之一,那么就以单词的二元式形式输出每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串各类单词的二元式表述均具有相同的结构与长度,形式如下:(单词种别,单词自身的值)是单词种别,而单词种别共分为、四类且每类对应一张表格因此,实际上就是一

3、个指向这四类中某一类对应表格的指针则为指向该类表格中一个特定项目的指针所以整个的词法分析过程就是从源程序中获得一个个的单词符号,将这些符号分别填入四张类表中,并且有一个二元式序列构成一个索引,这个索引为以后的语法分析提供处理上的方便为了减少实习量,可以适量地选取,中的一个子集来进行如下表:表1保留字表内部地址 12345678910保 留 字 forwhileDOELSEIF STATICINTSIZEOFBREAKCONTINUE表2界符表内部地址 123456789101112131415161718界符 +-*/=!=(),:;表3 单词符号的编码单词符号类别编码标识符1常数2保留字3+

4、4-5*6/7810=11!=12=13=14(15)16,17:18;192021保留字表包括10个有代表性的保留字,界符表包括关系运算符,算术运算符,分隔符三种,一对圆括号,加上赋值号,花括号,分号,引号这两表的内容表明C语言的条件语句,赋值语句,WHILE型循环语句,复合语句,过程及变量说明均可作为源程序例子输入给词法分析程序,标识符表中的每一项包含一个标识符,常数表中的每一项包含一个整常数,后两表的内容都是在词法分析过程中产生的如何从源程序中识别出一个个的单词符号呢?图1中的流图清晰地反映出这一过程图1中,双圆圈的状态表示终态,即能到达终态就代表识别出一个单词符号,而带有号的终态是指处

5、理时应回退一字符l 算法词法分析器在扫描过程中,依次从源程序中取出源字符,根据图1的扫描过程状态转换图,当碰到终态时,即双圆圈的状态时就得到一个单词符号,此时可以根据第一个字符判断单词属于K,I,C,P中哪一个类,从而确定单词的“单词种别”和“单词自身的值”。2字母非字母与数字1字母与数字0空白4数字非数字3数字+6;58:非=7=9(10,11)12其它171416=图1扫描程序的状态转换图 说明:这个图只是大概表达一个词法分析的思路,由于不知道加入,所以并不完全准确。2. 实验内容 流程图 、程序其它界符数字字母出错处理有C表有此单词否?形成一项无形成(C,i)十进制数转化成二进制数K表有

6、此单词否?形成(I,i)形成(K,i)有无查界符表形成(P,i)源程序完否?输出二元式开始开始对源程序扫描扫描到的单词符号首字母是什么?完未完图2词法分析算法流图源程序#include #include #include #include #include #define LENGTH1 10 /定义保留字的大小FILE * fp=NULL; /输出流指针FILE * fw=NULL; /输入流指针char character; /字符char token16; /字符数组,用来存放已读入的字符序列/编码表char* CODE=identifier/*标识符*/,constant/*常数*/,

7、keyword/*保留字*/,+,-,*,/,=,!=,=,=,(,),:,;,;/保留字表char *k=for,while,do,else,if,static,int,sizeof,break,continue;/标识符结构体typedef structchar * I256; /标识符数组int len;/标识符数量 identifier; /常量结构体typedef struct int cont300;/存放常量的数组int len;/常量的数目 constnumber;/读入一个字符,从输入流中读入一个字符到变量character中。void getNextChar(FILE *i

8、fp)if(character=getc(ifp)=EOF)exit(1);/读入非空白字符,检查变量character中的字符是否为空白字符或回车或换行符。若是,/则调用getNextChar()读入下一个字符,直到character中的字符满足条件.void getnbc(FILE *ifp)while(character= | character=n|character=9)getNextChar(ifp);/连接字符串,把character中的字符连接到token数组的结尾。void concat()char * ct=&character;strcat(token,ct);/判断是否

9、为字母。int letter()return isalpha(character);/判断是否为数字int digit()return isdigit(character);/回退字符,将刚读入的character中的字符回退到输入流中。并把character中的值置为空。void retract(FILE *ifp)(ifp-_cnt)+;(ifp-_ptr)-;character= ;/处理保留字,对存放在token中的字符串查保留字,若查到,则返回该保留字的类别编码,否则返回0.int reserve(char *k)int i;for(i=0;iLENGTH1;i+)if(strcmp

10、(token,ki)=0)return i+1;return 0;/处理标识符,对存放在token中的字符串查找符号表,若查到,则返回它在符号表的位置,/存入常数表中,并返回它在常数表中的位置编号。int symbol(identifier * id)int i;for(i=0;ilen;i+)if(strcmp(token,id-Ii)=0)return i+1;if(id-len256)assert(0);id-Iid-len=token;id-len+;return id-len;/将数字字符串转化为整数。int strtonumber()int i;int sum=0;for(i=0;

11、icontcon-len=strtonumber();con-len+;return con-len;/将整数值转化为字符串char * numbertoString(int num)char s3;int i=num/10;while(i0)char c=i+0;strcat(s,&c);return s;/将结果写入到文件并且输出到屏幕。void returntofile(int num,int val,identifier *id,constnumber *con)int i;int _num=num;char c;c=(;putc(c,fw);printf(%c,c);i=_num/1

12、0;while(i0) _num=_num-10*i;c=(i+0);printf(%c,c);putc(c,fw);i=_num/10;c=_num+0;printf(%c,c);putc(c,fw);printf(,);putc(,fw);/如果是标识符或常数 则放入括号内。if(num=1) /处理标识符printf(%s,id-Ival-1);printf();printf(n);fputs(id-Ival-1,fw);putc(),fw);putc(n,fw);if(num=2) /处理常数_num=con-contval-1;i=_num/10;while(i0)_num=_num

13、-10*i;c=(i+0);printf(%c,c);putc(c,fw);i=_num/10;c=_num+0;printf(%c,c);printf();printf(n);putc(c,fw);putc(),fw);putc(n,fw);if(num=3) /保留字printf(-);printf();printf( );printf(#);printf(%s,kval-1);printf(#);printf(n);putc(-,fw);putc(),fw);fputs( ,fw);putc(#,fw);fputs(kval-1,fw);putc(#,fw);putc(n,fw);if(

14、num3) /处理界符printf(-);printf();printf( );printf(#);printf(%s,CODEnum-1);printf(#);printf(n);putc(-,fw);putc(),fw);fputs( ,fw); putc(#,fw);fputs(CODEnum-1,fw);putc(#,fw);putc(n,fw);/将错误写入到文件或输出到屏幕void error()printf(ERROR,);printf(%c,character);printf();printf(n);fputs(ERROR,fw);putc(character,fw);putc

15、(),fw);putc(n,fw);/词法分析函数void LexAnalyze(char *k,char *CODE,identifier *id,constnumber *con,FILE *fp,FILE *fw)int num,val;strcpy(token,);getNextChar(fp);getnbc(fp);switch(character)case a:case b:case c:case d:case e:case f:case g:case h:case i:case j:case k:case l:case m:case n:case o:case p:case q:

16、case r:case s:case t:case u:case v:case w:case x:case y:case z:case A:case B:case C:case D:case E:case F:case G:case H:case I:case J:case K:case L:case M:case N:case O:case P:case Q:case R:case S:case T:case U:case V:case W:case X:case Y:case Z:while(letter()|digit()concat();getNextChar(fp);retract(

17、fp);num=reserve(k);/保留字if(num!=0) returntofile(3,num,id,con);else val=symbol(id);returntofile(1,val,id,con);break;case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:while(digit()concat();getNextChar(fp);retract(fp);val=constant(con);returntofile(2,val,id,con);break;case :getNextCh

18、ar(fp);if(character=)returntofile(11,0,id,con);elseretract(fp);returntofile(10,0,id,con);break;case =:getNextChar(fp);if(character=)returntofile(13,0,id,con);elseretract(fp);returntofile(14,0,id,con);break;case !:getNextChar(fp);if(character=)returntofile(12,0,id,con);elseerror();break;case +:return

19、tofile(4,0,id,con);break;case -:returntofile(5,0,id,con);break;case *:returntofile(6,0,id,con);break;case /:returntofile(7,0,id,con);break;case (:returntofile(15,0,id,con);break;case ):returntofile(16,0,id,con);break;case ,:returntofile(17,0,id,con);break;case :returntofile(18,0,id,con);break;case ;

20、:returntofile(19,0,id,con);break;case :returntofile(20,0,id,con);break;case :returntofile(21,0,id,con);break;default:error();main(int argc,char *argv)/初始化标识符和常数结构体identifier* id=(identifier*)malloc(sizeof(identifier);constnumber * con=(constnumber*)malloc(sizeof(constnumber);con-len=0; id-len=0;argc

21、=3;argv1=E:file1.txt;/待分析的文件argv2=E:file2.txt;/保存分析结果的文件/从打开目标文件流if(fp=fopen(argv1,r)=NULL)printf(cat: cant open %sn,*argv);return 1;/打开要写二元式的文件流if(fw=fopen(argv2,w)=NULL)printf(cat:cant open %sn,argv2);return 1;while(!feof(fp)LexAnalyze(k,CODE,id,con,fp,fw);/执行词法分析/关闭流fclose(fp);fclose(fw); return

22、0;4.实验结果要分析的C语言程序(1) int i=0,sum=0;while(i10)sum=sum+i;i=i+1;结果为:(3,-) #int#(1,i)(14,-) #=#(2,0)(17,-) #,#(1,sum)(14,-) #=#(2,0)(19,-) #;#(3,-) #while#(15,-) #(#(1,i)(8,-) #0)char c=i+0;strcat(s,&c);return s;结果为:(1,char)(1,s)(ERROR,)(2,3)(ERROR,)(19,-) #;#(3,-) #int#(1,i)(14,-) #=#(1,num)(7,-) #/#(2

23、,10)(19,-) #;#(3,-) #while#(15,-) #(#(1,i)(10,-) #(2,0)(16,-) #)#(20,-) #(1,char)(1,c)(14,-) #=#(1,i)(4,-) #+#(ERROR,)(2,0)(ERROR,)(19,-) #;#(1,strcat)(15,-) #(#(1,s)(17,-) #,#(ERROR,&)(1,c)(16,-) #)#(19,-) #;#(21,-) #(1,return)(1,s)(19,-) #;#5. 实验总结分析上机前应做好准备即根据实习目的、要求和分析,选择相应的数据结构,使用语言参照算法中的流程编写词法

24、分析的程序将编好的程序上机进行调试注意调试的例子应有词法正确的,也应有词法错误的或是超出所选数据结构范围的现在我谈一下关于做这个词法分析程序的心得。这个词法分析程序是全部用C语言的语法写的,幸亏我以前学过C语言。我认为C语言是很好的语言。这次写这个程序算是对我所学的C语言的一次的检验。在写程序的过程中,也遇到了一些问题,最主要的是文件的输入与输出,最头疼的是指针。几乎所在的错误都与指针有关。在遇到问题以后,我们不要畏惧,我们可以通过程序调试,找出问题的所在,只要找到问题的源,就总在解决它的办法。 在这个分析程序中,我加了注释,是很容易看懂的,而且程序的功能模块也分得很清楚。在写大型的程序时,这

25、两点我认为是非常重要的。附录资料:不需要的可以自行删除Abstract: Based on the comprehensive analysis on the plastic parts structure service requirement, mounding quality and mould menu factoring cost. A corresponding injection mould of internal side core pulling was designed. By adopting the multi-direction and multi-combinati

26、on core-pulling. A corresponding injection mould of internal side core pulling was designed, the working process of the mould was introducedC语言详解 - 枚举类型注:以下全部代码的执行环境为VC+ 6.0在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,您的代码可能是:#define MON 1#define TUE 2#define WED 3#define THU 4#define FRI 5#define

27、 SAT 6#define SUN 7在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。1. 定义一种新的数据类型 - 枚举型 以下代码定义了这种新的数据类型 - 枚举型enum DAY MON=1, TUE, WED, THU, FRI, SAT, SUN;(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。(4) 可以人为设定枚举成员的值,从而自定义某个范围

28、内的整数。(5) 枚举型是预处理指令#define的替代。(6) 类型定义以分号;结束。2. 使用枚举类型对变量进行声明新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型,如:整型int, 单精度浮点型float, 双精度浮点型double, 字符型char, 短整型short等等。用这些基本数据类型声明变量通常是这样:char a; /变量a的类型均为字符型charchar letter;int x, y, z; /变量x,y和z的类型均为整型intint number;double m, n;double result; /变量result的类型为双精度浮点型double

29、既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。方法一:枚举类型的定义和变量的声明分开enum DAY MON=1, TUE, WED, THU, FRI, SAT, SUN;enum DAY yesterday;enum DAY today;enum DAY tomorrow; /变量tomorrow的类型为枚举型enum DAYenum DAY good_day, bad_day; /变量good_day和bad_day的类型均为枚举型enum DAY方法二:类型定义与变量声明同时进行:enum /跟第一个定义不同的是,此处的标号DAY省略,这是允许的。 satur

30、day, sunday = 0, monday, tuesday, wednesday, thursday, friday workday; /变量workday的类型为枚举型enum DAYenum week Mon=1, Tue, Wed, Thu, Fri Sat, Sun days; /变量days的类型为枚举型enum weekenum BOOLEAN false, true end_flag, match_flag; /定义枚举类型并声明了两个枚举型变量方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:typedef enum workday satur

31、day, sunday = 0, monday, tuesday, wednesday, thursday, friday workday; /此处的workday为枚举型enum workday的别名workday today, tomorrow; /变量today和tomorrow的类型为枚举型workday,也即enum workdayenum workday中的workday可以省略:typedef enum saturday, sunday = 0, monday, tuesday, wednesday, thursday, friday workday; /此处的workday为枚

32、举型enum workday的别名workday today, tomorrow; /变量today和tomorrow的类型为枚举型workday,也即enum workday也可以用这种方式:typedef enum workday saturday, sunday = 0, monday, tuesday, wednesday, thursday, friday;workday today, tomorrow; /变量today和tomorrow的类型为枚举型workday,也即enum workday注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。错误

33、示例如下所示:错误声明一:存在同名的枚举类型typedef enum wednesday, thursday, friday workday;typedef enum WEEK saturday, sunday = 0, monday, workday; 错误声明二:存在同名的枚举成员typedef enum wednesday, thursday, friday workday_1;typedef enum WEEK wednesday, sunday = 0, monday, workday_2;3. 使用枚举类型的变量3.1 对枚举型的变量赋值。实例将枚举类型的赋值与基本数据类型的赋值进

34、行了对比:方法一:先声明变量,再对变量赋值#include/* 定义枚举类型 */enum DAY MON=1, TUE, WED, THU, FRI, SAT, SUN ;void main() /* 使用基本数据类型声明变量,然后对变量赋值 */ int x, y, z; x = 10; y = 20; z = 30; /* 使用枚举类型声明变量,再对枚举型变量赋值 */ enum DAY yesterday, today, tomorrow; yesterday = MON; today = TUE; tomorrow = WED; printf(%d %d %d n, yesterda

35、y, today, tomorrow);方法二:声明变量的同时赋初值#include /* 定义枚举类型 */enum DAY MON=1, TUE, WED, THU, FRI, SAT, SUN ;void main() /* 使用基本数据类型声明变量同时对变量赋初值 */ int x=10, y=20, z=30; /* 使用枚举类型声明变量同时对枚举型变量赋初值 */ enum DAY yesterday = MON, today = TUE, tomorrow = WED; printf(%d %d %d n, yesterday, today, tomorrow);方法三:定义类型的同时声明变量,然后对变量赋值。#include /* 定义枚举类型,同时声明该类型的三个变量,它们都为全局变量 */enum DAY MON=1, TUE, WED, THU, FRI, SAT, SUN

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服