递归下降语法分析程序的设计说明
递归下降语法分析程序设计

编译方法实验报告实验名称:简单的语法分析程序设计实验要求1.功能:对简单的赋值语句进行语法分析随机输入赋值语句,输出所输入的赋值语句与相应的四元式2.采用递归下降分析程序完成(自上而下的分析)3.确定各个子程序的功能并画出流程图4.文法如下:5.编码、调试通过采用标准输入输出方式。
输入输出的样例如下:【样例输入】x:=a+b*c/d-(e+f)【样例输出】(说明,语句和四元式之间用5个空格隔开)T1:=b*c (*,b,c,T1)T2:=T1/d (/,T1,d,T2)T3:=a+T2 (+,a,T2,T3)T4:=e+f (+,e,f,T4)T5:=T3-T4 (-,T3,T4,T5)x:=T5 (:=,T5,-,x)【样例说明】程序除能够正确输出四元式外,当输入的表达式错误时,还应能检测出语法错误,给出相应错误提示。
6.设计3-5个赋值语句测试实例,检验程序能否输出正确的四元式;当输入错误的句子时,检验程序能够给出语法错误的相应提示信息。
7.报告容包括:递归程序的调用过程,各子程序的流程图和总控流程图,详细设计,3-5个测试用例的程序运行截图及相关说明,有详细注释的程序代码清单等。
目录1.语法分析递归下降分析算法41.1背景知识41.2消除左递归62.详细设计及流程图62.1 函数void V( ) // V -> a|b|c|d|e...|z62.2 函数void A( ) // A -> V:=E72.3 函数void E() //E -> TE'72.4函数void T( ) // T -> FT'82.5函数void E1( ) //E'-> +TE'|-TE'|null82.6函数void T1() // T'-> *FT'|/FT'|null83.测试用例及截图93.1测试用例1及截图93.2测试用例2及截图103.3测试用例3及截图11代码清单111.语法分析递归下降分析算法1.1背景知识无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
语法分析程序(递归下降法)

