编译原理词法分析

  • 格式:docx
  • 大小:189.60 KB
  • 文档页数:13

编译原理实验词法分析姓名:***学号:********** 专业年级:创新实验111 指导老师:**1.实验目的及要求1、目的通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

2、要求●根据具体情况,由同学们自己选取C语言的一个适当大小的子集(可取一类典型单词,也可以尽可能使各种类型的单词都兼顾到);在实习前一定要制出相应的表。

●实验时间:9学时●检查内容及时间:A)完整的实验报告。

B)在机器上调试成功的源程序。

3、软件、硬件环境●C-Free5.0 ,Windows 7操作系统●计算机一台2.实验步骤●分析对于单词符号我们将其分成四类:保留字K、标识符I、常数C和界符P,每类单词符号均可使用一张表格表示.在词法分析过程中,保留字K和界符P这两个表格的内容是固定不变的(由语言确定),源程序字符串只能从其中选取,而标识符I、常数C这两表是在分析过程中不断形成的.对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是K、I、C或P中之一,那么就以单词的二元式形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串.各类单词的二元式表述均具有相同的结构与长度,形式如下:(单词种别t,单词自身的值i)t是单词种别,而单词种别共分为标识符,保留字,整数,长整数,浮点数,符号6类组成.所以整个的词法分析过程就是从源程序中获得一个个的单词符号,将这些符号分别填入四张类表中,并且有一个二元式序列构成一个索引,这个索引为以后的语法分析提供处理上的方便.为了减少实习量,可以适量地选取C语言中的一些常见的保留字的子集来进行.如下表:保留字表单词符号编码保留字表包括30个常见的保留字,界符表包括关系运算符,算术运算符,分隔符三种,一对圆括号,加上赋值号,花括号,分号,引号.这两表的内容表明C语言的条件语句,赋值语句,WHILE 型循环语句,复合语句,过程及变量说明均可作为源程序例子输入给词法分析程序,标识符表I中的每一项包含一个标识符,常数表C中的每一项包含一个整常数,后两表的内容都是在词法分析过程中产生的.如何从源程序中识别出一个个的单词符号呢?图1中的流图清晰地反映出这一过程.图1中,双圆圈的状态表示终态,即能到达终态就代表识别出一个单词符号,而带有*号的终态是指处理时应回退一字符.算法词法分析器在扫描过程中,依次从源程序中取出源字符,根据图1的扫描过程状态转换图,当碰到终态时,即双圆圈的状态时就得到一个单词符号,此时可以根据第一个字符判断单词属于6类中哪一个类,从而确定单词的“单词种别”和“单词自身的值”。

