• /  17
  • 下载费用: 14.9积分  

编译原理实验报告——词法分析器(内含源代码)

'编译原理实验报告——词法分析器(内含源代码)'
编译原理实验(一)编译原理实验(一)————词法分析器词法分析器 一.一. 实验描述实验描述运行环境:vc++2008对某特定语言 A ,构造其词法规则。该语言的单词符号包括:1 该程序能识别的单词符号及类别说明表单词类别PROGRAM0NOT1BEGIN2IF3END 4THEN5VAR6ELSE7INT8WHILE9AND10DO11OR 12标识符13常数14+15-16(17)18,19;20=21<22>23*24**25>=26<=27!=28 2 状态转换图3程序流程: 输入一个字符ch去掉空格Ch进行判断将ch与strToken连接输入ch继续判断ch若为字母、数字、下滑线连接继续输入将ch与strToken连接输入ch继续判断ch若为数字、小数点连接继续输入运算符界符判断数字字母或下滑线其他字符查表判断是否保留字输出保留字输出用户标识符是不是输出数字运算符?界符?继续输入判断是否为二元三元运算符运算符输出运算符输出界符界符判断读入的文件是否为空是否结束开始词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。二.二. 实验目的实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。同时增强编写和调试程序的能力。三.三. 实验任务实验任务 编制程序实现要求的功能,并能完成对测试样例程序的分析。四.四. 实验原理实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个 Analyzer 类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数 int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。void GetChar(char *ch); //将下一个输入字符读到 ch 中。void GetBC(char *ch); //检查 ch 中的字符是否为空白,若是,则调用 GetChar 直至 ch 进入一个非空白字符。void Concat(char *strTaken, char *ch); //将 ch 中的字符连接到 strToken 之后。int Reserve(char *strTaken); //对 strTaken 中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回 0。void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将 ch 置为空白字符。void input();//向存放输入结果的字符数组输入一句语句。void display();//输出一些程序结束字符显示样式int analyzerSubFun();//词法分析器子程序,为了实现词法分析的主要功能。五.五. 代码实现代码实现 // cifa.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "stdio.h"#include "string.h"#include "iostream"using namespace std;char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量//int Words[500][10];char ch;//当前读入字符int sr,to=0;//数组str, strtaken 的指针int st=0,dcount=0;int id=0;static int line=1;int h,l;typedef struct Words /*放置二元组*/{ int num;char letters[20];}DS; DS Words[500]; typedef struct words{ char word[20]; int type;}WORDS;WORDS words[]={ {"program",0}, {"not",1}, {"begin",2}, {"end",3}, {"if",4}, {"then",5}, {"var",6}, {"else",7}, {"int",8}, {"while",9}, {"and",10}, {"do",11}, {"or",12}, {"+",15}, {"-",16}, {"(",17}, {")",18}, {",",19}, {";",20}, {"=",21}, {"<",22}, {">",23}, {"*",24}, {"**",25}, {">=",26}, {"<=",27}, {"!=",28} }; typedef struct keytable /*放置关键字*/{ char name[20]; int kind;}KEYTABLE;KEYTABLE keyword[]={ /*设置关键字*/ {"program",0}, {"not",1}, {"begin",2}, {"end",3}, {"if",4}, {"then",5}, {"var",6}, {"else",7}, {"int",8}, {"while",9}, {"and",10}, {"do",11}, {"or",12}, };void openfile() /*打开文件*/{ cout<<"____________________________________________________"<<endl;cout<<" 词法分析器 "<<endl;cout<<"____________________________________________________"<<endl;cout<<"请在本程序根目录下寻找以.txt”为结尾的文件作为词法分析对象,输入文件名"<<endl; FILE *fp; char a,filename[10]; int n=0; gets(filename); if((fp=fopen(filename,"r"))==NULL) { printf("cannot open file.\n"); //exit(0); } else while(!feof(fp)) /*文件不结束,则循环*/ { a=getc(fp); /*getc函数带回一个字符,赋给a*/ set[n]=a; /*文件的每一个字符都放入set[]数组中*/ n++; } fclose(fp); /*关闭文件*/ set[n-1]='\0';}void reflesh() /*清空strtaken数组*/{ to=0; /*全局变量to是strtaken的指示器*/ strcpy(strtaken," ");}void pre1() /*预处理程序*/{ int i,a,b,n=0; do { if(set[n]=='/' && set[n+1]=='*') { a=n; /*记录第一个注释符的位置*/ while(!(set[n]=='*' && set[n+1]=='/')) { if(set[n]=='\n') line++; n++; } b=n+1; /*记录第二个注释符的位置*/ for(i=a;i<=b;i++) /**/ set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ } else if(set[n]=='/' && set[n+1]=='/') { a=n; /*记录第一个注释符的位置*/ while(!set[n]=='\n') n++; b=n+1; /*记录第二个注释符的位置*/ for(i=a;i<=b;i++) /**/ set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ } n++; }while(set[n]!='\0');} void pre2() /*预处理程序*/{ int j=0; sr=0; /*全局变量sr是str[]的指示器*/ do { if(set[j]==' '|| set[j]=='\n') { while(set[j]==' ' || set[j]=='\n') /*扫描到有连续的空格或换行符*/ { if(set[j]=='\n') line++; j++; } str[sr]=' '; /*用一个空格代替扫描到的连续空格和换行符放入str[]*/ sr++; } else { str[sr]=set[j]; /*若当前字符不为空格或换行符就直接放入str[]*/ sr++; j++; } }while(set[j]!='\0'); str[sr]='\0';}char GetChar() /*把字符读入全局变量ch中,指示器sr前移*/{ ch=str[sr]; sr++; return(str[sr-1]);}void GetBC() /*开始读入符号,直至第一个不为空格*/{ while(ch==' ') { ch=GetChar(); }}void Concat() /*把ch中的字符放入strtaken[]*/{ strtaken[to]=ch; to++; /*全局变量to是strtaken的指示器*/ strtaken[to]='\0';}int IsLetter() /*判断是否为字母*/{ if((ch>='a' && ch<='z')||(ch>='A' && ch<='Z')) return(1); else return(0);}int IsDigit() /*判断是否为数字*/{ if(ch>='0' && ch<='9') return(1); else return(0);}int Reserve() /*对strtaken中的字符串查找保留字表,若是则返回它的编码,否则返回-*/{ int i,k=0; for(i=0;i<=12;i++) { if(stricmp(strtaken,keyword[i].name)==0) { k=1; Words[dcount].num=keyword[i].kind; strcpy(Words[dcount].letters,"-"); dcount++; return(keyword[i].kind); } } if(k!=1) return(-1);}void Retract() /*指示器sr回调一个字符位置,把ch置为空*/{ sr--; ch=' ';} int InsertId(){ int i,k; for(i=0;i<id;i++) { k=strcmp(strtaken,sign[i]); if(k==0) return(i); } strcpy(sign[id],strtaken); /*插入标识符*/ Words[dcount].num=13; strcpy(Words[dcount].letters,strtaken); id++;dcount++; return(id-1);}int InsertConst(){ int i,k; for(i=0;i<st;i++) { k=strcmp(strtaken,constant[i]); if(k==0) return(i); } strcpy(constant[st],strtaken);/*插入常数*/ Words[dcount].num=14; strcpy(Words[dcount].letters,strtaken); st++;dcount++; return(st-1);}void analysis(){ int value; reflesh(); /*清空strtaken数组*/ pre1(); /*预处理,使注释内容换成单个空格,放回set[]中*/ pre2(); /*预处理,使set[]中连续的空格置换成单个空格,并把set[]的内容放到str[]中*/ sr=0; GetChar(); /*把字符读入全局变量ch中,指示器sr前移*/ GetBC(); /*读取第一个字符*/ while(ch!='\0') /*当不等于结束符,继续执行*/ { if(IsLetter())//标识符和关键字判定 { while(IsLetter() || IsDigit()) /*若第一个是字符,继续读取,直到出现空格*/ { Concat(); GetChar(); /*把字符读入全局变量ch中,指示器sr前移*/ } Retract(); /*指示器sr回调一个字符位置,把ch置为空*/ value=Reserve(); /*对strtaken中的字符串查找保留字表,若是则返回它的编码,否则返回-*/ if(value==-1) /*如果返回值是-,那就是标识符,把它输出*/ { InsertId(); /*插入标识符*/ } reflesh(); } else if(IsDigit()) { while(IsDigit()) /*否则,若第一个是数字,继续读取,直到出现空格*/ { Concat(); /*把ch中的字符放入strtaken[]*/ GetChar(); } Retract(); /*指示器sr回调一个字符位置,把ch置为空*/ InsertConst(); /*插入常数,返回类型为int*/ //printf(" %s",strtaken); //getchar(); reflesh(); } else switch(ch) /*否则,若是下面的符号*/ { case'+': case'-': case'(': case')': case',': case';': case'=': case'<': case'>': Concat(); for(int c0=15;c0<=23;c0++) { if(stricmp(strtaken,words[c0].word)==0) { Words[dcount].num=words[c0].type; dcount++; }} reflesh(); break; default:if(ch=='*') /*如果是"*"符号,继续读取下一个*/ { Concat(); /*判断是否为"**"的情况*/ GetChar(); if(ch==strtaken[0]) Concat(); else Retract(); for(int c1=24;c1<=25;c1++) { if(stricmp(strtaken,words[c1].word)==0) { Words[dcount].num=words[c1].type; dcount++; } } //printf(" %s",strtaken); //getchar(); reflesh(); break; }else if(ch=='<' || ch=='>' || ch=='!') { Concat(); /*判断是否为<=,>=,!=的情况*/ GetChar(); if(ch=='=') Concat(); else Retract(); for(int c2=26;c2<=28;c2++) { if(stricmp(strtaken,words[c2].word)==0) { Words[dcount].num=words[c2].type; dcount++; } } reflesh(); break; } else { h=ch/line; l=ch%line; cout<<"Error in "<<h<<"行"<<l<<"列"<<endl; //getchar(); break; } } GetChar(); GetBC(); } cout<<"输出二元组:"<<endl; for(int d_i=0;d_i<dcount;d_i++) cout<<Words[d_i].num<<" "<<Words[d_i].letters<<endl; cout<<endl; cout<<"输出标识符:"<<endl; for(int sign_i=0;sign_i<id;sign_i++)cout<<sign_i<<" "<<sign[sign_i]<<endl; cout<<endl; cout<<"输出常量:"<<endl;for(int const_i=0;const_i<st;const_i++)cout<<const_i<<" "<<constant[const_i]<<endl; cout<<endl;}int _tmain(int argc, _TCHAR* argv[]){ openfile(); analysis(); printf("Analysis is finished!"); getchar(); return 0;}测试结果测试结果测试语句为:ProgramProgram exampleexample ; ; varvar intint j,m,n;j,m,n; BeginBegin /*there/*there isis * * a a / / comment*/comment*/ i:=2;i:=2; j:=6;j:=6; m:=3;m:=3; //there//there isis a a commentcomment n:=j+m;n:=j+m; IfIf n>=3n>=3 andand n<5n<5 thenthen j:=j-1;j:=j-1; endend . . 结果截图: 六.六. 总结总结我在这次词法分析器的设计过程中学到了很多东西,其中最大的收获是对于编译原理中的词法分析这一过程理解的更加清楚明了。其次,是在使用 c++编程的能力有所提高。当然,在该词法分析器设计中也有一些不足的地方,比如能识别的关键字有限,并不能识别所有的关键字,识别不出字符常量等。分析结果输出方式为:用一个存放结果的字符串数组,并用指针指向它,输出结果正确,但是输出结果比较乱。不过总的来说,这次实验达到了其初衷,实现了规定的功能。八.致谢词:感谢 xxx 老师对我们的悉心教导以及提供我们这样一个学以致用的机会。 通过这一阶段对编译原理课程的学习,特别是通过这次对于词法分析器的编程实践,我对于编译原理中的词法分析这一过程理解的更加清楚明了,收获很大。
关 键 词:
编译 原理 实验 报告 词法 分析器 内含 源代码
 天天文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
关于本文
本文标题:编译原理实验报告——词法分析器(内含源代码)
链接地址: https://www.wenku365.com/p-18760123.html
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服点击这里,给天天文库发消息,QQ:1290478887 - 联系我们

本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有【成交的100%(原创)】。本站是网络服务平台方,若您的权利被侵害,侵权客服QQ:1290478887 欢迎举报。

1290478887@qq.com 2017-2027 https://www.wenku365.com 网站版权所有

粤ICP备19057495号 

收起
展开