实验一手工编写简易词法分析程序
- 格式:doc
- 大小:184.50 KB
- 文档页数:16
编译原理实验报告日期:班级:题目:组员:1实验目的及要求1.通过设计、编写、调试一个具体的词法分析程序,加深对词法分析原理的理解。
2.掌握在对程序设计语言源程序进行扫描的过程中, 将其分解为各类单词的词法分析方法。
2实验平台Windows + VC + Win32 Console3实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
4实验内容4.1 实现下述功能, 并将分析结果保存在文件中. (既可以参考范例程序, 也可以独立完成)程序输入/输出示例:输入一段C语言程序,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)输入源程序示例:main ( ){int a , b =10;int c ;c = a + b * 20;}输出固定表格如下输出动态表格如下运算符表44.2 程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;elsereturn 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│1\t│1\t\t│\n",Word);//不是关键字else if(c==2)printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│2\t│3\t\t│\n",Word);elseprintf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\n",Word); //输出关键字}else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│7\t\t│\n",Word); break;case']':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│9\t\t│\n",Word); break;case'(':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│3\t\t│\n",Word); break;case')':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│4\t\t│\n",Word); break;case'{':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│5\t\t│\n",Word); break;case'}':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│6\t\t│\n",Word); break;case',':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│1\t\t│\n",Word); break;case'"':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│8\t\t│\n",Word); break;case';':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│2\t\t│\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//运算符"+="}else if(ch=='+'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"++"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│1\t\t│\n",Word); //判断结果为"+"}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); }else if(ch=='-'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"--"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│2\t\t│\n",Word); //判断结果为"-"}break;case'*':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│3\t\t│\n",Word);break;case'/':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│4\t\t│\n",Word);break;case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│5\t\t│\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为运算符"<="}else if(ch=='<'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//判断结果为"<<"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"<"}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){ printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}if(IsAlpha(ch)) printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t│类型标识符\t│ \t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s \t│取余运算符\t│ \t\n",Word);}break;default:printf("\t\t├───────┼───┼───────┤\n\t\t│无法识别字符! \t\t\t\t │\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(true){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n**************************** 单词类别表****************************\n");printf("\t\t┌───────┬───────┐\n\t\t│单词类型\t│单词种别\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│标识符 \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│保留字 \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│常量 \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│运算符 \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│分界符 \t│5 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 保留字表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│保留字 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│int \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│float \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│main \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│printf \t│4 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 运算符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│算符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│+ \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│- \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│* \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│/ \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│= \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│其他 \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 分界符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│界符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│, \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│; \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│( \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│) \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│{ \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│} \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 词法分析结果如下******************************\n");printf("\t\t┌───────┬───┬───────┐\n\t\t│单词名称\t│类别\t│地址指针\t│\n",Word);do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');printf("\t\t└───────┴───┴───────┘\n",Word);return(0);}5实验结果5.1 解析源文件:main ( ){int a , b =10;int c ;c = a + b * 20;}#5.2 解析结果:6实验总结分析在本次实验,使我们再次浏览了有关C语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。