汇编语言词法分析(新)

  • 格式:doc
  • 大小:576.50 KB
  • 文档页数:13

数学与信息工程学院《编译原理》实验报告一实验名称:词法分析实验室:6202班级:09计算机3班姓名:沈春晖学号:0929210062词法分析器的设计一、实验目的通过完成词法分析程序,了解词法分析的过程。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

二、实验环境操作系统:window xp编写环境:visual c++ 、c-free、turbo c编写语言:c语言分析语言:PL/0三、实验内容对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下:(1)关键字:begin,call,const,do,end,if,odd,procedure,read,then,var,while,write(2)标识符:用来表示各种名字,必须以字母开头小于10位字符组成(3)数字:以0-9组成小于14位的数字(4)运算符:+,-,*,/,:=,<,<=,>,>=(5)界符:,,.,;,#表1 各种单词符号对应类型表单词符号类型+ plus- minus* times/ slash( lparen) rparen= eql, comma. perio# neq; semicolonbegin beginsymcall callsymconst constsymdo dosymend endsymififsym oddoddsym procedureproceduresym readreadsym thenthensym var varsym whilewhilesym write writesymN NYY开始调用GETSYM 取单词 输入要分析的文件文件是否存在文件是否结束结束打印分析结果图1 主流程图Y N N NNN YYY YGETSYM滤空CH=空?GETCH CH 是字母? K:=0 K<10?K:=K+1A[K]:=CH GETCHCH 是字母或数字?ID:=A ID 是否是保留字? SYM:=IDENT 相应保留字类别送SYM返回CH 是数字?拼数,将拼数后的值送NUM SYM:=SYM把该字符转换成对应单词,或拼复合单词,将其类别送SYM 中图2 GETSYM 流程图NYGETSYM 函数功能:(1) 滤空格 空格在词法分析时是一种不可缺少的界符,而在语法分析时则是无用的,所以必须过滤(2) 识别保留字 主程序定义了一个以字符为元素的一维数组WORD ,称保留字表。

对字母开头的字母、数字字符串要查此表。

若查着则识别为保留字,将对应的类别放在SYM 中。

如IF 的对应值IFSYM ,THEN 的对应值为THENSYM 。

若查不着,则认为是用户定义的标识符(3) 识别保留字 对用户定义的标识符将IDENT 放在SYM 中,标识符本身的值放在ID 中(4) 拼数 当扫描到数字串时,将字符串形式的十进制数转换为二进制数,然后把数的类别NUMBER 放在SYM 中,数值本身的值放在NUM 中(5) 拼合复合词 对两个字符组成的算符,如:>=、:=、<=等单词,识别后将类别送SYM 中(6) 输出源程序 为边读入字符边输出(可输出在文件中)N NGETCH缓冲区是否还有字符?源程序文件是否结束?打印出错信息 停止编译读入一行源程序放入在LINE 中并输出,置CC:=0 CC:=CC+1CH:=LINE[CC]返回Y Y图3 GETCH 流程图四、实验结果要分析的内容如下:const a=35;var c,d;procedure p;beginvar g;g:=465494366466564444;write(g);end;beginread(c,d);if c<=d then c:=a;write(c,d);call p;end.图4 实验结果图五、实验小结(心得体会)刚开始的时候运行中报错,原因是函数的调用顺序出现错误,后经调试改正了。

通过本实验的完成,更了解了此法分析的基本任务是从字符串表示的原程序中识别出具有独立意义的单词符号,其基本意思是根据少苗到单词符号的第一个字符的种类,拼出相应的单词符号。

