《编译原理实验报告——词法分析器(内含源代码).docx》由会员分享,可在线阅读,更多相关《编译原理实验报告——词法分析器(内含源代码).docx(17页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、编译原理实验(一)词法分析器一 实验描述运行环境:vc+2008对某特定语言A ,构造其词法规则。该语言的单词符号包括:1该程序能识别的单词符号及类别说明表单词类别PROGRAM0NOT1BEGIN2IF3END 4THEN5VAR6ELSE7INT8WHILE9AND10DO11OR 12标识符13常数14+15-16(17)18,19;20=2123*24*25=26=27!=282状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。二 实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结
2、构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。同时增强编写和调试程序的能力。三 实验任务 编制程序实现要求的功能,并能完成对测试样例程序的分析。四 实验原理char set1000,str500,strtaken20;/set存储代码,strtaken存储当前字符char sign5010,constant5010;/存储标识符和常量定义了一个Analyzer类class Analyzerpublic:Analyzer();/构造函数 Analyzer();/析构函数 int IsLetter(char ch); /判断是否是字母,是则返回
3、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 Retrac
4、t(char *ch) ; /将搜索指针器回调一个字符位置,将ch置为空白字符。void input();/向存放输入结果的字符数组输入一句语句。void display();/输出一些程序结束字符显示样式int analyzerSubFun();/词法分析器子程序,为了实现词法分析的主要功能。五 代码实现 / cifa.cpp : 定义控制台应用程序的入口点。/#include stdafx.h#include stdio.h#include string.h#include iostreamusing namespace std;char set1000,str500,strtaken20
5、;/set存储代码,strtaken存储当前字符char sign5010,constant5010;/存储标识符和常量/int Words50010;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 letters20;DS; DS Words500; typedef struct words char word20; int type;WORDS;WORDS
6、 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, ,23, *,24, *,25, =,26, =,27, !=,28 ;typedef struct keytable /*放置关键字*/ char name20; int kind;KEYTABLE;KEYTABLE keyword= /*设置关键字*/ program,0, not,1, beg
7、in,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,filename10; int n=0; gets(filename); if(fp=fopen(filename,r)=NULL) printf(cannot open file.n);
8、 /exit(0); else while(!feof(fp) /*文件不结束,则循环*/ a=getc(fp); /*getc函数带回一个字符,赋给a*/ setn=a; /*文件的每一个字符都放入set数组中*/ n+; fclose(fp); /*关闭文件*/ setn-1=0;void reflesh() /*清空strtaken数组*/ to=0; /*全局变量to是strtaken的指示器*/ strcpy(strtaken, );void pre1() /*预处理程序*/ int i,a,b,n=0; do if(setn=/ & setn+1=*) a=n; /*记录第一个注释
9、符的位置*/ while(!(setn=* & setn+1=/) if(setn=n) line+; n+; b=n+1; /*记录第二个注释符的位置*/ for(i=a;i=b;i+) /*/ seti= ; /*把注释的内容换成空格,等待第二步预处理*/ else if(setn=/ & setn+1=/) a=n; /*记录第一个注释符的位置*/ while(!setn=n) n+; b=n+1; /*记录第二个注释符的位置*/ for(i=a;i=a & ch=A & ch=0 & ch=9) return(1); else return(0);int Reserve() /*对st
10、rtaken中的字符串查找保留字表,若是则返回它的编码,否则返回*/ int i,k=0; for(i=0;i=12;i+) if(stricmp(strtaken,keywordi.name)=0) k=1; Wordsdcount.num=keywordi.kind; strcpy(Wordsdcount.letters,-); dcount+; return(keywordi.kind); if(k!=1) return(-1);void Retract() /*指示器sr回调一个字符位置,把ch置为空*/ sr-; ch= ;int InsertId() int i,k; for(i=
11、0;iid;i+) k=strcmp(strtaken,signi); if(k=0) return(i); strcpy(signid,strtaken); /*插入标识符*/ Wordsdcount.num=13; strcpy(Wordsdcount.letters,strtaken); id+;dcount+; return(id-1);int InsertConst() int i,k; for(i=0;ist;i+) k=strcmp(strtaken,constanti); if(k=0) return(i); strcpy(constantst,strtaken);/*插入常数
12、*/ Wordsdcount.num=14; strcpy(Wordsdcount.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
13、) /*当不等于结束符,继续执行*/ if(IsLetter()/标识符和关键字判定 while(IsLetter() | IsDigit() /*若第一个是字符,继续读取,直到出现空格*/ Concat(); GetChar(); /*把字符读入全局变量ch中,指示器sr前移*/ Retract(); /*指示器sr回调一个字符位置,把ch置为空*/ value=Reserve(); /*对strtaken中的字符串查找保留字表,若是则返回它的编码,否则返回*/ if(value=-1) /*如果返回值是,那就是标识符,把它输出*/ InsertId(); /*插入标识符*/ reflesh
14、(); 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=
15、: case: Concat(); for(int c0=15;c0=23;c0+) if(stricmp(strtaken,wordsc0.word)=0) Wordsdcount.num=wordsc0.type; dcount+; reflesh(); break; default:if(ch=*) /*如果是*符号,继续读取下一个*/ Concat(); /*判断是否为*的情况*/ GetChar(); if(ch=strtaken0) Concat(); else Retract(); for(int c1=24;c1=25;c1+) if(stricmp(strtaken,word
16、sc1.word)=0) Wordsdcount.num=wordsc1.type; dcount+; /printf( %s,strtaken); /getchar(); reflesh(); break; else if(ch= | ch=!) Concat(); /*判断是否为=,!=的情况*/ GetChar(); if(ch=) Concat(); else Retract(); for(int c2=26;c2=28;c2+) if(stricmp(strtaken,wordsc2.word)=0) Wordsdcount.num=wordsc2.type; dcount+; re
17、flesh(); break; else h=ch/line; l=ch%line; coutError in h行l列endl; /getchar(); break; GetChar(); GetBC(); cout输出二元组:endl; for(int d_i=0;d_idcount;d_i+) coutWordsd_i.num Wordsd_i.lettersendl; coutendl; cout输出标识符:endl; for(int sign_i=0;sign_iid;sign_i+)coutsign_i signsign_iendl; coutendl; cout输出常量:endl
18、;for(int const_i=0;const_ist;const_i+)coutconst_i constantconst_iendl; cout=3 and n5 then j:=j-1; end . 结果截图:六 总结我在这次词法分析器的设计过程中学到了很多东西,其中最大的收获是对于编译原理中的词法分析这一过程理解的更加清楚明了。其次,是在使用c+编程的能力有所提高。当然,在该词法分析器设计中也有一些不足的地方,比如能识别的关键字有限,并不能识别所有的关键字,识别不出字符常量等。分析结果输出方式为:用一个存放结果的字符串数组,并用指针指向它,输出结果正确,但是输出结果比较乱。不过总的来说,这次实验达到了其初衷,实现了规定的功能。八致谢词:感谢xxx老师对我们的悉心教导以及提供我们这样一个学以致用的机会。通过这一阶段对编译原理课程的学习,特别是通过这次对于词法分析器的编程实践,我对于编译原理中的词法分析这一过程理解的更加清楚明了,收获很大。