logo资料库

编译原理课程词法分析器实验报告含详细源码及分析.doc

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
一、 实验题目: 词法分析程序 二、 实验内容: 1、主程序设计考虑: 主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。 id 和 ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。 主程序的工作部分建议设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上送来的一个 单词;调用词法分析过程;输出每个单词的内部码。 2)词法分析过程考虑 该过程取名为 lexical,它根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词类, 产生类号。对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素, 则记录其在表中的位置,如未出现过,将标识符按顺序填入数组 id 中,将常数存入数组中 ci 中,并记 录其在表中的位置。 三、 程序源代码: #include #include #include #include #define LEN sizeof(struct Node) #define NULL 0 struct Node { char data; struct Node *next; }; void Output1(struct Node*); void Scaner(); /*词法分析*/ void Scaner1(); void GetBC(); void GetChar(); void Concat(); int IsLetter(char ch); int IsDegit(char ch); int Reserve(); void Retract(); void Back(char *a,char *b); struct Node *head,*p; 第 页 共 页
char ch; /*全局变量*/ char *key[]={"int","char","float","void","const","if","else","do","while","scanf","printf","retu rn","main"}; /*关键字表*/ char Token[20]; /*字符数组,存放构成单词的符号串*/ char *id[256]; int ci [256]; int i=0; int j=0; int opt; void main() { head=(struct Node *)malloc(LEN); /*分配头节点存储空间*/ if(!head) { printf("error"); exit(1); } head->next=NULL; head->data=' '; p=head; printf("如果想结束输入就在新的一行的开始输入’$’!\n 输入结束后屏幕上会输入你刚输入的代 码\n"); printf("请输入你的代码:\n"); while(1) { int i=0; char temp[256];/*每行长度不超过 256 个字符*/ gets(temp); /*输入源程序,以行为单位*/ if(temp[0]=='$') break;/*当输入的第一个字符为$时表示输入源代码结束*/ p->next=(struct Node *)malloc(LEN); if(!(head->next)) { printf("error"); exit(1); } // p=head; p=head->next; while(temp[i]!='\0' && i<256) { /*将输入的代码以行为单位存入缓冲区*/ p->data=temp[i]; p->next=(struct Node *)malloc(LEN); if(!(p->next)) 第 页 共 页
{ printf("error"); exit(1); } p=p->next; i++; } p->data='\n'; p->next=NULL; /*尾结点*/ /*扫描缓冲区,输出结果*/ } printf("你刚才输入的是代码为:\n"); Output1(head); p=head->next; printf("经该词法分析器程序处理后输出结果为:\n"); printf("注:第一个无素 1,2,3,4,5 分别表关键字、表标识符、表常数、表运算符、表界符\n"); printf(" // printf("有两种输出格式,可通输入 0 或 1 进行选择"); //opt=(int)getchar(); while(p->next!=NULL) { 第二无素为该单词在各自表中的指针或内部码值\n"); Scaner(); } system("pause"); //return 0; } void Output1(struct Node *head) { /*扫描缓冲区函数*/ if(!(head)) {printf("error");exit(1);} p=head->next; while(p->next!=NULL) { printf("%c",p->data); p=p->next; } printf("\n"); } void GetBC() /*若 ch 中是空白字符,则不停调用 getch()直到读入的不是空白字符为止*/ { while (ch==' ') GetChar(); } void GetChar() /*从缓冲区读入一字符*/ 第 页 共 页
{ } ch=p->data; p=p->next; void Concat() { /*将 ch 中的字符连接到 token 的后面*/ unsigned int i; i=strlen(Token); if(ch!=' ') { Token[i]=ch; Token[i+1]='\0'; } } int IsLetter(char ch) { return isalpha((int)ch); } int IsDigit(char ch) { /*判断 ch 中的是否是数字*/ return isdigit((int)ch); } int Reserve() /*判断 token 中的字符串是否是关键字或是标识符*/ { int k; for(k=0;k<13;k++) { if(strcmp(key[k],Token)==0) return (k+1); } return 0; } void Retract() /*指针回退一个字符*/ { struct Node *Q; Q=head->next; while(Q->next!=p) Q=Q->next; p=Q; } void Back(char *a,char *b) { 第 页 共 页
printf("(%s,%s)\n",a,b); } void Scaner() { int c; Token[0]=NULL; GetChar(); GetBC(); if(IsLetter(ch)) { while(IsLetter(ch)||IsDigit(ch)) { Concat(); GetChar(); } Retract(); c=Reserve(); if(c!=0) { printf("<1,%d>\n",c); } else { printf("<2,%d>\n",i); id[i]=Token; i++; } } else if(IsDigit(ch)){ while(IsDigit(ch)) { Concat(); GetChar(); } Retract(); printf("<3,%d>\n",j); ci[j]=atoi(Token); j++; } else switch(ch) { case'+': GetChar(); if(ch=='+') 第 页 共 页
{ } printf("<4,39>\n"); Retract(); printf("<4,15>\n"); break; case'-': GetChar(); if(ch=='-') case'&':GetChar(); case'|':GetChar(); { printf("<4,40>\n");} Retract(); printf("<4,16>\n"); break; if(ch=='&') { printf("<4,27>\n"); } printf("error\n"); Retract(); if(ch=='|') { printf("<4,28>\n"); } Retract(); break; case'*': case'/': case'%': printf("<4,17>\n"); break; printf("<4,18>\n"); break; printf("<4,19>\n"); break; case'<': GetChar(); if(ch=='=') { printf("<4,26>\n"); } Retract(); printf("<4,23>\n"); break; case'>': GetChar(); 第 页 共 页
if(ch=='=') { printf("<4,25>\n"); } Retract(); printf("<4,22>\n"); break; case';':printf("<5,35>\n");break; case',': printf("<5,36>\n");break; case'"': printf("<5,37>\n");break; case'{': printf("<5,33>\n");break; case'}':printf("<5,34>\n");break; case'(':printf("<5,31>\n");break; case')':printf("<5,32>\n");break; case'=':GetChar(); if(ch=='=') { printf("<4,21>\n");} Retract(); printf("<5,20>\n"); case'!':GetChar(); break; if(ch=='=') { printf("<5,24>\n");} Retract(); printf("<5,29>\n"); break; case'\n': break; default: printf("error\n");break; } } 四、 测试结果: 第 页 共 页
五、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等) 注:内容一律使用宋体五号字,单倍行间距 1、 通过这次实验我对词法分析器有了进一步的了解,把理论知识应用于实验中。 2、 在编写程序过程中也遇到了很多困难,不过最终通过自己细心检查得到了解决,为以后编程积累了些 小知识; 3、 程序实现功能很有限,但时间有限,只完成上述功能,以后会继续改进的。 4、 希望老师以后多一些实践机会,把理论知识应用到实际程序中,会更容易理解。 第 页 共 页
分享到:
收藏