语法分析程序(递归下降法)班级学号姓名:指导老师:一. 实验目的:1、学习语法分析的主要方法;2、熟悉复习词法分析的方法;3、判断表达式的正确性;4、熟悉C语言并提高动手能力;二. 实验内容:用递归下降分析法编写一个用于判断数学表达式是否正确的语法分析三.实验硬件和软件平台:INTEL C433MHz Cpu128Mb SDRAMTurbo C 2.0Microsoft Windows XP SP1四.步骤和算法描述:1.调用词法分析程序,转换表达式成为内号;2.调用语法分析程序,判断表达式正确与否;五.源程序:#include <stdio.h>#include <string.h>#include <io.h>#define yy swy=adv()FILE *fp1;char ch;int swy;main(){void CS();int chz(char str[15]);int adv();void CT();void E(); void EB();void ERROR();void ET();void F();void IT();void T();void sentence();clrscr();ch=' ';fp1=fopen("pas.txt","r");if(!fp1){printf("Can not open ljx.txt!!\n”); exit(0);}/* while(!feof(fp1)) */{yy;sentence();fclose(fp1);}}void ERROR(){printf("%d ERROR!\n ",swy); }void E(){T();while(swy==34||swy==35){yy;T();}}void T(){F();while(swy==36||swy==37){yy;F();}}void F(){if(swy==21||swy==22) yy;else if(swy==27){yy;E();if(swy==28) yy;else ERROR();}else ERROR();}void sentence(){ switch(swy){case 21 :{yy;if(swy==44){yy;E();}else ERROR();break;}case 1:CS();break;case 8:{yy;EB();if(swy!=4)ERROR();yy;sentence();break;}case 19:{yy;EB();if(swy!=4)ERROR();yy;sentence();}break;case 14:{yy;if(swy!=27) ERROR();yy;IT();if(swy!=28)ERROR();yy;break;}case 20:{yy;if(swy!=27) ERROR();yy;ET();if(swy!=28)ERROR();yy;break;}}}void CS(){yy;sentence();while(swy==24){yy;sentence();}if(swy==6)yy;else ERROR();}void CT(){if(swy==5){yy;sentence();}}void EB(){E();if(swy<=43&&swy>=38){yy;E();}else ERROR();}void IT(){if(swy!=21)ERROR();yy;while(swy==23){yy;if(swy!=21)ERROR();else ERROR();} }void ET(){E();while(swy==23){yy;E();}}int chz(char str1[15]){charstr[21][15]={"and","begin","const","div","do", "else","end","function","if","integer","not","or","pro cdure","program","read","real","then","type","var","while","write"};int i,max,min,mid;for(i=0;i<=14;i++)if(str1[i]<='Z'&&str1[i]>='A')str1[i]=str1[i]+'a'-'A';max=20;min=0;mid=10;while(min<=max){i=strcmp(str1,str[mid]);if(i==0) return mid;elseif(i>0){min=mid+1;mid=(max+min)/2;}else{max=mid-1;mid=(max+min)/2;}}return 0;}int adv(){char str1[15];int t,i=0,sk=0;float num,xs;if(ch==''||swy==24){fscanf(fp1,"%c",&(ch));printf("% c",ch);}while(!feof(fp1)&&i<100){if(((ch)>='a'&&(ch)<='z')||((ch)>='A'&&( ch)<='Z')){i=0;while((((ch)>='a'&&(ch)<='z')||((ch)>='A '&&(ch)<='Z')||((ch)>='0'&&(ch)<='9'))){str1[i]=(ch);i++;{fscanf(fp1,"%c",&(ch));printf("%c",ch);}}str1[i]='\0';t=chz(str1);if(!t)return 21;else return t;}else if(ch>='0'&&ch<='9'){num=0;while(ch>='0'&&ch<='9'){num=num*10+(ch)-'0';{fscanf(fp1,"%c",&(ch));printf("%c",ch); }}if(ch=='.'){xs=0.1;{fscanf(fp1,"%c",&(ch));printf("%c",ch); }while(ch>='0'&&ch<='9'){num+=(ch-'0')*xs;xs*=0.1;{fscanf(fp1,"%c",&(ch));printf("%c",ch); }}}return 22;}switch(ch){case '+' :{ch=' ';return 34;}case '*' :{ch=' ';return 36;}case ',' :{ch=' ';return 23;}case ';' :{ch=' ';return 24;}case '.' :{ch=' ';return 26;}case '(' :{ch=' ';return 27;}case ')' :{ch=' ';return 28;}case '[' :{ch=' ';return 29;}case ']' :{ch=' ';return 30;}case '{' :{ch=' ';return 45;}case '}' :{ch=' ';return 46;}case '-' :{ch=' ';return 35;}case '..' :{ch=' ';return 31;}case '/' :{ch=' ';return 37;}case '#' :{ch=' ';return 47;}case '<' : { {fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 42;}else {return 39;}}case ':' :{{fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 44;}else {return 25;}}case '>' :{{fscanf(fp1,"%c",&(ch));printf("%c",ch);}sk=1;if((ch)=='='){ch=' ';return 44;}else {return 40;}}default:break;}if(sk==0){fscanf(fp1,"%c",&(ch));printf( "%c",ch);}else sk=0;}}。
编译原理语法分析递归下降子程序实验报告

