当前位置:文档之家› 词法分析的设计与实现

词法分析的设计与实现

题目词法分析的设计与实现学院专业名称计算机科学与技术姓名导师姓名2010年12 月目录1.课程设计的目的 (1)2.课程设计的内容 (1)3、课程设计的要求 (1)4.课程设计报告内容 (1)4.1设计功能分析 (1)4.2 设计思路 (1)4.3 正规文法 (2)4.4 状态图 (3)4.5设计词法分析算法代码 (5)4.6基本测试数据 (12)4.7结果截图 (12)5.设计体会 (12)6.参考文献 (13)7.思考题 (13)词法分析的设计与实现一、课程设计的目的1、基本掌握计算机语言的词法分析程序的开发方法。

2、实现一个词法分析程序,将字符串流分解成终结符流供语法分析使用。

3、通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

4、了解当前常用的软件开发工具Visual C++,熟练掌握基于MFC的程序设计,培养解决实际问题的能力。

5、对C语言和数据结构的进一步巩固加深。

二课程设计的内容编制一个能够分析三种数、标识符、主要运算符、分隔符和主要关键字的词法分析程序。

三、课程设计的要求1.根据以下的正规式,编制正规文法,画出状态图;标识符 <字母>(<字母>|<数字字符>)*十进制数(0 | 1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*(ε|.)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*八进制数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*(ε|.)(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* (ε|.)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和分隔符 + - * / > < = ( ) ;关键字 if then else while do2.根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从键盘读入数据,分析出一个单词。

2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。

3.编写测试程序,反复调用函数scan( ),输出单词种别和属性。

四、课程设计报告内容4.1、设计功能分析程序能够从左到右一个字符一个字符地读入源程序,并对构成的源程序的字符流进行扫描和分解,从而识别出一个个单词,并给出单词的种别和属性。

4.2、设计思路主函数main()的思想:先输入一串字符,将字符串用空格打断,若是分隔出的单元不为空,则对此单元继续分析,根据所输入的字符串判断出是标识符、八进制数、十进制数、十六进制数、运算符、分隔符还是关键字,然后赋予那单词的种别和属性。

4.3、正规文法对于十进制数:A1——>B1C1B1——>D1B1|εC1——>E1B1E1——> ε|.D1——>0|1|2|3|4|5|6|7|8|9对于八进制数:A2——>0B2B2——>C2D2C2——>E2F2E2——>1|2|3|4|5|6|7F2——>GF|εD2——>H2F2H2——> ε|.D2——>1|2|3|4|5|6|7G2——>0|1|2|3|4|5|6|7对于十六进制:A3——>0xB3B3——>C3D3C3——>E3C3|εE3——> 0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|fD3——>F3C3F3——> ε|.对于运算符和分隔符:A4——>+|-|*|/|>|<|=|(|)|;对于标识符和关键字:A5——>B5C5B5——>D5E5D5——>a|b|……|y|zE5——>F5E5|εF5——>a|b|……|y|z|0|1|2|3|4|5|6|7|8|9C5——>G5E5G5——> ε|.综上正规文法为:S——>A1|A2|A3|A4|A5A1——>B1C1B1——>D1B1|εC1——>E1B1E1——> ε|.D1——>0|1|2|3|4|5|6|7|8|9A2——>0B2B2——>C2D2C2——>E2F2E2——>1|2|3|4|5|6|7F2——>GF|εD2——>H2F2H2——> ε|.D2——>1|2|3|4|5|6|7G2——>0|1|2|3|4|5|6|7A3——>0xB3B3——>C3D3C3——>E3C3|εE3——> 0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f D3——>F3C3F3——> ε|.A4——>+|-|*|/|>|<|=|(|)|;A5——>B5C5B5——>D5E5D5——>a|b|……|y|zE5——>F5E5|εF5——>a|b|……|y|z|0|1|2|3|4|5|6|7|8|9 C5——>G5E5G5——> ε|.4.4、状态图0 (7)*0….9/a …z/A …Z1 (9)0 (9)其他开始空白a ….z / A …Z23 469其他。

0 (9)非数字。

0 (7)非o..7且非。

1100 (7)非o..7。

7581211131…9/a ….f / A …F 14非1….9且非a...f 且非A...F15 0….9/a...f/A...F 16非0….9且非a...f 且非A...F。

17。

1819+/-/ …/;If/while/then/dox/X4.4设计词法分析算法代码:#include<string.h>#include<stdio.h>#include "stdafx.h"union chars{ //联合,可存储字符串,整型和浮点型char pro_char[15];int pro_number;float real;};struct data{ //将每个单元用一个结构来存储,其内容包括:类型,所属的具体类型,以及属性值char kind[7];int id;union chars pro;};int scan(char *a); //对每个用空格打断的单元进行进一步的分析,对其进行进一步的分类void Prints(char a[15],int id,int a_long); //将分析后的每个token输出void save(char *a,int id,int x); //将分析后的结果保存到一个结构数组中char nowChar[15]; //临时的存储单元,用来存储被空格打断以后单元char kinds[11][8]={" ","INT10","INT8","INT16","IDN"," "," "," ","REAL10","REAL8","REAL16"};//单词的不同种别struct data link[100]; //用来存放词法分析以后的结果的结构数组int link_long=0; //全局变量int scan(char *a){int id;int a_long=0;int doc=0;while(*a!=NULL){nowChar[0]='\0';a_long=0;doc=0;//对数值的判断及处理if('0'<=*a&&*a<='9'){ //如果第一个字符为数值nowChar[a_long]=*a;*a++;a_long++;//对十六进制的判断及处理if(nowChar[0]=='0'&&(*a=='x'||*a=='X')){ //如果第一个字符为0且第二个字符为x,则为十六进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'<=*a&&*a<='9')||('a'<=*a&&*a<='f')||('A'<=*a&&*a<='F')||*a=='.')){ nowChar[a_long]=*a; //一直将此十六进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0'; //判断输入的十六进制数是否合法if(a_long==2){ //输入的只有0x,则输入错误Prints(nowChar,7,a_long);return 0;}if(doc) //输入的十六进制数是浮点型的Prints(nowChar,10,a_long); //则将其具体的类型属性定为10else //输入的十六进制数是整型的Prints(nowChar,3,a_long); //则将其具体的类型属性定义为3continue;}//对八进制的判断及处理if(nowChar[0]=='0'&&'0'<=*a&&*a<='7'){ //如果第一个字符为0且第二个字符为0~7,则为八进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'<=*a&&*a<='7')||*a=='.')){nowChar[a_long]=*a; //一直将此八进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) //输入的八进制数是浮点型的Prints(nowChar,9,a_long); //则将其具体的类型属性定为9else //输入的十六进制数是整型的Prints(nowChar,2,a_long); //则将其具体的类型属性定义为2continue;}//对十进制数的判断及处理else{while(*a!=NULL&&(('0'<=*a&&*a<='9')||*a=='.')){nowChar[a_long]=*a; //一直将此十进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) //输入的十进制数是浮点型的Prints(nowChar,8,a_long); //则将其具体的类型属性定为8else //输入的十进制数是整型的Prints(nowChar,1,a_long); //则将其具体的类型属性定义为1continue;}} //完成了对数值的判断及处理//对字符的判断及处理else{nowChar[a_long]=*a;*a++;a_long++;//判断输入的字符是否为运算符或其他的分隔符switch(nowChar[0]){case'+':case'-':case'*':case'/':case'<':case'>':case'(':case')':case'=':case';':nowChar[a_long]='\0';Prints(nowChar,5,a_long); //将其具体的类型属性定义为5continue;default:break;}//判断输入的第一个字符是否为字母if(('a'<=nowChar[0]&&nowChar[0]<='z')||('A'<=nowChar[0]&&nowChar[0]<='Z')){while(*a!=NULL&&(('a'<=*a&&*a<='z')||('A'<=*a&&*a<='Z')||('0'<=*a&&*a<='9')||(*a=='.')||( *a=='_'))){ //一直将此字符串完全读入nowChar[a_long]=*a;*a++;a_long++;}nowChar[a_long]='\0';//判断输入的字符串是否为特殊的标识符,若是,则将其具体类型值定义为6//判断输入的字符串是否为特殊的字符串ifif(a_long==2&&strcmp(nowChar,"if")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串thenif(a_long==4&&strcmp(nowChar,"then")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串elseif(a_long==4&&strcmp(nowChar,"else")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串whileif(a_long==5&&strcmp(nowChar,"while")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串doif(a_long==2&&strcmp(nowChar,"do")==0){Prints(nowChar,6,a_long);continue;}//若输入的字符串不符合以上几种情况,则输入的为变量//若输入的字符串为变量,则将其具体属性值定义为4Prints(nowChar,4,a_long);continue;}//如果输入的既不是数值也不是字符串,则输入错误,将其具体类型之定义为7 else{Prints(nowChar,7,a_long);return 0;}}}return 1;}main(){char buf[100]; //用来存储从键盘上输入一串字符char *tokenPtr; //用来存储用空格打断后的单元int id=1; //用来存储具体的类型号link_long=0;while(id){link_long=0;gets(buf); //从键盘上输入一串字符tokenPtr=strtok(buf," "); //用空格将字符串打断while(id&&*tokenPtr!=NULL){ //分割出来的单元不为空id=scan(tokenPtr); //将此单元进行继续分析,并返回其具体的类型值tokenPtr=strtok(NULL," "); //将字符串继续用空格进行分割}}printf("\n\n");getchar();return 0;}//将所分解后的单元存入结构数组中void save(char *a,int id,int x,float y){int i;if(link_long<100){link[link_long].id=id; //将具体的类型值存入if(id>=5){if(id>=8){//id=8,9,10//若为浮点型的数值,则将浮点型的y值(转换后的)存入其属性当中且存入单词的种别for(i=0;i<9&&kinds[id][i]!='\0';i++)link[link_long].kind[i]=kinds[id][i];link[link_long].pro.real=y;}//id=5,6,7else{//若为标识符,则将单词种别定为自身,属性值定为空for(i=0;i<15&&a[i]!='\0';i++)link[link_long].kind[i]=a[i];link[link_long].pro.pro_char[0]='-';link[link_long].pro.pro_char[1]='\0';}link_long++;}//id=1,2,3,4else{for(i=0;i<8&&kinds[id][i]!='\0';i++)link[link_long].kind[i]=kinds[id][i]; //若分解后的token为变量或者整型数值,则将其单词种别直接输出if(id==4){ //若token为变量,则将其属性值设为自身for(i=0;i<15&&a[i]!='\0';i++)link[link_long].pro.pro_char[i]=a[i];link[link_long].pro.pro_char[i]='\0';}else //若token为整型数值,则将其相应的十进制数值赋给其属性值link[link_long].pro.pro_number=x;}link_long++; //继续存入下一个token}elseprintf("Full 100\n"); //结构数组已经存满return;}//将词法分析器分解后的结果输出出来void Prints(char a[15],int id,int a_long){int i;int x=0;float y=0;//int float1;//char *c;if(id==1){ //若为十进制整数for(i=1;i<a_long&&a[i]!='\0';i++)x=x*10+(a[i]-48);printf("INT10\t%s\n",a);save(a,id,x,y); //存入结构数组return;}if(id==2){ //若为八进制整数for(i=1;i<a_long&&a[i]!='\0';i++)x=x*8+(a[i]-48); //换算为十进制数printf("INT8\t%d\n",x);save(a,id,x,y); //存入结构数组return;}if(id==3){ //若为十六进制整数for(i=2;i<a_long&&a[i]!='\0';i++){if('0'<=a[i]&&a[i]<'9')x=x*16+(a[i]-48); //换算为十进制数else{if('a'<=a[i]&&a[i]<='f')x=x*16+(a[i]-87);elsex=x*16+(a[i]-55);}printf("INT16\t%d\n",x);save(a,id,x,y); //存入结构数组return;}if(id==4){ //若为变量printf("IDN\t%s\n",a);save(a,id,x,y); //存入结构数组return;}if(id==5||id==6){ //若为标识符(+,-,*,/,++以及if,else,while,then,do)printf("%s\t-\n",a);save(a,id,x,y); //存入结构数组return;}if(id==8){ //若为十进制浮点型for(i=0;i<a_long&&a[i]!='.';i++)x=x*10+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/10;y=y+x; //整数部分与小数部分换算后相加printf("REAL10\t%f\n",y);save(a,id,x,y); //存入结构数组return;}if(id==9){ //若为八进制浮点型for(i=1;i<a_long&&a[i]!='.';i++)x=x*8+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/8;y=y+x; //整数部分与小数部分换算后相加printf("REAL8\t%f\n",y);save(a,id,x,y); //存入结构数组return;}if(id==10){ //若为十六进制浮点型for(i=2;i<a_long&&a[i]!='.';i++) //将整数部分与小数部分分割开,并进行相应的换算x=x*16+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/16;y=y+x; //整数部分与小数部分换算后相加printf("REAL16\t%f\n",y); //存入结构数组save(a,id,x,y);return;printf("Wrong Enter"); //所得的具体类型值为7,则输入有错误return ;}4.5基本测试数据:输入数据例:00 96*name 25> 0x8d while 5;4.6结果截图:五、设计体会本次的课程设计使团队成员对词法分析的过程有了全新的了解,同时也明白了词法分析何时可以采用空格来区分单词,明白了程序设计中影响词法分析的效率的环节。

相关主题