编译原理词法分析五种类别识别程序含实现代码cpp

更新时间:2023-11-19 15:28:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验一 词法分析

一、实验目的和要求

通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)

二、实验过程

(1)程序思路

这里以开始定义的C语言子集的源程序作为词法分析程序的输入数据。在词法分析中,自文件头开始扫描源程序字符,一旦发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查填适当的信息表。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。

0.定义部分:定义常量、变量、数据结构。

1.初始化:从文件将源程序全部输入到字符缓冲区中。 2.取单词前:去掉多余空白。 3.取单词后:去掉多余空白。

4.取单词:利用实验一的成果读出单词的每一个字符,组成单词,分析类型。循环取字符,直到遇到“#”字符就停止扫描。 5.显示结果。 (2)程序实现部分代码

char *table[7]={\ //定义关键字 char *table1[5]={\ //定义运算符符号 int lookup(char *TOKEN) //关键字匹配函数,查询所述程序中的关键字 { int m,i;

for(i=0;i<=6;i++) { if((m=strcmp(TOKEN,table[i]))==0) return 1; }

return 0; }

int lookup1(char *TOKEN) //判断>= <= != ==,方法与lookup()相似 int lookup2(int i,char *TOKEN) //判断数字加字母的情况 {

int j;

for(j=1;j='a'||TOKEN[j]>='A') return 1; }

return 0; }

bool zimu(char ch) //bool类型函数,判断是否为字母 {

if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z') return true; else return false; }

bool shuzi(char ch) //判断是否为数字,方法与zimu()类似 bool fuhao(char ch) //判断双字符 {

if(ch=='+'||ch=='>'||ch=='<'||ch=='!'||ch=='=') return true; else return false; }

void out(int c,char *TOKEN) //输出函数形式为(c,“TOKEN”) {

printf(\\\n\}

void scanner(FILE *fp) //扫描函数 {

char TOKEN[20]={'\\0'}; int i;

ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符 if(zimu(ch)) //判断该字符是否是字母 { TOKEN[0]=ch; ch=fgetc(fp); //fgetc(fp)从数据流中读取一个字符 i=1; while(shuzi(ch)|| zimu(ch)) //判断该字符是否是字母或数字 { TOKEN[i]=ch; ch=fgetc(fp); i++; } fseek(fp,-1,1); if(lookup(TOKEN)) //判断是关键字还是普通的标识符 out(1,TOKEN); else out(2,TOKEN); }

else if(shuzi(ch)) { TOKEN[0]=ch; ch=fgetc(fp); //fgetc(fp)从数据流中区下一个字符

i=1; while(shuzi(ch)||zimu(ch)) //判断该字符是否是字母或数字 { TOKEN[i]=ch; ch=fgetc(fp); i++; }

fseek(fp,-1,1); if(lookup2(i,TOKEN)) //如果出现2a的情况下,判断为错误语法 printf(\\\n\ else out(3,TOKEN); }

else if(fuhao(ch)) //符号函数,用来判断是否是双运算符 { TOKEN[0]=ch; ch=fgetc(fp); i=1; while(fuhao(ch)) { TOKEN[i]=ch; ch=fgetc(fp); i++; } fseek(fp,-1,1);

//调用lookpu1()判断符号是否为table1[5]里的双运算符 if(lookup1(TOKEN))

out(4,TOKEN); else out(4,TOKEN); }

//判断一般运算符,一般运算符有+、-、*、/、=等,这里以“+”为例 else if(ch=='+') { TOKEN[0]=ch; out(4,TOKEN); }

//判断分隔符,分隔符有,、;、{、}、[、]、(、)等,这里以“;”为例 else if(ch==';') { TOKEN[0]=ch; out(5,TOKEN); } }

//main()函数在此省略

三、调试错误

在程序初步完成时,运行程序就出现了错误,文件读取错误,后来仔细分析了mian()函数的代码,也没有检查出来什么,别人的这种错误都是因为把文件名写成了123.txt.txt,我的并没有这种错误还是打不开,最后还是看了看前面的代码,发现在判断数字的函数那里我把并且符号&&写成了或者符号||,改正之后程序正常运行。除此还有像双运算符无法识别,那是因为我没有写有关的代码,最后补充了lookup2()还定义了table1[5],用来判断是否出现双运算符的情况,经过调试,双运算符也识别成功。

四、实验结果

测试数据:

D盘的一个名为123.txt文本文件里的内容如下:

main() {

int a,b1; b1=10; a<=b1; }#

运行结果:

运行结果如图1所示,可看出,像<=双字符以及2b1这样的错误语法都给分析了出来,算是达到了预期的效果。

图1 运行结果

五、实验总结

本实验是为了完成词法分析,正好是编译原理这门课程的理论到实践的一个机会。原本是怀着期待的心情等到这堂课的,但是看到老师给出的要求,自己要实现功能却一点思路都没有,感觉无从下手。还好老师给出了一大部分的代码,我们只需补充完整就好,这样对于我们来说就轻松了不少。

刚下手时就开始查资料,翻书,了解老师给出代码中出现的不同函数的作用,其中最多的也就是关于文件的函数,了解了整体框架后就好办了,整体有了一点思路,我只需把判断代码补充好就行。所以,根据老师给出的判断关键字的函数lookup(),我模仿写了关于判断双运算符号的函数lookup1(),又根据zimu()和shuzi()补充了判断一个字符是字母还是数字的这两个函数。if(zimu(ch))是用来判

断一个字符是不是字母,进而判断它后面的字符是数字还是字母,直到扫描到非字母非数字,再去调用lookup()函数此字符串是不是关键字,是关键字就输出(1,TOKEN),不是关键字就是普通标示符则输出(2,TOKEN);根据zimu()我又添加了else if(shuzi(ch))用来判断一个字符是不是数字,知道扫描到的下一个字符是非数字借书扫描输出(3,)TOKEN;接着再写else if(fuhao())用来判断一个字符是不是一般的运算符号,是则输出(4,TOKEN);最后又补充了几个关于一般的运算符号以及分隔符的判断函数。再结合mian函数,程序基本上就算是完成了。但是还有很多细节没有涉及到,像<=这样的双运算符还有像2a这样的错误代码的判断还没有涉及到,关于2a的这种情况就是在判断完数字后在判断下一个字符是否是数字或者字母,如果是字母就输出错误形式(error,TOKEN),如果还是数字那就是纯数字属于第三类,输出(3,TOKEN),这样就把判断函数给补充完整了,这样的程序才更完善。其中有些特殊的运算符像::或者其他错误的特殊符号此程序中并没有全部涉及到,但是是可以手动添加的,也就是说此程序的扩展性很好。

在程序实现的过程中,很必然的出现了很多错误,最后也都一一解决了,有关遇到的问题在调试错误这部分已具体列出。总的来说,这次程序的实现并不是很顺利,最后也达到了效果,不过这其中的过程还是让我学到了很多。虽然已经距离学习C++有很长一段时间了,但这个语言在计算机专业还是有一定作用的,它其中有关的函数还有很多是我不知道的,在这一方面应该加强学习。此外还有关于编译原理这门课程的,很明显,这门课程对我们了解程序的编译问题起到了很好的作用,很有学好的必要,以后我肯定会更加努力的学习其中的理论知识和理论方法,以便对我以后的工作提供良好的帮助。

本文来源:https://www.bwwdw.com/article/39ov.html

Top