编译原理语法分析递归下降子程序实验报告编译课程设计-递归下降语法分析课程名称编译原理设计题目递归下降语法分析一、设计目的通过设计、编制、调试一个具体的语法分析程序,加深对语法分析原理的理解,加深对语法及语义分析原理的理解,并实现对文法的判断,是算符优先文法的对其进行FirstVT集及LastVT集的分析,并对输入的字符串进行规约输出规约结果成功或失败。
二、设计内容及步骤内容:在C++ 6.0中编写程序代码实现语法分析功能,调试得到相应文法的判断结果:是算符优先或不是。
若是,则输出各非终结符的FirstVT与LastVT集的结果,还可进行字符串的规约,输出详细的规约步骤,程序自动判别规约成功与失败。
步骤:1.看书,找资料,了解语法分析器的工作过程与原理2.分析题目,列出基本的设计思路1定义栈,进栈,出栈函数○2栈为空时的处理○3构造函数判断文法是否是算符文法,算符优先文法○4构造FirstVT和LastVT函数对文法的非终结符进行分析○5是算符优先文法时,构造函数对其可以进行输入待规约○串,输出规约结果○6构造主函数,对过程进行分析3.上机实践编码,将设计的思路转换成C++语言编码,编译运行4.测试,输入不同的文法,观察运行结果详细的算法描述详细设计伪代码如下:首先要声明变量,然后定义各个函数1.void Initstack(charstack &s){//定义栈s.base=new charLode[20];s.top=-1; }2. void push(charstack&s,charLode w){//字符进栈s.top++;s.base[s.top].E=w.E;s.base[s.top].e=w.e;}3. void pop(charstack&s,charLode &w){//字符出栈w.E=s.base[s.top].E; 三、w.e=s.base[s.top].e;s.top--;}4. int IsEmpty(charstack s){//判断栈是否为空if(s.top==-1)return 1;else return 0;}5.int IsLetter(char ch){//判断是否为非终结符if(ch='A'&&ch= 'Z')return 1;else return 0;}6.int judge1(int n){ //judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法}7. void judge2(int n){//judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法8.int search1(char r[],int kk,char a){ //search1是查看存放终结符的数组r中是否含有重复的终结符}9.void createF(int n){ //createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体}10.void search(charLode w){ //search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1 }分情况讨论://产生式的后选式的第一个字符就是终结符的情况//产生式的后选式的第一个字符是非终结符的情况11.void LastVT(int n){//求LastVT}12.void FirstVT(int n){//求FirstVT}13.void createYXB(int n){//构造优先表分情况讨论://优先级等于的情况,用1值表示等于}//优先级小于的情况,用2值表示小于//优先级大于的情况,用3值表示大于}14.int judge3(char s,char a){//judge3是用来返回在归约过程中两个非终结符相比较的值}15.void print(char s[],charSTR[][20],int q,int u,int ii,int k){//打印归约的过程}16. void process(char STR[][20],int ii){//对输入的字符串进行归约的过程}四、设计结果分两大类,四种不同的情况第一类情况:产生式的候选式以终结符开始候选式以终结符开始经过存在递归式的非终结符后再以终结符结束篇二:编译原理递归下降子程序北华航天工业学院《编译原理》课程实验报告课程实验题目:递归下降子程序实验作者所在系部:计算机科学与工程系作者所在专业:计算机科学与技术作者所在班级:xxxx作者学号:xxxxx_作者姓名:xxxx指导教师姓名:xxxxx完成时间:2011年3月28日一、实验目的通过本实验,了解递归下降预测分析的原理和过程以及可能存在的回溯问题,探讨解决方法,为预测分析表方法的学习奠定基础。
设计3语法分析之递归下降分析法剖析

词法分析程序一、设计目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、设计要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>::=begin<语句串>end⑵<语句串>::=<语句>{;<语句>}⑶<语句>::=<赋值语句>⑷<赋值语句>::=ID:=<表达式>⑸<表达式>::=<项>{+<项> | -<项>}⑹<项>::=<因子>{*<因子> | /<因子>⑺<因子>::=ID | NUM | (<表达式>)2.2 实验要求说明输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
例如:输入 begin a:=9; x:=2*3; b:=a+x end # 输出 success!输入 x:=a+b*c end #输出 error三、设计说明(含主要算法的流程图)1、主程序示意图如图2-1所示。
图2-1 语法分析主程序示意图2、递归下降分析程序示意图如图2-2所示。
3、语句串分析过程示意图如图2-3所示。
否是否是否是否图2-3 语句串分析示意图是图2-2 递归下降分析程序示意图4、statement语句分析程序流程如图2-4、2-5、2-6、2-7所示。
否否否是图2-4 statement语句分析函数示意图图2-5 expression表达式分析函数示意图是否否是是否否是图 2-6 term分析函数示意图否是图2-7 factor分析过程示意图5、实验源代码#include "stdio.h"#include "string.h"char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"}; int syn,p,m,n,sum;int kk;factor();expression();yucu();term();statement();lrparser();scaner();main(){p=kk=0;printf("\nplease input a string (end with '#'): \n");do{ scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}lrparser(){if(syn==1){scaner(); /*读下一个单词符号*/yucu(); /*调用yucu()函数;*/if (syn==6){ scaner();if ((syn==0)&&(kk==0))printf("success!\n");}else { if(kk!=1) printf("the string haven't got a 'end'!\n"); kk=1;}}else { printf("haven't got a 'begin'!\n");kk=1;}return;}yucu(){statement(); /*调用函数statement();*/ while(syn==26){scaner(); /*读下一个单词符号*/if(syn!=6)statement(); /*调用函数statement();*/ }return;}statement(){ if(syn==10){scaner(); /*读下一个单词符号*/if(syn==18){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/}else { printf("the sing ':=' is wrong!\n");kk=1;}}else { printf("wrong sentence!\n");kk=1;}return;}expression(){ term();while((syn==13)||(syn==14)){ scaner(); /*读下一个单词符号*/ term(); /*调用函数term();*/}return;}term(){ factor();while((syn==15)||(syn==16)){ scaner(); /*读下一个单词符号*/ factor(); /*调用函数factor(); */ }return;}factor(){ if((syn==10)||(syn==11)) scaner();else if(syn==27){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/if(syn==28)scaner(); /*读下一个单词符号*/else { printf("the error on '('\n");kk=1;}}else { printf("the expression error!\n");kk=1;}return;}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch< ='9'))){token[m++]=ch;ch=prog[p++];}p--;syn=10;token[m++]='\0';for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0) { syn=n+1;break;}}else if((ch>='0')&&(ch<='9')) { while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':m=0;ch=prog[p++];if(ch=='>'){ syn=21;}else if(ch=='='){ syn=22;}else{ syn=20;p--;}break;case '>':m=0;ch=prog[p++];if(ch=='='){ syn=24;}else{ syn=23;p--;}break;case ':':m=0;ch=prog[p++];if(ch=='='){ syn=18;}else{ syn=17;p--;}break;case '+': syn=13; break; case '-': syn=14; break; case '*': syn=15;break; case '/': syn=16;break; case '(': syn=27;break; case ')': syn=28;break; case '=': syn=25;break; case ';': syn=26;break;case '#': syn=0;break;default: syn=-1;break;}}4、运行结果及分析输入 begin a:=9; x:=2*3; b:=a+x end # 后输出success!如图4-1所示:图4-1输入 x:=a+b*c end # 后输出 error 如图4-2所示:图4-2五、总结通过本次试验,了解了语法分析的运行过程,主程序大致流程为:“置初值”调用scaner函数读下一个单词符号调用IrParse结束。
编译原理之递归下降语法分析程序(实验)

编译原理之递归下降语法分析程序(实验)⼀、实验⽬的利⽤C语⾔编制递归下降分析程序,并对简单语⾔进⾏语法分析。
编制⼀个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
⼆、实验原理每个⾮终结符都对应⼀个⼦程序。
该⼦程序根据下⼀个输⼊符号(SELECT集)来确定按照哪⼀个产⽣式进⾏处理,再根据该产⽣式的右端:每遇到⼀个终结符,则判断当前读⼊的单词是否与该终结符相匹配,若匹配,再读取下⼀个单词继续分析;不匹配,则进⾏出错处理每遇到⼀个⾮终结符,则调⽤相应的⼦程序三、实验要求说明输⼊单词串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:输⼊begin a:=9;b:=2;c:=a+b;b:=a+c end #输出success输⼊a:=9;b:=2;c:=a+b;b:=a+c end #输出‘end' error四、实验步骤1.待分析的语⾔的语法(参考P90)2.将其改为⽂法表⽰,⾄少包含–语句–条件–表达式E -> E+T | TT -> T*F | FF -> (E) | i3. 消除其左递归E -> TE'E' -> +TE' | εT -> FT'T' -> *FT' | εF -> (E) | i4. 提取公共左因⼦5. SELECT集计算SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *}SELECT(E'->+TE')=FIRST(+TE')={+}SELECT(E'->ε)=follow(E')=follow(E)={#, )}SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i}SELECT(T'->*FT')=FRIST(*FT')={*}SELECT(T'->ε)=follow(T')=follow(T)={#, ), +}SELECT(F->(E))=FRIST((E)) ={(}SELECT(F->i)=FRIST(i) ={i}6. LL(1)⽂法判断 其中SELECT(E'->+TE')与SELECT(E'->ε)互不相交,SELECT(T'->*FT')与SELECT(T'->ε)互不相交,SELECT(F->(E))与SELECT(F->i)互不相交,故原⽂法为LL(1)⽂法。
递归下降程序实验报告

一、实验目的1. 理解递归下降分析法的原理和实现方法。
2. 掌握递归下降分析程序的设计和调试。
3. 加深对编译原理中语法分析部分的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验内容1. 递归下降分析法原理介绍2. 递归下降分析程序的设计与实现3. 递归下降分析程序的调试与测试四、实验步骤1. 递归下降分析法原理介绍递归下降分析法是一种自顶向下的语法分析方法,它将文法中的非终结符对应为分析过程中的递归子程序。
当遇到一个非终结符时,程序将调用对应的递归子程序,直到处理完整个输入串。
2. 递归下降分析程序的设计与实现(1)定义文法以一个简单的算术表达式文法为例,文法如下:E -> E + T| TT -> T F| FF -> ( E )| id(2)消除左递归由于文法中存在左递归,我们需要对其进行消除,消除后的文法如下:E -> T + E'E' -> + T E' | εT -> F T'T' -> F T' | εF -> ( E ) | id(3)设计递归下降分析程序根据消除左递归后的文法,设计递归下降分析程序如下:```cpp#include <iostream>#include <string>using namespace std;// 定义终结符const char PLUS = '+';const char MUL = '';const char LPAREN = '(';const char RPAREN = ')';const char ID = 'i'; // 假设id为'i'// 分析器状态int index = 0;string input;// 非终结符E的分析程序void E() {T();while (input[index] == PLUS) {index++;T();}}// 非终结符T的分析程序void T() {F();while (input[index] == MUL) {index++;F();}}// 非终结符F的分析程序void F() {if (input[index] == LPAREN) {index++; // 跳过左括号E();if (input[index] != RPAREN) {cout << "Error: Missing right parenthesis" << endl; return;}index++; // 跳过右括号} else if (input[index] == ID) {index++; // 跳过标识符} else {cout << "Error: Invalid character" << endl;return;}}// 主函数int main() {cout << "Enter an arithmetic expression: ";cin >> input;index = 0; // 初始化分析器状态E();if (index == input.size()) {cout << "The expression is valid." << endl;} else {cout << "The expression is invalid." << endl;}return 0;}```3. 递归下降分析程序的调试与测试将以上代码编译并运行,输入以下表达式进行测试:```2 +3 (4 - 5) / 6```程序输出结果为:```The expression is valid.```五、实验总结通过本次实验,我们了解了递归下降分析法的原理和实现方法,掌握了递归下降分析程序的设计与调试。
语法分析递归下降分析法

语法分析递归下降分析法递归下降分析法是一种常用的语法分析方法,它通过构建递归子程序来解析输入的语法串。
该方法可以分为两个步骤:构建语法树和构建语法分析器。
首先,我们需要构建语法树。
语法树是一个表示语言结构的树形结构,它由各类语法片段(非终结符)和终结符组成。
构建语法树的过程就是根据文法规则从根节点开始递归地扩展子节点,直到达到文法推导出的终结符。
具体来说,我们可以通过以下步骤来构建语法树:1.设计满足语言结构的文法规则。
文法规则定义了语法片段之间的关系和转换规则。
2.将文法规则转换为程序中的递归子程序。
每个递归子程序对应一个语法片段,并按照文法规则递归地扩展子节点。
3.设计词法分析器将输入的语法串分词为单个有效的词法单元。
4.从语法树的根节点开始,根据递归子程序逐步扩展子节点,直到达到终结符。
同时,将每一步的扩展结果记录在语法树中。
接下来,我们需要构建语法分析器。
语法分析器是一个根据语法规则判断输入语法串是否符合语法规则的程序。
它可以通过递归下降分析法来实现。
具体来说,我们可以通过以下步骤来构建语法分析器:1.定义一个语法分析器的函数,作为程序的入口。
2.在语法分析器函数中,根据文法规则调用递归子程序,分析输入的语法串。
3.每个递归子程序对应一个语法片段,它会对输入的语法串进行识别和匹配,并根据文法规则进行扩展。
4.如果递归子程序无法匹配当前的输入,那么意味着输入的语法串不符合文法规则。
5.如果递归子程序成功扩展,并继续匹配下一个输入,则语法分析器会一直进行下去,直到分析完整个语法串。
总结起来,递归下降分析法是一种简单而有效的语法分析方法。
它通过构建递归子程序来解析输入的语法串,并构造出对应的语法树。
虽然递归下降分析法在处理左递归和回溯等问题上存在一定的困难,但它仍然是一种重要的语法分析方法,被广泛应用于编译器和自然语言处理等领域。
语法分析——递归下降分析法

实验2 语法分析——递归下降分析法一、实验目的1、通过该课程设计要学会用消除左递归的方法来使文法满足进行确定自顶向下分析的条件。
2、学会用C/C++高级程序设计语言来设计一个递归下降分析法的语法分析器;3、通过该课程设计,加深对语法分析理论的理解,培养动手实践的能力。
二、设计内容参考算数运算的递归子程序构造方法及代码,完成以下任务:构造布尔表达式的文法,并编写其递归子程序。
程序设计语言中的布尔表达式有两个作用,一是计算逻辑值,更多的情况是二,用作改变控制流语句中条件表达式,如在if-then,if-then-else或是while-do 语句中使用。
布尔表达式是由布尔算符(and,or,not)施予布尔变量或关系运算表达式而成。
为简单起见,以如下文法生成的布尔表达式作为设计对象:E→E and E | E or E | not E | i rop i | true | falsei→标识符|数字rop→>= | > | <= | < | == | <>以上文法带有二义性,并且未消除左递归,请对之处理后,再构造递归下降程序。
可适当减少工作量,暂时忽略id的定义,输入时直接用数字或字母表示。
三、语法分析器的功能该语法分析器能够分析词法分析器的结果,即单词二元式。
在输入单词二元式后,能输出分析的结果。
四、算法分析1、语法分析的相关知识;2、递归子程序法的相关理论知识;3、根据递归子程序法相关理论,具体针对文法的每一条规则编写相应得递归子程序以及分析过程等。
//在递归子程序的编写过程中,当要识别一个非终结符时,需时刻留意该非终结符的FIRST集与FOLLOW集。
程序示例一:G:P→begin d;X end G’:P→begin d;X endX→d;X|Y X→d;X|YY→Y;s|s Y→sZ Z→;sZ|ε相应的递归子程序设计如下:P(){ if(token==“begin“){ Read(token);If(token==’d’)Read(token);ElseERROR;If (token==’;’)Read(token);ElseERROR;If (token==’d’ || ‘s’)X();Else ERROR;If(token==’end’) OK;}Else ERROR;}X() //X→d;X|Y{if(token==’d’){read(token);if(token==’;’)read(token);elseERROR;If(token==’d’)X();Else if (token==’s’) //注意:对Y的识别也可以是在X的过程中一开始就进行,所以在最外层分支中,加上一个token==s的分支Y();Else ERROR;}Else ERROR;}Y() //Y→sZ{if(token==’s’){read(token);If(token==’;’ || ‘end’)Z();Else ERROR;Else ERROR;}Z() //Z→;s Z|ε{if(token==’;’){read(token);If(token==’s’)Read(token);Else ERROR;If(token==’;’)Z();Else if (token==’end’) // 类似的,这里对于读到end,也要最外层添加一个分支Return;Else ERROR;}Else ERROR;}程序示例二(参考代码):构造文法G[E]:E→E + T | T T→T * F | F F→(E)| d的递归子程序(即语法分析器)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译方法实验报告实验名称:简单的语法分析程序设计实验要求1.功能:对简单的赋值语句进行语法分析随机输入赋值语句,输出所输入的赋值语句与相应的四元式2.采用递归下降分析程序完成(自上而下的分析)3.确定各个子程序的功能并画出流程图4.文法如下:5.编码、调试通过采用标准输入输出方式。
输入输出的样例如下:【样例输入】x:=a+b*c/d-(e+f)【样例输出】(说明,语句和四元式之间用5个空格隔开)T1:=b*c (*,b,c,T1)T2:=T1/d (/,T1,d,T2)T3:=a+T2 (+,a,T2,T3)T4:=e+f (+,e,f,T4)T5:=T3-T4 (-,T3,T4,T5)x:=T5 (:=,T5,-,x)【样例说明】程序除能够正确输出四元式外,当输入的表达式错误时,还应能检测出语法错误,给出相应错误提示。
6.设计3-5个赋值语句测试实例,检验程序能否输出正确的四元式;当输入错误的句子时,检验程序能够给出语法错误的相应提示信息。
7.报告容包括:递归程序的调用过程,各子程序的流程图和总控流程图,详细设计,3-5个测试用例的程序运行截图及相关说明,有详细注释的程序代码清单等。
目录1.语法分析递归下降分析算法 (5)1.1背景知识 (5)1.2消除左递归 (6)2.详细设计及流程图 (6)2.1 函数void V( ) // V -> a|b|c|d|e...|z . (6)2.2 函数void A( ) // A -> V:=E (7)2.3 函数void E() //E -> TE' (7)2.4函数void T( ) // T -> FT' (8)2.5函数void E1( ) //E'-> +TE'|-TE'|null (8)2.6函数void T1() // T'-> *FT'|/FT'|null (9)3.测试用例及截图 (9)3.1测试用例1及截图 (9)3.2测试用例2及截图 (10)3.3测试用例3及截图 (11)代码清单 (11)1.语法分析递归下降分析算法1.1背景知识无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
无左递归:既没有直接左递归,也没有间接左递归。
无回溯:对于任一非终结符号U的产生式右部x1|x2|…|xn,其对应的字的首终结符号两两不相交。
如果一个文法不含回路,也不含以ε为右部的产生式,那么可以通过执行消除文法左递归的算法消除文法的一切左递归(改写后的文法可能含有以ε为右部的产生式)。
文法的左递归消除算法:1、将文法G的所有非终结符排序为U1 ,U2 ,… ,Un;2、For(i=1;i++;i≥n){for j→1 to i-1把产生式Ui→Ujα替换成Ui→β1α| β2α|…|βmα;其中:Uj→ β1| β2 |… |βm 消除Ui产生式中的直接左递归;}3.化简改写之后的文法,删除多余产生式。
文法的直接左递归消除公式:直接左递归形式:U→Ux|y;其中:x,y∈(V N∪V T)* ,y不以U打头。
直接左递归的消除:U→yU‟U‟→xU‟|ε直接左递归的一般形式:U→Ux1|Ux2|…|Ux m|y1|y2|…|y n;其中:x i≠ε ,y i都不以U打头。
一般形式直接左递归的消除:U→y1U‟| y2U‟|…| y n U‟U‟→x1U‟| x2U‟| …| x m U‟|ε回溯的消除的前提是文法不得含有左递归,可提左因子来消除回溯。
1.2消除左递归根据实验中给出的文法,进行消除左递归及回溯,得到下列的式子A -> V:=EE -> TE'E'-> +TE'|-TE'|nullT -> FT'T'-> *FT'|/FT'|nullF -> V|(E)V -> a|b|c|d|e...|z2.详细设计及流程图根据消除左递归后的文法,可以编写相应的函数。
2.1 函数void V( ) // V -> a|b|c|d|e...|zvoid V() // V -> a|b|c|d|e...|z函数设计主要用来识别小写字母的,如果是小写字母的话,放入字符表,不是的话,输出语法错误。
函数比较简单,代码如下:if(islower(s[sym])){Table[list_n][0] = s[sym]; //把读取的小写字母存入符号表,便于分析是生成中间代码Table[list_n][1] = '\0';list_n++;sym++;}else{printf("Operand Errors!\n"); //运算对象错误SIGN=1;exit(0);}2.2 函数void A( ) // A -> V:=Evoid A() // A -> V:=E 函数主要用来实现赋值的操作,流程图如图1所示。
开始V( )s[sym]==':'&&s[sym+1]=='='sym+=2;E( );Y输出表达式N输出错误结束图1 A( ) 函数流程图2.3 函数void E() //E -> TE'函数E()里面主要递归调用函数T( )和E'( )。
当没有出现语法错误时就可正常的运行。
函数比较简单,代码如下:{if(SIGN==0){T();E1();}}2.4函数void T( ) // T -> FT'函数T( )里面主要递归调用函数F ( )和T''( )。
当没有出现语法错误时就可正常的运行。
函数比较简单,代码如下:if(SIGN==0){F();T1();}2.5函数void E1( ) //E'-> +TE'|-TE'|null函数void E1() //E'-> +TE'|-TE'|null,主要用来实现加减法的语义分析。
流程图如图2所示。
开始SIGN==0s[sym] == '+'||s[sym]=='-'输出三地址式和四元表达式p=sym; sym++T()Y E1()结束NN图2 E1 ( ) 函数流程图2.6函数void T1() // T'-> *FT'|/FT'|null函数void T1() // T'-> *FT'|/FT'|null ,主要用来实现乘除法的语义分析。
流程图如图3所示。
开始SIGN==0s[sym] == '*'||s[sym]=='/'输出三地址式和四元表达式p=sym; sym++F()Y T1()结束NN图3 T1 ( ) 函数流程图3.测试用例及截图3.1测试用例1及截图用例1为实验要求上的的用例。
测试结果图4所示。
图4 测试用例1及结果截图3.2测试用例2及截图用例2为出现大写字母,出现报错。
测试结果图5所示。
图5 测试用例2及结果截图3.3测试用例3及截图用例3为随意编写用例。
测试结果图6所示。
图6 测试用例3及结果截图代码清单#include<stdio.h>#include<stdlib.h>#include<string.h>#include <ctype.h>void A(); // A -> V:=Evoid E(); // E -> TE'void T(); // T -> FT'void E1(); // E'-> +TE'|-TE'|nullvoid T1(); // T'-> *FT'|/FT'|nullvoid F(); // F -> V|(E)void V(); // V -> a|b|c|d|e...|zchar s[50],n='1'; //s[50]用于存放输入的赋值表达式char Table[50][3]; //产生中间代码所需的符号表int SIGN,sym; //sym为s[50]中当前读入符号的下标int list_n=0; //符号表的下标/*消除左递归及回溯A -> V:=EE -> TE'E'-> +TE'|-TE'|nullT -> FT'T'-> *FT'|/FT'|nullF -> V|(E)V -> a|b|c|d|e...|z*/int main(){SIGN = 0; //SIGN用于指示赋值表达式是否出现错误sym=0;scanf("%s",&s);if( s[0] == '\0') //没有输入的情况直接退出return 0;A();if(s[sym]!='\0'&&SIGN==0){printf("ERROR!\n");exit(0);}return 0;}void A() // A -> V:=E{V();if(s[sym]==':'&&s[sym+1]=='=') //判断赋值号是否有拼写错误{sym+=2;E();printf("%s:=%s",Table[list_n-2],Table[list_n-1]);printf(" (:=,%s,-,%s)\n",Table[list_n-1],Table[list_n-2]);}else{printf("The assignment Symbol spelling mistakes!\n"); //赋值号拼写错误SIGN=1;exit(0);}}void V() // V -> a|b|c|d|e...|z{if(islower(s[sym])){Table[list_n][0] = s[sym]; //把读取的小写字母存入符号表,便于分析是生成中间代码Table[list_n][1] = '\0';list_n++;sym++;}else{printf("Operand Errors!\n"); //运算对象错误SIGN=1;exit(0);}}void E() //E -> TE'{if(SIGN==0){T();E1();}}void T() // T -> FT'{if(SIGN==0){F();T1();}}void E1() //E'-> +TE'|-TE'|null{int p;if(SIGN==0){if(s[sym] == '+'||s[sym]=='-'){p=sym; //用p记录出现'+'或'-'时sym的值sym++;T();char ch[3];ch[0] = 'T';ch[1] = n;ch[2] = '\0';if(s[p] == '+'){printf("%s:=%s+%s",ch,Table[list_n-2],Table[list_n-1]); //输出三地址代码printf(" (+,%s,%s,%s)\n",Table[list_n-2],Table[list_n-1],ch); //输出四元式}else{printf("%s:=%s-%s",ch,Table[list_n-2],Table[list_n-1]); //输出三地址代码printf(" (-,%s,%s,%s)\n",Table[list_n-2],Table[list_n-1],ch); //输出四元式}strcpy(Table[list_n-2],ch); //将当前结果归结式放在符号表中list_n--;n++;E1();}}}void T1() // T'-> *FT'|/FT'|null{int p;if(SIGN==0){if(s[sym] == '*'||s[sym]=='/'){p=sym;sym++;F();char ch[3];ch[0] = 'T';ch[1] = n;ch[2] = '\0';if(s[p] == '*'){printf("%s:=%s*%s",ch,Table[list_n-2],Table[list_n-1]); //输出三地址代码printf(" (*,%s,%s,%s)\n",Table[list_n-2],Table[list_n-1],ch);//输出四元式}else{printf("%s:=%s/%s",ch,Table[list_n-2],Table[list_n-1]); //输出三地址代码printf(" (/,%s,%s,%s)\n", Table[list_n-2],Table[list_n-1],ch);//输出四元式}strcpy(Table[list_n-2],ch); //将当前结果归结式放在符号表中list_n--;n++;T1();}}}void F() //F -> V|(E){if(SIGN==0){if(s[sym]=='('){sym++;E();if(s[sym]==')')sym++;else{printf("ERROR!\n");SIGN=1;exit(0);}}else if(islower(s[sym])) //判断s[sym]是否是小写字母V();else{printf("ERROR!\n");SIGN=1;exit(0);}}}。