递归下降语法分析程序设计
递归下降法
试构造一个识别该文法句子的递归下 降分析程序。
递归下降分析法
分析 首先消去文法左递归,得到文法 G'[E]
E→E + T |T T→T * F |F
F→(E) | id
E → TE' E'→ +TE' | ε T → FT' T'→ *FT' | ε F → (E) | id
T( ); E'( ); }
E'( )
E → TE'
{
E' → +TE' | ε
if (sym = =‘+’) {
GetSym( );
T → FT ' T ' → *FT ' | ε
F → (E) | id
T();
E ( );
}
else if ((sym!=‘)’)&&(sym!=‘#’))
error( );
递归下降分析法
递归下降分析法是确定的自上 而下分析法,这种分析法要求文 法是LL(1)文法。
递归下降分析法
基本思想 对文法中的每个非终结符编写一个函
数 (或子程序), 每个函数(或子程序)的 功能是识别由该非终结符所表示的语法成 分。由于描述语言的文法常常是递归定义 的,因此相应的这组函数(或子程序)必 然以相互递归的方式进行调用,所以将此 种分析法称为递归下降分析法。
F→ (E) | id
递归下降分析法
该文法是LL(1)文法,其递归下降分 析程序中主函数和函数F( )同上,对函 数E( )和函数T( )用while语句描述如下:
编译原理 递归下降词法分析
编译原理实验报告—递归下降分析法程序实验2.1 递归下降分析法一、实验目的1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。
2. 本次实验的目的是加深对递归下降分析法的理解。
二、实验平台Windows + VC++6.0范例程序: “递归下降分析法.cpp ”三、实验内容对下列文法,用递归下降分析法对任意输入的符号串进行分析:(1)E→TG(2)G→+TG|-TG(3)G→ε(4)T→FS(5)S→*FS|/FS(6)S→ε(7)F→(E)(8)F→i1.程序功能:输入: 一个以# 结束的符号串(包括+ - * / ()i # ):例如:i+i*i-i/i#输出:(1) 详细的分析步骤,每一步使用的产生式、已分析过的串、当前分析字符、剩余串,第一步, 产生式E->TG的第一个为非终结字符,所以不输出分析串,此时分析字符为i,剩余字符i+i*i-i/i#;第二步,由第一步的E->TG的第一个为非终结字符T,可进行对产生式T->FS 分析,此时第一个仍为非终结字符F,所以不输出分析串,分析字符仍为i, 剩余字符i+i*i-i/i#;第三步,使用产生式F->i,此时的分析串为i,,分析字符为i,匹配成功,剩余字符串+i*i-i/i#;第四步,因为使用了产生式T->FS,F->i,第一个字符i匹配成功,接着分析字符+,使用产生式S->ε,进行下步;第五步,使用产生式G->+TG,此时的分析串包含i+,分析字符为+,剩余字符串+i*i-i/i#;第六步,重复对产生式T->FS,F->i的使用,对第二个i进行匹配,此时分析串i+i,分析字符为i,剩余串*i-i/i#;第七步,分析字符*,使用产生式S->*FS, 分析串i+i*,剩余串i-i/i#;第八步,字符*匹配成功后,使用产生式F->i,匹配第三个字符i,,此时剩余串-i/i#;第九步,分析字符-,只有产生式G->-TG可以产生字符-。
递归下降法
递归下降法递归下降法是一种能够解决CFG(上下文无关文法)中文法制导翻译方法,它是程序设计语言翻译中常用的算法之一。
它是一种分析工具,可以将源程序转换成更简化的表示形式,有助于实现高效编译。
递归下降法本质上是一种递归算法,又被称为递归前行法。
它是一种将一个文法应用到有括号结构的句子中的一种方法,利用递归的概念,将文法的对应句子的分析过程反映到源程序中,实现源程序的分析。
首先,基于CFG,递归下降法使用了文法的结构体,其构成元素有符号表,文法规则,产生式,终结符号和非终结符号,等等。
递归下降法从高层次上分析文法,它将文法结构条件分解为可以分析的符号表,对每一个符号提出文法规则,由此可以实现编译器的分析和转换。
第二,递归下降法可以利用递归的概念,从高层次的文法分析过程得出底层符号的实现方式。
比如文法:A→BB,如果B仅仅是一个终结符号,可以将其分析为A→BC,将文法分解,再对终结符号进行分析,直到将所有的终结符号分析完毕。
再者,递归下降法能够找到源程序中不符合文法要求的语句,可以更精确地指出源程序中的错误。
比如在语法分析的过程中,如果碰到与文法不符的句子,就能发现错误,及时给出报错信息,从而纠正错误。
最后,递归下降法是一种全面的语法分析算法,不仅可以用于语法分析,也可以用于语义分析。
它利用文法规则来确认每一个单词语句结构,并检测单词是否符合文法,通过这种检测,可以有效率地进行语义分析,找出语法错误,有助于源程序翻译的准确性和正确性。
总之,递归下降法是一种非常有用的文法分析算法,它主要用于解决CFG中的文法制导翻译任务,能够解决句子的分析,语义分析,出错检测等问题,能够精确控制源程序的正确性和准确性,是程序设计翻译中必不可少的算法之一。
递归下降语法分析程序设计说明书
编译方法实验报告实验名称:简单的语法分析程序设计实验要求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.语法分析递归下降分析算法21.1背景知识21.2消除左递归32.详细设计及流程图32.1 函数void V< > // V -> a|b|c|d|e...|z32.2 函数void A< > // A -> V:=E42.3 函数void E<> //E -> TE'42.4函数void T< > // T -> FT'42.5函数void E1< > //E'-> +TE'|-TE'|null52.6函数void T1<> // T'-> *FT'|/FT'|null53.测试用例及截图53.1测试用例1及截图53.2测试用例2及截图53.3测试用例3及截图5代码清单51.语法分析递归下降分析算法1.1背景知识无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
编译原理实验报告:实验二编写递归下降语法分析程序
编译原理实验报告实验名称:实验二编写递归下降语法分析器实验类型:验证型实验指导教师:何中胜专业班级:13软件四姓名:丁越学号:13030504电子邮箱:862245792@实验地点:秋白楼B720实验成绩:日期:2016年4 月1 日一、实验目的通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,掌握常用的语法分析方法。
通过本实验,应达到以下目标:1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
2、掌握词法分析的实现方法。
3、上机调试编出的语法分析程序。
二、实验过程1、分析对象分析算术表达式的 BNF 定义如下:〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉〈项〉→〈因式〉|〈项〉*〈因式〉|〈项〉/〈因式〉〈因式〉→〈变量〉│(〈算术表达式〉)〈变量〉→i用符号表示如下:E→T|E+T|E-TT→F|T*F|T/FF→i│(E)递归下降分析程序实现思想简单易懂。
程序结构和语法产生式有直接的对应关系。
因为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。
递归下降分析程序的实现思想是:识别程序由一组子程序组成。
每个子程序对应于一个非终结符号。
每一个子程序的功能是:选择正确的右部,扫描完相应的字。
在右部中有非终结符号时,调用该非终结符号对应的子程序来完成。
自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推导出待检查的符号串。
分析速度慢。
而无回溯的自上向下分析技术,当选择某非终结符的产生时,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。
无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。
无左递归:既没有直接左递归,也没有间接左递归。
无回溯:对于任一非终结符号 U 的产生式右部x1|x2|…|xn,其对应的字的首终结符号两两不相交。
2. 递归下降语法分析流程图实验分为五个模块,分别是:E( )函数,E1( )函数,T( )函数,T1( )函数,F( )函数。
如何进行编译器设计和解释器开发
如何进行编译器设计和解释器开发编译器和解释器是软件开发中非常重要的工具,它们用于将源代码转换为可以被计算机执行的机器码或者解释执行源代码。
编译器是将源代码一次性地转换为目标代码,而解释器是逐行地解释源代码并执行相应的操作。
本文将介绍编译器的设计和解释器的开发过程,并提供一些实用的技巧和建议。
一、编译器设计编译器设计是一个复杂的任务,需要掌握词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等多个环节。
下面是编译器设计的一般流程:1.词法分析:将源代码分解为一个个token,例如关键词、标识符、数字、操作符等。
可以使用正则表达式或者有限状态自动机来进行词法分析。
2.语法分析:根据语法规则将token组成一个个语法结构,例如函数、表达式、语句等。
可以使用上下文无关文法和语法分析算法(如LL(1)或者LR(1))来进行语法分析。
3.语义分析:对语法结构进行语义检查,例如类型检查、作用域检查、类型转换等。
在这一阶段还可以进行符号表的构建,用于保存变量和函数的信息。
4.中间代码生成:将源代码转换为一种中间表示形式,通常是一个抽象的指令序列,例如三地址码、虚拟机指令、中间表达式等。
中间代码的生成可以使用递归下降、语法制导翻译或者语法制导翻译的变体等方法。
5.代码优化:对中间代码进行优化,以提高代码的执行效率和减小代码的体积。
常见的优化技术包括常量折叠、公共子表达式消除、死代码删除、循环优化等。
6.目标代码生成:将中间代码转换为目标机器的机器码或者汇编代码。
目标代码生成可以分为两个阶段:指令选择(选择适合目标机器的指令)和寄存器分配(将变量分配到寄存器或者内存中)。
7.代码生成完成后,还需要进行链接和装载,将目标代码与库文件进行链接,并将最终的可执行文件加载到内存中执行。
二、解释器开发与编译器不同,解释器是逐行地解释和执行源代码,不需要将源代码先转换为目标代码。
下面是解释器的开发过程:1.词法分析:同编译器设计一样,解释器也需要进行词法分析,将源代码分解为一个个token。
语法分析递归下降分析法
语法分析递归下降分析法递归下降分析法是一种常用的语法分析方法,它通过构建递归子程序来解析输入的语法串。
该方法可以分为两个步骤:构建语法树和构建语法分析器。
首先,我们需要构建语法树。
语法树是一个表示语言结构的树形结构,它由各类语法片段(非终结符)和终结符组成。
构建语法树的过程就是根据文法规则从根节点开始递归地扩展子节点,直到达到文法推导出的终结符。
具体来说,我们可以通过以下步骤来构建语法树:1.设计满足语言结构的文法规则。
文法规则定义了语法片段之间的关系和转换规则。
2.将文法规则转换为程序中的递归子程序。
每个递归子程序对应一个语法片段,并按照文法规则递归地扩展子节点。
3.设计词法分析器将输入的语法串分词为单个有效的词法单元。
4.从语法树的根节点开始,根据递归子程序逐步扩展子节点,直到达到终结符。
同时,将每一步的扩展结果记录在语法树中。
接下来,我们需要构建语法分析器。
语法分析器是一个根据语法规则判断输入语法串是否符合语法规则的程序。
它可以通过递归下降分析法来实现。
具体来说,我们可以通过以下步骤来构建语法分析器:1.定义一个语法分析器的函数,作为程序的入口。
2.在语法分析器函数中,根据文法规则调用递归子程序,分析输入的语法串。
3.每个递归子程序对应一个语法片段,它会对输入的语法串进行识别和匹配,并根据文法规则进行扩展。
4.如果递归子程序无法匹配当前的输入,那么意味着输入的语法串不符合文法规则。
5.如果递归子程序成功扩展,并继续匹配下一个输入,则语法分析器会一直进行下去,直到分析完整个语法串。
总结起来,递归下降分析法是一种简单而有效的语法分析方法。
它通过构建递归子程序来解析输入的语法串,并构造出对应的语法树。
虽然递归下降分析法在处理左递归和回溯等问题上存在一定的困难,但它仍然是一种重要的语法分析方法,被广泛应用于编译器和自然语言处理等领域。
第四章3-递归下降法
冲突
Predict(A→β 定义 Predict(A→β) First(β λ∉First( First(β = First(β) , 当λ∉First(β) (First( First(β })∪ λ∈First( First(β = (First(β)-{λ})∪Follow(A) ,当λ∈First(β)
满足产生式预测集合不相交条件的文法 为递归下降文法
递归子程序方法要求的条件
predict(A→βk)∩ predict(A→βj )= ∅, β ∩ β 当k ≠ j
结论
如果文法中每个非终极符只有一个产生 式,则没有上述限制。因为其递归下降 子程序中没有多分支的选择问题。 递归下降条件是针对具有多产生式的非 终极符而言的。
必须消除选择的二义性
产生式A→β被选择的条件是: 产生式A→β被选择的条件是: A→ 当前要匹配的输入符属于predict(A→β 当前要匹配的输入符属于predict(A→β)。 predict(A→ 至多一个产生式被选择的条件是: 至多一个产生式被选择的条件是: predict(A→βk) ∩ predict(A→βj )=∅,当k ≠ j predict(A→β )=∅ predict(A→β
//调用Exp子程序 //调用Exp子程序 调用Exp
Match($do); Match($do); Stm end
//调用 调用Exp子程序 调用 子程序
Match(#while) ( ) 表示检查当前 输入的Token是 输入的 是 不是#while,若 不是 , 是,则输入指 针移一位, 针移一位,读 下一个Token, 下一个 , 否则表示有错
具有多个产生式的非终极符
当产生式中形如: 当产生式中形如: A → β1| β2| …| βn 也可以写成 | 则按下面的方法编写子程序A 则按下面的方法编写子程序A: Case结构 结构 procedure A( ) token∈Predict(A→β begin if token∈Predict(A→β1) then θ(β1) else if token∈Predict(A→β2) then θ(β2) else token∈Predict(A→β …… token∈Predict(A→β →βn) if token∈Predict(A→βn) then θ(βn) else err( ) end 其中对β 其中对βi=X1X2…Xn,θ(βi) = θ’(X1);θ’(X2);…;θ’(Xn); β θ θ 如果X 如果 i∈VN,θ’(Xi)= Xi 如果X 如果 i∈VT,θ’(Xi)= Match(Xi) 如果X 空语句) 如果 i= ε , θ(ε) = skip(空语句 ε 空语句
语法分析器设计实验报告
学号《编译原理》实验2:语法分析器设计学生姓名专业、班级指导教师赵璐成绩计算机与信息工程学院2018 年11 月27 日一、实验目的1.理解语法分析程序的功能。
2.熟悉语法分析程序的设计原理和构造方法。
3.掌握递归下降语法分析程序的构造方法。
4.设计一个递归下降的语法分析器,作为实验一构造的词法分析器的下一步编译工具,能语法分析前一步词法分析器输出的单词符号序列。
二、实验要求1.根据书P206给出的简单语言的语法规则,编写C或C++语言源程序,实现针对该简单语言的递归下降的语法分析器;2.独立做实验,输入、调试所编程序;3.实验结束后,根据实验报告模板编写实验报告。
三、实验内容和步骤用Visual C++作为实验开发环境,创建一个Win32 Console Application工程,工程名为你的学号,添加三个文件:(1)存储结构定义:以ParserDef.h和LexerDef.h为文件名;(2)基本操作的算法:以ParserAlgo.h和LexerAlgo.h为文件名;(3)调用基本操作的主程序:以ParserMain.cpp为文件名。
编写程序:(1)文件LexerDef.h和LexerAlgo.h为实验一的内容。
(2)文件ParserDef.h定义语法分析所需的全局变量等。
(3)文件ParserAlgo.h实现对语法规则中各语法成分的分析子算法。
(4)文件ParserMain.cpp实现针对P206简单语言语法规则的递归下降语法分析器。
源程序代码:=============================ParserDef.h================================ int kk;#define _KEY_WORD_END "waiting for your expanding"char * rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};char input[255];char token[255]="";int p_input;int p_token;char ch;============================ParserAlgo.h================================ char prog[80];int syn,p,m,n,sum=0;void scaner() {m=0;for(n=0; n<8; n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';syn=10;p=p-1; //回退一个字符for(n=0; n<6; n++) {if(strcmp(token,rwtab[n])==0) {syn=n+1;break;}}} else if(ch>='0' && ch<='9') {sum=0;while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=prog[p++];}p=p-1;syn=11;} else {switch(ch) {case '<':m=0;token[m++]=ch;ch=prog[p];if(ch=='>') {syn=21;token[m++]=ch;} else if(ch=='=') {syn=22;token[m++]=ch;} else {syn=20;p=p-1;}p=p+1;token[m]='\0';break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=24;token[m++]=ch;} else {syn=23;p=p-1;}break;case ':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=18;token[m++]=ch;} else {syn=17;p=p-1;}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}}============================ParserMain.cpp============================== #include<stdio.h>#include<stdlib.h>#include<string.h>#include"LexerDef.h"#include"ParserDef.h"#include"LexerAlgo.h"#include"ParserAlgo.h"void lrparser();void yucu();void statement();void expression();void term();void factor();void lrparser() {if (syn==1) { //beginscaner();yucu();if (syn==6) { //endscaner();if (syn==0 && kk==0) printf("success \n");} else {if(kk!=1) printf("error,lose 'end' ! \n");kk=1;}} else {printf("error,lose 'begin' ! \n");kk=1;}return;}void yucu() {statement();while(syn==26) {scaner();statement();}return;}void statement() {if (syn==10) { //为标识符scaner();if (syn==18) { //为:=scaner();expression();} else {printf("error!");kk=1;}} else {printf("error!");kk=1;}return;}void expression() {term();while(syn==13 || syn==14) {scaner();term();}return;}void term() {factor();while(syn==15 || syn==16) {scaner();factor();}return;}void factor() {if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号else if(syn==27) {scaner();expression();if(syn==28)scaner();else {printf(" ')' 错误\n");kk=1;}} else {printf("表达式错误\n");kk=1;}return;}void main() {p=0;printf("********************语法分析程序***************\n");printf("请输入源程序:\n");do {scanf("%c",&ch);prog[p++]=ch;} while(ch!='#');p=0;scaner();lrparser();printf("语法分析结束!\n");}四、解答下列问题(1)简述该语法分析器的算法思想。
编译原理语法分析器
编译原理语法分析器编译原理语法分析器是编译器中的重要组成部分,它负责将源代码解析成抽象语法树,为后续的语义分析和代码生成做准备。
本文将介绍语法分析器的原理、分类和常用算法。
一、语法分析器的原理语法分析器的主要任务是根据给定的文法定义,将源代码解析成一个个语法单元,并构建出一棵抽象语法树。
它通过递归下降、预测分析和LR分析等算法来实现。
1. 递归下降法递归下降法是一种基于产生式的自顶向下分析方法。
它从文法的开始符号出发,通过不断地推导和回溯,逐步地构建抽象语法树。
递归下降法易于理解和实现,但对左递归和回溯有一定的局限性。
2. 预测分析法预测分析法也是自顶向下的分析方法,它通过预测下一个输入符号来选择适当的产生式进行推导。
为了提高效率,预测分析法使用预测分析表来存储各个非终结符和终结符的关系。
3. LR分析法LR分析法是一种自底向上的分析方法,它使用LR自动机和LR分析表来进行分析。
LR自动机是一个有限状态控制器,通过状态转移和规约动作来解析源代码。
LR分析表存储了状态转移和规约的规则。
二、语法分析器的分类根据语法分析器的特性和实现方式,可以将其分为LL分析器和LR 分析器。
1. LL分析器LL分析器是基于递归下降法和预测分析法的一类分析器。
它从左到右、从左到右地扫描源代码,并根据预测分析表进行推导。
常见的LL分析器有LL(1)分析器和LL(k)分析器。
2. LR分析器LR分析器是基于LR分析法的一类分析器。
它先通过移进-归约的方式建立一棵语法树,然后再进行规约操作。
LR分析器具有强大的语法处理能力,常见的LR分析器有LR(0)、SLR(1)、LR(1)和LALR(1)分析器。
三、常用的语法分析算法除了递归下降法、预测分析法和LR分析法,还有一些其他的语法分析算法。
1. LL算法LL算法是一种递归下降法的改进算法,它通过构造LL表和预测分析表实现分析过程。
LL算法具有很好的可读性和易于理解的特点。
2. LR算法LR算法是一种自底向上的分析方法,它通过建立LR自动机和构造LR分析表来进行分析。
编译原理——表达式分析
一、实验目的:熟悉并设计一个表达式的语法分析器二、相关知识:1、形式语言基础及其文法运算2、语法分析原理及4种常用的语法分析方法其中:四种算法为(1)设计算术表达式的递归下降子程序分析算法三、实验内容:1.设计表达式的语法语法分析器算法2.编写代码并上机调试运行通过要求:输入------------ 表达式输出------------ 表达式语法是否正确四、概要设计1.算术表达式的递归下降子程序分析算法(1)算术表达式文法G(E): E → E ω0 T | TT → T ω1 F | FF → i | (E)(2)文法变换:G’(E) E →T {ω0 T}T →F {ω1 F}F → i | (E)(3)递归下降子程序框图:E: 入口T:入口T Fn ω0? n ω1?y y出口出口read(w) read(w)T FF: 入口主程序:Z →E开始( ? n i ? n errread(w) read(w)EEerr n # ?err n ) ? yyread(w)结束出口(4)数据结构char exp[50]; //算术表达式区int i=0;int err=0 ; //err输出指示char w; //当前单词(5)源程序清单:#include <stdio.h>#include <stdlib.h>void E();void T();void F();int Print();char exp[50];//算术表达式区int i=0;int err=0;char w;//当前单词int Print(){printf("err") ;err=1;return err;}void F(){if((w>='a'&&w<='z')||(w>='0'&&w<='9')){w=exp[i++];//read(w)}else if(w=='('){w=exp[i++];E();if(w!=')'){if(!err)Print();}elsew=exp[i++];//read(w)}else{if(!err)Print();}}void T(){F();while(w=='*'||w=='/'){w=exp[i++];//read(w)F();}}void E(){T();while(w=='+'||w=='-'){w=exp[i++];//read(w)T();}}int main(){printf("please input your expression:");//输入表达式 scanf("%s",exp);w=exp[i++];//read(w)E();if(!err){if(w=='#')printf("OK!"); elseprintf("err"); }return 0;}(6)运行结果。
递归下降分析方法是一种
递归下降分析方法是一种递归下降分析方法是一种常用的语法分析方法,用于处理上下文无关文法。
它是自顶向下的分析方法,可以从给定的非终结符开始递归地扩展并产生整个句子。
递归下降分析的基本原理递归下降分析的基本原理是根据上下文无关文法的定义,构建一个分析函数集合来实现对语法的分析。
这个函数集合中的每一个函数对应一个非终结符,它逐个对输入符号进行匹配,并根据产生式不断地扩展和推导。
递归下降分析的过程首先确定要解析的非终结符,然后根据该非终结符的定义从左到右递归地匹配输入符号,直到匹配成功。
如果在某个步骤中无法匹配符号,那么就回退到上一个分析函数,并尝试其他的规则进行匹配。
递归下降分析方法通过语法的递归性质来处理语法的递归定义。
它通过分析函数的递归调用来生成分析树,从而实现对句子结构的逐步推导和分析。
递归下降分析的优势和局限性递归下降分析方法具有以下优势:1. 简洁明了:递归下降分析方法通过函数的递归调用来模拟语法的递归定义,使得算法本身更加直观和易于理解。
2. 灵活性高:递归下降分析方法具有较高的灵活性,可以通过适当的调整分析函数的顺序和匹配规则来适应不同的语法结构。
然而,递归下降分析方法也存在一些局限性:1. 左递归问题:递归下降分析方法对左递归的处理不够有效,可能会导致死循环或栈溢出的问题。
2. 回溯问题:递归下降分析方法在遇到无法匹配的情况时需要进行回溯,可能会导致分析效率较低。
实现递归下降分析的步骤实现递归下降分析通常包括以下几个步骤:1. 按照文法定义编写分析函数:根据文法定义,为每个非终结符编写相应的分析函数,实现对输入符号的匹配和推导。
2. 建立终结符表和非终结符表:根据文法定义,建立终结符和非终结符的表格,用于分析函数的选择和匹配。
3. 构建语法分析树:通过分析函数的递归调用,将输入符号逐步匹配和扩展,构建语法分析树。
4. 回溯和错误处理:当无法匹配输入符号时进行回溯,根据具体情况进行相应的错误处理。
编译原理实验报告3
编译原理实验报告3编译原理实验报告——表达式语法分析——表达式语法分析表达式语法分析实验报告一、实验题目设计一个简单的表达式语法分析器(采用递归下降方法设计实现)二、实验目的1、了解形式语言基础及其文法运算;2、熟悉语法分析原理及 4 种常用的语法分析方法;其中:四种算法为(1)设计算术表达式的递归下降子程序分析算法(2)设计算术表达式的 LL(1) 分析算法(3)设计算术表达式的简单优先分析算法(4)设计算术表达式的SLR(1) 分析算法3、选择上述一种方法并设计一个表达式的语法分析器。
(本实验设计的是递归下降的表达式语法分析器)三、实验内容1.设计递归下降语法分析器算法;2.编写代码并上机调试运行通过; 3、写出试验体会及心得。
四、实验要求1、给出算术表达式文法2、进行适当的文法变换3、选择一种语法分析的方法,并说明其原理4、根据原理给出相应的算法设计,说明主要的数据结构并画出算法流程图5、编写代码并上机调试运行通过6、写出程序运行结果7、写出相应的文档以及代码注释8、输入——表达式;输出——表达式语法是否正确。
五、递归下降的表达式语法分析器设计概要1.算术表达式文法.G(E):E T F 2.文法变换:文法变换:G’(E): E->TE' E'->+TE'|ε T->FT' T'->*FT'|ε F->(E)|I E +T | T T* F | F i | (E)3. 递归下降子程序框图:递归下降子程序框图:六、实验设计源程序#includechar inputstream[50]; int temp=0; int right; void e(); void e1(); void t(); void t1(); void f(); void main() { right=1;//存储输入句子//数组下标 //判断输出信息cout<<"请输入您要分析的字符串以#结束(^为空字符):"<>inputstream; e(); if((inputstream[temp]=='#')&&right) cout<<"分析成功"<<<"e-="" cout<<"分析失败"<TE'"<<<"e'-="" e1()="" e1();="" if(inputstream[temp]="='+')" t();="" void="" {="" }="">+TE'"<e1(); } else if (inputstream[temp]!='#'||inputstream[temp]!=')') { cout<<"T'->^"<<<"t-="" else="" return="" right="0;" t()="" void="" {="" }="">FT'"<<<"t'-="" f();="" if(inputstream[temp]="='*')" t1()="" t1();="" void="" {="" }="">*FT'"<<<"t'-="" else="" f();="" if="" t1();="" temp++;="" {="" }="">^"<} } void f() { if(inputstream[temp]=='i') { cout<<"F->i"<if(inputstream[temp]=='(') { cout<<"F->(E)"<<<"f-="" e();="" if(inputstream[temp]="=')')" temp++;="" {="">(E)"<七、运行结果八、实验思考题语法分析的任务是什么?语法分析的任务是什么?答:语法分析器的任务是识别和处理比单词更大的语法单位,如:程序设计语言中的表达式、各种说明和语句乃至全部源程序,指出其中的语法错误;必要时,可生成内部形式,便于下一阶段处理。
实验二 语法分析程序设计与实现
/*输出剩余串*/
/*输出对齐符*/
cout<<B[j]; cout<<"\t\t\t"; } void main() { int m,n,k=0,flag=0,finish=0; char ch,x; type cha; /*把文法产生式赋值结构体*/ e.origin='E'; strcpy(e.array,"TG"); e.length=2; t.origin='T'; strcpy(t.array,"FS"); t.length=2; g.origin='G'; strcpy(g.array,"+TG"); g.length=3; g1.origin='G'; strcpy(g1.array,"-TG"); g1.length=3; g2.origin='G'; g2.array[0]='^'; g2.length=1; s.origin='S';
g2
S->*FS s
T->/FS s1
S->^
s2
F->(E)
f
G->i
f1
分析表:
i
+
-
*
/
(
)
#
E
e
e
G
g
g1
g2
g2
T
t
t
S
s2
s2
s
s1
s2
s2
F
f1
普拉特解析法
普拉特解析法普拉特解析法是一种基于递归下降语法分析的方法,可用于实现计算器、编译器等程序,也是编译原理中较为常见的语法分析方法。
一、递归下降语法分析递归下降语法分析是一种自顶向下的语法分析方法,其主要思想是依据给定的文法规则从上至下递归分析输入的符号串(即待分析字符串),并在分析过程中生成相应的语法树或抽象语法树。
该方法的具体实现过程如下:1. 定义语法规则在递归下降语法分析中,需要首先定义一个正规式(即文法规则),该正规式描述了待分析的符号串应符合的语法规则。
通常,一个正规式由终结符号和非终结符号组成,其中终结符号是指满足语法规则的最基本的符号,而非终结符号则由终结符号和其他非终结符号组成的语言构成。
2. 编写语法分析程序在定义好语法规则后,需要编写对应的语法分析程序。
具体实现中,可选用递归下降法、LL语法分析器等方法。
其中递归下降法是最常用的方法之一,其主要过程如下:- 从定义的正规式中选取一个非终结符号作为起点进行语法分析。
- 对于每个非终结符号,编写对应的处理程序,该程序能够根据文法规则递归分析所有可能的产生式。
- 对于每个终结符号,编写对应的处理程序,根据输入的符号串将其匹配到对应的终结符。
- 组合各个处理程序,构成完整的语法分析程序。
3. 执行语法分析程序完成上述步骤后,即可执行编写好的语法分析程序,并对输入的符号串进行语法分析。
在此过程中,程序会逐步构建出语法树或抽象语法树,并通过将树状结构转化为代码来实现解析。
二、普拉特解析法普拉特解析法(Pratt Parsing)是一种常用的递归下降语法分析方法,它能够支持二元运算符、一元运算符以及其他任意的操作符类型,因此被广泛用于实现计算器、编译器等程序。
普拉特解析法的具体实现过程如下:1. 定义语法规则在使用普拉特解析法实现语法分析程序时,需要首先定义一个特殊的正规式,该正规式是一个表达式语法的扩展版本,其包含了以下几种类型的操作符:- 前缀操作符- 后缀操作符- 双目中置操作符此外,还需要对每一种操作符对应的优先级进行定义,以确定该操作符在语法分析中的位置。
编译原理——语法分析程序设计实验报告
实验二语法分析程序设计[实验目的]:1.了解语法分析的主要任务。
2.熟悉编译程序的编制。
[实验内容]:根据某文法,构造一基本递归下降语法分析程序。
给出分析过程中所用的产生式序列。
[实验要求]:1.选择一个文法,进行实验,可选的文法包括以下三个:P190 4.8P190 4.9P190 4.102.设计语法分析程序的输出形式(输出应为语法树或推导),一个可以参考的例子,可见图1。
3.编写递归下降语法分析程序(参考P148-149 Topdown parsing byrecursive-descent),实现基本的递归下降分析器,能够分析任给的符号串是否为该文法所定义的合法句子。
实验报告中要说明分析使用的方法。
4.根据所作业题选项e所给出的input,生成并输出分析过程中所用的产生式序列(show the actions of parser):1 产生式12 产生式2……5.自已设计一个不合法的句子,作为输出进行分析,给出结果。
[实验过程]本次实验选择的文法为P190 4.8lexp->atom|listatom->number|identifierlist->(lexp-seq)lexp-seq->lexp lexp-seq1.写出实现的算法,并画流程图。
本次实验采用递归下降算法,算法流程图如下图1-1:图1-1 算法流程图2.根据你选择的文法,分析左递归或左因子是否会影响本算法的结果。
会影响本算法的结果。
递归下降分析法要求的文法是LL(1)文法,需要消除左递归和左因子的影响。
如果存在左因子,对相同的字符跳转到不同的函数,无法实现递归。
3.列举实验设计过程中出现的问题及解决的方法(至少3条,选择实验中最困扰的问题)。
1).会多次输出accept/error结果解决方案:所有的递归函数返回类型为int,若accept返回1,error返回0,在main主函数中统一判断输出语句。
编译原理语法分析实验二表达式语法分析器的设计实现
编译原理程序设计实验报告——实验题目班级:计算机1306姓名:学号:实验目标:表达式语法分析器的设计实现1) 递归下降子程序 2) LL (1)分析法实验内容: 1. 概要设计1) 按照流程图,调用子程序实现;2) 通过ll (1)分析表和对应压栈、弹栈操作实现。
2. 流程图1) 递归: Z ’(main):N Err开始Read (w ) E #? 结束E: E1:Y NY NT: T1:YNYNF :N N err Y YY N err入口 TE1 入口+? -? 出口Read(w) T出口入口 FT1 出口入口*?/?出口Read (w )T入口I ? (? Read (w )E )? Read (w )出口2) LL (1):BeginPUSH(#),PUSH(E)POP(x)x ∈VTx ∈VNx=wendW=#nyNEXT(w)yn err查LL (1)分析表空?nPUSH (i )errny逆序压栈开始构建LL(1)分析表调用函数token ()切分单词 调用*Analyse(char *token)进行分析 结束3.关键函数1)递归下降子程序void E(); //E->TX;int E1(); //X->+TX | evoid T(); //T->FYint T1(); //Y->*FY | eint F(); //F->(E) | i2)LL(1)分析法char *Find(char vn,char vt)//是否查到表char *Analyse(char *token)//分析过程int Token()//将token中数字表示成i,标识符表示成n源程序代码:(加入注释)1)递归下降子程序:#include<stdio.h>#include<iostream>#include <string.h>#include <stdlib.h>using namespace std;/********全局变量**********/char str[30];int index=0;void E();//E->TX;int E1();//X->+TX | evoid T();//T->FYint T1();//Y->*FY | eint F();//F->(E) | iFILE *fp;char cur;/*************主函数************/int main(){int len;int m;if((fp=fopen("source.txt","r"))==NULL){cout<<"can not open the source file!"<<endl;exit(1);}cur=fgetc(fp);while(cur!='#'){E();}cout<<endl;cout<<"success"<<endl;return 0;}/*************************************/void E(){T();E1();}/*************************************/int E1(){if(cur=='+'){cur=fgetc(fp);T();cout<<'+'<<" ";E1();}else if(cur=='-'){cur=fgetc(fp);T();cout<<'-'<<" ";E1();}return 0;}/************************************/void T(){F();T1();}/***********************************/int T1(){if(cur=='*'){cur=fgetc(fp);F();cout<<'*'<<" ";T1();}else if(cur=='/'){cur=fgetc(fp);F();cout<<'/'<<" ";T1();}return 0;}int F(){if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){for(int i=0;i<20;i++){str[i]='\0';index=0;}str[index++]=cur;cur=fgetc(fp);while((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'||(cur<='9'&&cur>='0')){str[index++]=cur;cur=fgetc(fp);}cout<<str;cout<<" ";return NULL;}else if (cur<='9'&&cur>='0'){for(int i=0;i<20;i++){str[i]='\0';index=0;}while(cur<='9'&&cur>='0'){str[index++]=cur;cur=fgetc(fp);}if(cur=='.'){str[index++]=cur;cur=fgetc(fp);while(cur<='9'&&cur>='0'){str[index++]=cur;cur=fgetc(fp);}cout<<str;cout<<" ";return NULL;}else if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){printf("error6\n");exit(1);}else{cout<<str;cout<<" ";return NULL;}}else if (cur=='('){cur=fgetc(fp);E();if(cur==')'){cur=fgetc(fp);return 0;}else{printf("error3\n");exit (1);}}else{printf("error4\n");exit(1);}return 0;}程序运行结果:(截屏)输入:Source.txt文本((Aa+Bb)*(88.2/3))#输出:2)LL(1)#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[12];}MAP[22];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;char token[30];int token_index=0;charG[12][12]={"E->TR","R->+TR","R->-TR","R->e","T->FW","W->*FW","W->/FW", "W->e","F->(E)","F->i","F->n"};//存储文法中的产生式,用R代表E',W代表T',e代表空//char VN[6]={'E','R','T','W','F'};//存储非终结符//char VT[9]={'i','n','+','-','*','/','(',')','#'};//存储终结符char Select[12][12]={"(,i,n","+","-","),#","(,i,n","*","/","+,-,),#","(","i","n"};//存储文法中每个产生式对应的select集合charRight[12][8]={"->TR","->+TR","->-TR","->e","->FW","->*FW","->/FW","->e","->( E)","->i","->n"};stack<char> stak,stak1,stak2;char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn&& MAP[i].vt==vt)return MAP[i].s;}return "error";}char *Analyse(char *token){char p,action[10],output[10];int i=1,j,k=0,l_act,m;while(!stak.empty())//判断栈中是否为空,若不空就将栈顶元素与分析表匹配进行相应操作stak.pop();stak.push('#');//栈底标志stak.push('E');//起始符号先入栈printf(" 步骤栈顶元素输入串推导所用产生式或匹配\n");p=stak.top();while(p!='#')//查预测分析表将栈顶元素进行匹配,若栈顶元素与输入串匹配成功则向前匹配,否则生成式反序入栈{printf("%7d ",i++);p=stak.top();//从栈中弹出一个栈顶符号,由p记录并输出stak.pop();printf("%6c ",p);for(j=0,m=0;j<token_index;j++)//将未被匹配的剩余输入串输出output[m++]=token[j];output[m]='\0';printf("%10s",output);if(p==token[k]){ if(p=='#')//若最后一个结束符号匹配说明输入表达式被接受,否则继续匹配{printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{ //将未被匹配的第一个字符与find函数的结果进行比较,在预测分析表中查找相应生成式strcpy(action,Find(p,token[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}return "ERROR";}int Token(){FILE *fp;char cur;int i,j;fp=fopen("source.txt","r");cur=fgetc(fp);while(cur!=EOF)//把用字母数字表示的输入串转换为token序列的表示方法{if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){cur=fgetc(fp);while((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'||(cur<='9'&&cur>='0')){cur=fgetc(fp);} token[token_index++]='i';continue;}else if (cur<='9'&&cur>='0'){while(cur<='9'&&cur>='0')cur=fgetc(fp);if(cur=='.'){cur=fgetc(fp);while(cur<='9'&&cur>='0')cur=fgetc(fp);}token[token_index++]='n';continue;}else{token[token_index++]=cur;cur=fgetc(fp);continue;} }token[token_index]='#';cout<<"把文件中字符串用i表示,数字用n表示,转化后:";for(int index=0;index<=token_index;index++)cout<<token[index];cout<<endl<<endl;return 0;}int main (){int i,j,l,m;for(i=0,k=0;i<11;i++)//通过select集合生成预测分析表{l=strlen(Select[i]);for(j=0;j<l;j+=2){MAP[k].vn=G[i][0];MAP[k].vt=Select[i][j];strcpy(MAP[k].s,Right[i]);k++;}}Token();cout<<"分析过程如下:"<<endl;cout<<Analyse(token)<<endl;return 0;}程序运行结果:(截屏)输入:Source.txt文本((Aa+Bb)*(88.2/3))输出:目录第一章总论 ........................................................................................ 错误!未定义书签。
递归下降语法分析器实验报告
一、实验目的使用递归子程序法设计一个语法分析程序,理解自顶向下分析方法的原理,掌握手工编写语法分析程序的方法。
二、实验原理1. 基本原理递归下降法是语法分析中最易懂的一种方法。
它的主要原理是,对每个非终极符按其产生式结构构造相应语法分析子程序,其中终极符产生匹配命令,而非终极符则产生过程调用命令。
因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。
其中子程序的结构与产生式结构几乎是一致的。
2. 文法要求递归下降法要满足的条件:假设A的全部产生式为Aα1|α2|……|αn ,则必须满足如下条件才能保证可以唯一的选择合适的产生式predict(Aαi)∩predict(Aαj)=Φ,当i≠j.3. 实现原理假设文法中有如下的产生式A1 | 2 | … | n,则应按如下方法编写语法分析子程序procedure A()begin if tokenPredict(A1) then θ(1) elseif tokenPredict(A2) then θ(2) else……if tokenPredict(An) then θ(n) elseerror()end其中对i =X1X2…Xn,θ(i) =θ’(X1); θ’(X2);…; θ’(Xn);● 如果XiVN,θ’(Xi)= Xi● 如果XiVT,θ’(Xi)= Match(Xi)● 如果Xi= , θ’(λ) = skip(空语句)三、实验要求1、使用递归下降分析算法分析表达式文法:exp ::= exp addop term | termaddop ::= + | -term ::= term mulop factor | factormulop ::= * | /factor ::= (exp) | number其中number可以是多位的十进制数字串(整数即可),因此这里还需要一个小的词法分析器来得到number的值。
2、该词法分析器以子程序形式出现,当需要进行词法分析时进行调用;3、能够识别正确和错误的表达式;4、在进行语法分析的过程中,计算输入表达式的值。
LL(!)语法分析
LL(1)语法分析一、实验目的:理解语法分析程序的主要任务和实现技术。
二、实验内容:为无二义性表达式文法G[E]构造语法分析程序G[E]: E->E+T|T T->T*F|F F->(E)|i三、实验要求:1.用递归下降分析方法实现,要求能够对正确的和错误的输入串进行分析,给出分析结果(accept/error)。
2.程序输入为形如i+i*i# 或者ii#的串,输出为推导所用的产生式序列四、程序流程图#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[10];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空charG[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->( E)","F->i"};//存储文法中的产生式char VN[6]={'E','R','T','W','F'};//存储非终结符char VT[6]={'i','+','*','(',')','#'};//存储终结符char SELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集charRight[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"} ;stack <char> stak,stak1,stak2;bool compare(char *a,char *b){int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i++)for(j=0;j<lb;j++){if(a[i]==b[j])return 1;}return 0;}char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}//当非终结符遇到终结符时应采用哪个产生式来推导char * Analyse(char * word){char p,action[10],output[10];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();//清空了分析栈stak.push('#');stak.push('E');printf("_____________________________________________________________ ___________________\n");printf("\n 对符号串%s的分析过程\n",word);printf(" 步骤栈顶元素剩余输入串推到所用产生式或匹配\n");p=stak.top();while(p!='#'){printf("%7d ",i++);p=stak.top();stak.pop();//栈顶元素出栈printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);//剩余的输入串if(p==word[k]){if(p=='#'){printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);//产生式长度if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)//如果不是空产生式stak.push(action[j]);//将推导用的产生式倒叙入栈}}if(strcmp(output,"#")!=0)return "ERROR";}int main (){char c;int e=0;//freopen("in.txt","r",stdin);// freopen("c:\out.txt","w",stdout);char source[100];int i,j,flag,l,m;printf("\n*****为了方便编写程序,用R代表E',W代表T',e代表空*****\n\n");printf("该文法的产生式如下:\n");for(i=0;i<8;i++)printf(" %s\n",G[i]);printf("_____________________________________________________________ ___________________\n");printf("\n该文法的SELECT集如下:\n");for(i=0;i<8;i++){printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]);}printf("_____________________________________________________________ ___________________\n");//判断是否是LL(1)文法flag=1;for(i=0;i<8;i++){for(j=i+1;j<8;j++){if(G[i][0]==G[j][0])//产生式左部相同{if(compare(SELECT[i],SELECT[j])){flag=0;break;}}}if(j!=8)break;}if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。
语法分析器实验报告
杭州电子科技大学班级: 12052312 专业: 计算机科学与技术实验报告【实验名称】实验二语法分析一. 实验目的编写一个语法分析程序, 实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二. 实验内容利用编程语言实现语法分析程序, 并对简单语言进行语法分析。
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测试以上输入的分析, 并完成实验报告。
2.3 语法分析程序的算法思想(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-7 factor 分析过程示意图三.个人心得一、 通过该实验, 主要有以下几方面收获: 二、 对实验原理有更深的理解。
- 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.语法分析递归下降分析算法............................... 错误!未定义书签。
背景知识............................................. 错误!未定义书签。
消除左递归........................................... 错误!未定义书签。
2.详细设计及流程图....................................... 错误!未定义书签。
函数void V( ) .|z ................................. 错误!未定义书签。
函数void A( ) 错误!未指定书签。
错误!未指定书签。
错误!未指定书签。
错误!未指定书签。
错误!未指定书签。
试用例及截图........................ 错误!未定义书签。
测试用例1及截图..................................... 错误!未定义书签。
测试用例2及截图..................................... 错误!未定义书签。
测试用例3及截图..................................... 错误!未定义书签。
代码清单................................................. 错误!未定义书签。
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∪V)* ,y不以U打头。
直接左递归的消除:U→yU‟U‟→xU‟|ε直接左递归的一般形式:U→Ux|Ux|…|Ux|y|y|…|y;其中:x≠ε ,y都不以U打头。
一般形式直接左递归的消除:U→yU‟| yU‟ |…| yU‟U‟→xU‟| xU‟| …| xU‟|ε回溯的消除的前提是文法不得含有左递归,可提左因子来消除回溯。
消除左递归根据实验中给出的文法,进行消除左递归及回溯,得到下列的式子A -> V:=EE -> TE'E'-> +TE'|-TE'|nullT -> FT'T'-> *FT'|/FT'|nullF -> V|(E)V -> a|b|c|d|e...|z2.详细设计及流程图根据消除左递归后的文法,可以编写相应的函数。
函数void V( ) .|zv oid V() .|z函数设计主要用来识别小写字母的,如果是小写字母的话,放入字符表,不是的话,输出语法错误。
函数比较简单,代码如下:i f(islower(s[sym])){Table[list_n][0] = s[sym];开始V( )s[sym]==':'&&s[sym+1]=='='sym+=2;E( );Y输出表达式N输出错误结束开始SIGN==0s[sym] == '+'||s[sym]=='-'输出三地址式和四元表达式p=sym;sym++T()YE1()结束N N开始SIGN==0s[sym] == '*'||s[sym]=='/'输出三地址式和四元表达式p=sym;sym++F()YT1()结束N N 试用例及截图测试用例1及截图用例1为实验要求上的的用例。
测试结果图4所示。
图4 测试用例1及结果截图测试用例2及截图用例2为出现大写字母,出现报错。
测试结果图5所示。
图5 测试用例2及结果截图测试用例3及截图用例3为随意编写用例。
测试结果图6所示。
图6 测试用例3及结果截图代码清单#include<>#include<>#include<>#include <>void A(); .|zchar s[50],n='1'; .|z*/int main(){SIGN = 0; .|z{i f(islower(s[sym])){Table[list_n][0] = s[sym]; //把读取的小写字母存入符号表,便于分析是生成中间代码Table[list_n][1] = '\0';list_n++;sym++;}e lse{printf("Operand Errors!\n"); //运算对象错误SIGN=1;exit(0);}}void E() //E -> TE'{i f(SIGN==0){T();E1();}}void T() // T -> FT'{i f(SIGN==0){F();T1();}}void E1() //E'-> +TE'|-TE'|null{i nt p;i f(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;i f(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){i f(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);}}}。