数字源程序#include<stdio.h> #include<string.h> #include <iostream.h> FILE * fp=NULL; FILE * fw=NULL; char token[16];3点4131416!=非=2字母非字母与数字1字母或数字或_空白4数字非数字3 数字所有单个字符6其它同理1714<=1316非=图1 扫描程序的状态转换图char ch;int number,count,p,m=0,sum=0;char*keyword[30]={"include","define","int","float","double","for","if ","else","void","struct","char","return","sizeof","true","flase","boolean","typedef","exte rn","break","continue","swtich","signed","unsigned","case","default", "printf","scanf","do","while","NULL"};//获取字符串void getNextChar(FILE *ifp){if((ch=getc(ifp))==EOF)exit(1);if(ch==92)//"\"阿斯科马{getNextChar(ifp);if(ch=='n')getNextChar(ifp);}}void getnbc(FILE *ifp){while(ch==' '|| ch=='\n'||ch==9){getNextChar(ifp);}}void retract(FILE *ifp)//回退符{(ifp->_cnt)++;//没看懂(ifp->_ptr)--;//ch=' ';}void scanner()//分别判断标识符或保留字整数或浮点数运算符或分隔符或特殊字符{for(int i=0;i<16;i++)token[i]=NULL;//ch=wenben[p++];getNextChar(fp);getnbc(fp);if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){count=0;while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9 ')||(ch=='_')){token[count++]=ch;//ch=wenben[p++];getNextChar(fp);}//token[count++]='\0';retract(fp);number=1;for( int i=0;i<30;i++)if(strcmp(token,keyword[i])==0){number=5;break;}}else if(ch>='0'&& ch<='9'){int b=1;count=0;token[count++]=ch;//ch=wenben[p++];getNextChar(fp);while(ch>='0'&&ch<='9'){b++;token[count++]=ch;getNextChar(fp);}if(ch=='.'){token[count++]=ch;getNextChar(fp);while(ch>='0'&&ch<='9'){token[count++]=ch;getNextChar(fp);}retract(fp);number=4;}else{retract(fp);sum=0;for(int i=0;i<b;i++){sum=sum*10+token[i];}if(sum<32768)number=2;else if(sum<2147483648)number=3;else number=-1;}}else switch(ch){case'<':count=0;token[count++]=ch;getNextChar(fp);if(ch=='='){token[count++]=ch;number=13;}else{number=12;retract(fp);}break;case'>':count=0;token[count++]=ch;getNextChar(fp);if(ch=='='){token[count++]=ch;number=11;}else{number=10;retract(fp);}break;case'=':count=0; token[count++]=ch; getNextChar(fp);if(ch=='='){token[count++]=ch;number=15;}else{number=14;retract(fp);}break;case'!':count=0; token[count++]=ch; getNextChar(fp);if(ch=='='){token[count++]=ch;number=17;}else{number=16;retract(fp);}break;case'|':count=0; token[count++]=ch; getNextChar(fp);if(ch=='|'){token[count++]=ch;number=19;}else{number=18;retract(fp);}break;case'&':count=0; token[count++]=ch;getNextChar(fp);if(ch=='&'){token[count++]=ch;number=21;}else{number=20;retract(fp);}break;case'%':count=0;token[count++]=ch;getNextChar(fp);if(ch=='d'){token[count++]=ch;number=33;}else if(ch=='s'){token[count++]=ch;number=34;}else if(ch=='c'){token[count++]=ch;number=36;}else if(ch=='f'){token[count++]=ch;number=37;}else{number=-1;}break;case'+':number=6;token[0]=ch;break; case'-':number=7;token[0]=ch;break; case'*':number=8;token[0]=ch;break; case'/':number=9;token[0]=ch;break; case'(':number=22;token[0]=ch;break; case')':number=23;token[0]=ch;break;case'[':number=24;token[0]=ch;break; case']':number=25;token[0]=ch;break; case'{':number=26;token[0]=ch;break; case'}':number=27;token[0]=ch;break;case';':number=30;token[0]=ch;break;case'"':number=31;token[0]=ch;break;case'#':number=39;token[0]=ch;break;case'.':number=29;token[0]=ch;break;case',':number=28;token[0]=ch;break; default: number=-1;break;}}void error(){printf("(ERROR,");printf("%c",ch);printf(")");printf("\n");fputs("(ERROR,",fw);putc(ch,fw);putc(')',fw);putc('\n',fw);}void ttrue(){char c;c='(';putc(c,fw);printf("%c",c);printf("%d",number);int q=number/10;while(q>0){number=number-10*q;c=(q+'0');putc(c,fw);q=number/10;}c=number+'0';putc(c,fw);printf(",");putc(',',fw);fputs(token,fw);printf("%s",token);c=')';printf("%c",c);putc(c,fw);putc('\n',fw);printf("\n");}int main(int argc,char *argv[]){argc=3;argv[1]="D:\\read.txt";//分析文档argv[2]="D:\\write.txt";//存放文档//从打开目标文件流if((fp=fopen(argv[1],"r"))==NULL){printf("不能打开%s\n",*argv);return 1;}//打开要写二元式的文件流if((fw=fopen(argv[2],"w"))==NULL){printf("不能打开 %s\n",argv[2]);return 1;}do{scanner();switch(number){case -1: error();break;default:ttrue();break;}}while (!feof(fp));fclose(fp);fclose(fw);return 0;}运行结果图:实验总结分析上机前应做好准备.即根据实习目的、要求和分析,选择相应的数据结构,使用C语言参照算法中的流程编写词法分析的程序.将编好的程序上机进行调试.注意调试的例子应有词法正确的,也应有词法错误的或是超出所选数据结构范围的.现在我谈一下关于做这个词法分析程序的心得。