附录:源代码#include<stdio.h>#include"string.h"#define al 10 /*符号的最大长度*/#define norw 13 /*关键字个数*/#define namx 14 /*数字允许的最长位数*/FILE *fin;FILE *fout;char fname[al],fwname[al],a[al+1]/*a[50]*/,id[al+1],sym[20];static char sword[11]={'+','-','*','/','(',')','=',',','.','#',';'};static charssym[11][al]={"plus","minus","times","slash","lparen","rparen","eql","comma","period","neq", "semicolon"};static charword[13][al]={"begin","call","const","do","end","if","odd","procedure","read","then","var"," while","write"};//保留关键字static charwsym[13][al]={"beginsym","callsym","constsym","dosym","endsym","ifsym","oddsym","procsym","r eadsym","thensym","varsym","whilesym","writesym"};//关键字类型int cc,ll,cx,linecount,num;char line[81];char ch;void main(){int getsym();printf("**********编译原理实验PL/0语言词法分析**********\n");printf("请输入进行词法分析的文件名:");scanf("%s",fname);fin=fopen(fname,"r");printf("请输入分析结果保存的文件名:");scanf("%s",fwname);fout=fopen(fwname,"w");linecount=0;//记录文件的行数cc=ll=0;ch=' ';if(fin){printf("\n-----开始词法分析-----\n");fprintf(fout,"-----开始词法分析-----\n");printf("单词自身的值单词种别\n");fprintf(fout,"单词自身的值单词种别\n");while( getsym()!=-1 ){printf("%-20s",a);fprintf(fout,"%-20s",a);printf("%s",sym);//输出单词种别fprintf(fout,"%s",sym);printf("\n");fprintf(fout,"\n");}printf("%-20s",a);fprintf(fout,"%-20s",a);printf("%s",sym);//输出单词种别fprintf(fout,"%s",sym);printf("\n程序分析完毕");fprintf(fout,"\n程序分析完毕");}else{printf("你输入的文件不存在");fprintf(fout,"你输入的文件不存在");}}void error(int rowcount,int wordcount){printf("!第%d行第%d个位置数字越界\n",rowcount,wordcount);fprintf(fout,"!第%d行第%d个位置数字越界\n",rowcount,wordcount); }int getch(){if(cc==ll){//缓冲是否被读取完毕if(feof(fin)){return -1;}ll=0;cc=0;ch=' ';while(ch!=10){if(EOF==fscanf(fin,"%c",&ch)){line[ll]=0;break;}line[ll]=ch;ll++;}linecount++;printf("开始分析程序的第%d行\n",linecount);fprintf(fout,"开始分析程序的第%d行\n",linecount);}ch=line[cc];cc++;return 0;}int getsym(){int i,j,k;while(ch==' ' || ch==10 || ch==9 )/*判断字符是否为空,空跳过取下一个字符*/ {if(-1==getch()){return -1;}}if(ch>='a' && ch<='z'){//如果是字符或以字符开头int b=0;k=0;do{if(k<al){a[k]=ch;k++;}if(-1==getch()){a[k]=0;b=1;break;}}while(ch>='a' && ch<='z' || ch>='0' && ch<='9');a[k]=0;strcpy(id,a);i=0;j=norw-1;do{k=(i+j)/2;if(strcmp(id,word[k])<=0){j=k-1;}if(strcmp(id,word[k])>=0){i=k+1;}}while(i<=j);if(i-1>j){strcpy(sym,wsym[k]);}else{strcpy(sym,"ident");}if(b==1) return -1;}else{if(ch>='0' && ch<='9'){//如果非字符开头k=0;num=0;strcpy(sym,"number");do{a[k]=ch;num=10*num+ch-'0';//转换为对应的数字k++;if(-1==getch()){a[k]=0;return -1;}}while(ch>='0' && ch<='9');a[k]=0;k--;if(k>namx){error(linecount,cc);//错误处理,数字越界}}else{//如果是计算、比较符号a[0]=ch;if(ch==':'){if(-1==getch()){a[1]=0;return -1;};if(ch=='='){strcpy(sym,"becomes");a[1]=ch;a[2]=0;if(-1==getch()) return -1;}else{a[1]=0;strcpy(sym,"nul");//不可识别符号}}else{if(ch=='<'){if(-1==getch()) {a[1]=0;return -1;};if(ch=='='){a[1]=ch;a[2]=0;strcpy(sym,"leq");//小于等于if(-1==getch()) return -1;}else{a[1]=0;strcpy(sym,"lss");//小于}}else{if(ch=='>'){if(-1==getch()) {a[1]=0;return -1;};if(ch=='='){a[1]=ch;a[2]=0;strcpy(sym,"geq");if(-1==getch()) return -1;}else{a[1]=0;strcpy(sym,"gtr");}}else{//单字符符号处理i=0;a[1]=0;while(i<11 && ch!=sword[i]){i++;}if(i<11){strcpy(sym,ssym[i]);if( strcmp(sym,"period")!=0 ){if(-1==getch()) return -1;}else{return -1;}}else{printf("不可识别的字符\n");}}}//非字符开头处理结束}}}return 0;}。