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

合集下载

递归下降法

递归下降法
例 设有文法G[E]: E→ E + T | T T→ T * F | F F→ (E) | id
试构造一个识别该文法句子的递归下 降分析程序。
递归下降分析法
分析 首先消去文法左递归,得到文法 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-递归下降法

第四章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(空语句 ε 空语句
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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);}}}。

相关文档
最新文档