编译原理实验报告词法分析器和LL1文法.doc
-编译原理课程综合性实验报告开课实验室: 实验题目词法分析器的设计一、实验目的通过设计、编制、调试一个具体的词法分析程序,实现对高级程序设计语言源程序进展扫描, 并将其分解为各种单词的词法分析法;加深对课堂教学的理解;提高词法分析法的实践能力。二、实验要求任选一种高级程序设计语言编程完成词法分析器。词法分析器应以教材所述分词原理为依据,使用恰当的数据构造和法,构造清晰、高效。编制一个读单词过程,源程序保存在文本文件中也可键盘输入,读取该文件,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、分界符五大类。依次输出各个单词的部单词种别及单词符号自身值,遇到错误时可显示“Eorror,然后跳过错误局部继续显示。二、实验设备与环境1硬件:PC机Pentium100以上。2软件:Win10,VS2010。三、实验容1正规文法<关键字>-> int |for| while | do | return | break | continue<运算符和界符>->|+ | - | * | / |=| < | <=|!=| > | >= |,| ; | ( | ) |<标识符>-> letter (letter | digit)*<整型常数>-> digit digit*2算法思想算法的根本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其根本思想是根据扫描到单词符号的第一个字符的种类,拼接出相应的单词符号。2.1 主程序置初值调用扫描子程序将结果存入构造体输入串完毕 否 是 输出单词二元组完毕图1词法分析主程序示意图其中初始包括关键字、运算符、界限符的置初值。 2.2 扫描子程序的算法思想:在词法分析中,先以只读式读取一个文件,自文件头开场扫描文本,滤去开头的空格、回车符、换行符等。读取的字符送入word。扫描第一个字符,看匹配的类型,并进展相应的类型分析,满足判断类型时,输出其种别码和值。忽略空格te*t是否扫描完毕 返回 是 是否字母拼字符串 数字 其他运算符、 符号界符等符号是否关键字.返回拼数 否4/5,单词自身值报错2,单词自身值 是1,单词自身值3,单词自身值图 2 扫描子程序四、实验步骤编写程序时,先定义几个全局变量,key事先存放7个关键字,words用来存放识别出来的单词二元组,te*t用来存放从文件读取的容,word用于存放识别出来的单词,length存放字符个数,k存放识别出来的单词个数。首先,将文本容读取到te*t中,文本容最后一个字符是空白符,然后调用scan法,逐个扫描每个字符,如果word的第一个字符是字母,则进展拼字符串,再判断是关键字还是标识符;如果word的第一个字符是数字,则在word清空之前判断是否有识别出非数字字符,假设有,则出错,假设没有,则识别出来的字符串是常数;假设word第一个字符是运算符或界限符,则各自存到words中。最后扫描完毕后输出。五、实验结果及分析六、实验小结和思考通过这次实验,我对词法分析器有了进一步的了解,而且对词法分析和语法分析在实践中的应用有了深入的掌握, 让我对高级语言的学习有了更深的认识 ,了解得更透彻。七、源程序清单*include<stdio.h>*include<stdlib.h>*include<string>usingnamespace std;*define MA* 10000struct WordString string Word;/单词int category;/类别 ;char *key7 = "int","for", "while", "do", "return", "break", "continue"/关键字 WordString wordsMA*; /创立一个单词符号串 string te*t; /读入的文本存入te*t中 string word; /分割出的单词用word表示int length; /字符个数int k; /总单词个数void scan() int i,j; k=0; word="for(i=0;i<=length-1;i+) if(word!=")if(word0>='A')&&(word0<='Z')|(word0>='a')&&(word0<='z')/首字符是字母 if(te*ti>='A')&&(te*ti<='Z')|(te*ti>='a')&&(te*ti<='z')|(te*ti>=48)&&(te*ti<=57) word+=te*ti; else wordsk.Word=word;for(j=0;j<7;j+)if(wordsk.Word=keyj)wordsk.category=1;/表示关键字break;elseif(j=6)wordsk.category=2;/表示标识符k+;word="i-; elseif(word0=','|word0=''|word0=''|word0=''|word0='('|word0=')')/首字符是界限符 wordsk.Word=word; wordsk.category=5;/表示界限符 k+; word=" i-; elseif(word0='+'|word0='-'|word0='*'|word0='/'|word0='='|word0='>'|word0='<'|word0='!')/首字符是运算符 if(te*ti='=') word+=te*ti;wordsk.Word=word;wordsk.category=4;/表示运算符k+;word=" else wordsk.Word=word; wordsk.category=4;/表示运算符 k+; word=" i-; elseif(word0>=48&&word0<=57)/首字符是数字 if(te*ti>=48&&te*ti<=57) word+=te*ti; elseif(te*ti>='A'&&te*ti<='Z')|(te*ti>='a'&&te*ti<='z') word+=te*ti; wordsk.category=6;/表示出错,标识符以数字开头 else wordsk.Word=word;if(wordsk.category!=6) wordsk.category=3;/表示常数 k+; word=" i-; elseif(te*ti!=10&&te*ti!=32&&te*ti!=9)word+=te*ti; int main() FILE *fp; /文件指针 fp=fopen("te*t.t*t","r"); /翻开文件if(fp=NULL) printf("Can't open this file!n"); e*it(0); int i=0;while(!feof(fp) /判断是否到文件结尾 te*t+=fgetc(fp); i+; length=i;/te*t最后一个字符是空字符 fclose(fp); /关闭文件 scan();for(i=0;i<k;i+) /输出 if(wordsi.category=6) printf("%s Eorrorn",wordsi.Word.c_str();else printf("(%d, %s)n",wordsi.category,wordsi.Word.c_str(); getchar();return 0;开课实验室:C210 2016年 12月 8日实验题目语法分析LL(1)语法分析法的实现一、实验目的通过设计、开发一个高级语言的LL1语法分析程序,实现对源程序的语法检查和构造分析,加深对相关课堂教学容包括自顶向下语法分析、First集、Follow集、Select集、判断LL1文法的法、文法等价变换、LL(1)分析表的构造、对*一输入串的分析过程的理解,提高语法分析法的实践能力。二、实验要求消除直接左递归前的文法 消除直接左递归后的等价文法 G E:EE+T GE: ETE ET E+TE| TT*F TFT TF T*FT| F(E)|i F(E)|i根据文法建立LL(1)分析表,并对输入串i+i*i进展语法分析,判断其是否是合法的句子,给出句子的分析过程。具体要求如下:1、理解语法分析在编译程序中的作用;2、理解LL(1)语法分析法对文法的要求(必须是LL(1)文法); 3、理解LL(1)分析器模型;4、熟练掌握文法变换法(消除直接左递归和提取左公共因子)。5、熟练掌握Select集合的求解法和LL(1)分析表的构造法;二、实验设备与环境1硬件:PC机Pentium100以上。2软件:Win10,VS2010。三、实验容给定一个上下文无关文法G,在LL(1)语法分析法中,必须先求出Select集,通过Select集判断是否是LL(1)文法,假设是,则构造预测分析表。求出预测分析表之后,键盘输入一个字符串,依据LL(1)分析表单步输出字符串的分析过程。四、实验步骤 输入字符串和初始符号栈符号栈大小大于等于0. N待分析字符是否为合法字符. Y Y N栈顶字符是否为合法字符. Y N待分析字符是否和符号栈栈顶字符相等. N Y待分析字符和栈顶字符同时为“*对照分析表判断采用产生式 Y 分析成功产生式右部为空. Y N匹配分析字符分析下一个字符弹出栈顶符号,不压入栈弹出栈顶符号,产生式右部逆序入栈 N修改栈大小修改栈大小五、实验结果及分析六、实验小结和思考本实验加深了我对 LL(1)分析法的算法和思想的理解。七、源程序清单*include<string.h>*include<stdio.h>*include<stdlib.h>*include<conio.h>/*1:E->TE' 2:E'->+TE' 3:E'->? 4:T->FT' 5:T'->*FT' 6:T'->? 7:F->(E) 8:F->i*/int ll156=1,0,0,1,0,0,0,2,0,0,3,3,4,0,0,4,0,0,0,6,5,0,6,6,8,0,0,7,0,0;/表示LL(1)分析表容int main()char ch10='*','E' /用于存放符号栈容char str10; /存放输入串char str110; /用于存放最初输入的字符串char cha; /分析字符int i,j,m,n; /j:终结符所代表数字;m:非终结符所代表数字;n:产生式右部大小int l=1; /符号栈大小int k=1; /分析输入串的第几个字符int how; /利用哪个产生式int step=1; /步骤int length=0;printf("请输入一串字符串,以*结尾:");doscanf("%c",&cha);strlength=cha;str1length=cha;length+;while(cha!='*');printf("步骤t符号栈tt输入串tt所用产生式n");docha=str1k-1;printf("%dt",step);for(i=0;i<=l;i+)printf("%c",chi); /输出符号栈printf("tt");for(i=k-1;i<length;i+) printf("%c",stri);printf("tt");switch(cha)case'i':j=0;break;case'+':j=1;break;case'*':j=2;break;case'(':j=3;break;case')':j=4;break;case'*':j=5;break;defult:j=-1;break;if(j!=-1) /正确的字符if(chl!=cha)if(chl!=39)switch(chl)case'E':m=0;break;case'T':m=2;break;case'F':m=4;break;default:m=-1;break;elseswitch(chl-1)case'E':m=1;break;case'T':m=3;break;default:m=-1;break;if(m!=-1)if(chl!=cha)how=ll1mj;if(how=1)printf("E->TE'n");n=3;l=l+n-1;chl='T'chl-1=39;chl-2='E'step=step+1;elseif(how=2)printf("E'->+TE'n");n=4;l=l+n-2;chl='+'chl-1='T'chl-2=39;chl-3='E'step=step+1;elseif(how=3)printf("E'->?n");l=l-2;step=step+1;elseif(how=4)printf("T->FT'n");n=3;l=l+n-1;chl='F'chl-1=39;chl-2='T'step=step+1;elseif(how=5)printf("T'->*FT'n");n=4;l=l+n-2;chl='*'chl-1='F'chl-2=39;chl-3='T'step=step+1;elseif(how=6)printf("T'->?n");l=l-2;step=step+1;elseif(how=7)printf("F->(E)n");n=3;l=l+n-1;chl='('chl-1='E'chl-2=')'step=step+1;elseif(how=8)printf("F->in");n=1;l=l+n-1;chl='i'step=step+1;elseprintf("错误!n");break;elseif(cha='*' && chl='*')printf("成功!n");break;elseprintf("n");l=l-1;k=k+1;step=step+1;elseprintf("错洙?误ó!");break;else/错误的字符printf("错误的字符!");break;while(l>=0);getch();return 0;. z.