第四章语法分析5PPT格式课件下载.ppt
《第四章语法分析5PPT格式课件下载.ppt》由会员分享,可在线阅读,更多相关《第四章语法分析5PPT格式课件下载.ppt(72页珍藏版)》请在冰豆网上搜索。
A,a搜索符a的集合总是Follow(A)的子集。
10/27/20227编译原理活前缀的有效活前缀的有效LR
(1)项目项目qLR
(1)项目A,a对活前缀有效,如果存在着推导S*rmAwrmw,其中:
1.=;
2.a是w的第一个符号,或者w为且a是$。
10/27/20228编译原理构造有效的构造有效的LR
(1)项目集项目集q项目AB,a对活前缀有效,必定存在S*rmAaxrmBax,其中=。
q假设ax能推出by,那么,B,b对有效,b是从能推出的开始符号,或当可空时,b就是a。
bFIRST(a)。
10/27/20229编译原理LALR分析表的构造分析表的构造1.先构造文法的LR
(1)项目集族C=I0,I1,In;
2.再合并C中的同心集,得到C=J0,J1,Jm;
由此得到的识别活前缀的DFA实际上和LR(0)项目的DFA相同,但带上了搜索符10/27/202210编译原理wAwALL分析方法和分析方法和LR分析方法的比较分析方法的比较qA,LL
(1)向前看下一个输入根据FIRST()确定使用哪条产生式推导;
而LR
(1)是在识别出整个后,再往前看1个符号,然后确定使用哪条产生式归约。
SS10/27/202211编译原理在下面的推导中,最后一步用的是ALL
(1)决定用该决定用该产生式的位置是产生式的位置是First()LR
(1)决定用该决定用该产生式的位置产生式的位置LL分析方法和分析方法和LR分析方法的比较分析方法的比较10/27/202212编译原理非非LR结构结构q例:
L=wwRwa,b*SaSabSb10/27/202213编译原理LL分析方法和LR分析方法的比较qLL(k)文法都是LR(k)文法。
LR文法比LL文法描述的语言更多。
10/27/202214编译原理LR
(1)方法LL
(1)方法建立分析树的方式自下而上自上而下归约还是推导规范归约(最右推导的逆过程)最左推导决定使用产生式的时机看见产生式右部推出的全部内容后再决定用哪个产生式进行归约看见产生式右部推出的第一个终结符后就确定用哪个产生式进行推导LR分析方法和LL分析方法的比较10/27/202215编译原理LR
(1)方法LL
(1)方法对CFG的显式限制没有限制无左递归、无公共左因子分析表比较状态文法符号分析表大非终结符终结符分析表小分析栈比较状态栈,通常状态比文法符号包含更多信息文法符号栈LR分析方法和分析方法和LL分析方法的比较分析方法的比较10/27/202216编译原理LR
(1)方法LL
(1)方法确定句柄根据栈顶状态和下一个符号便可以确定句柄和归约所用产生式无句柄概念语法错误不会将出错点后的符号移入分析栈和LR一样,不会读过出错点而不报错LR分析方法和分析方法和LL分析方法的比较分析方法的比较10/27/202217编译原理48二义文法的应用二义文法的应用q任何二义性的文法都不是LR文法。
q二义文法的特点:
简洁、自然例如,表达式文法二义文法:
EE+E|E*E|(E)|id非二义的文法:
EE+T|TTT*F|FF(E)|idq语法分析的效率高(基于消除二义后得到的分析表)10/27/202218编译原理4.8.1使用文法以外信息解决分析动作使用文法以外信息解决分析动作冲突冲突优先级和结合规则例:
规定:
*优先级高于+,两者都是左结合EE+E|E*E|(E)|id10/27/202219编译原理拓广文法的拓广文法的LR(0)项目集项目集I0:
EEEE+EEE*EE(E)EidI1:
EEEE+EEE*EI2:
E(E)EE+EEE*EE(E)EidI3:
EidI4:
EE+EEE+EEE*EE(E)EidI5:
EE*EEE+EEE*EE(E)EidI6:
E(E)EE+EEE*EI7:
EE+EEE+EEE*EII8:
EE*EEE+EEE*EI9:
E(E)FOLLOW(E)=$,+,*,)移进移进-归约冲突归约冲突10/27/202220编译原理10/27/202221编译原理SLR分析表(存在冲突)分析表(存在冲突)10/27/202222编译原理使用文法以外信息来解决分析动作冲突使用文法以外信息来解决分析动作冲突考虑考虑id+id+id和和id+id*id形成格局形成格局栈栈输入输入0E1+4E7*id$面临+,归约面临*,移进面临)和$,归约I7:
EE+EEE+EEE*E10/27/202223编译原理4.8.2悬空悬空else的二义性的二义性SSSiSeS|iS|a10/27/202224编译原理I0:
SSSiSeSSiSSaI1:
SSI2:
SiSeSSiSSiSeSSiSSaI3:
SaI4:
SiSeSSiSI5:
SiSeSSiSeSSiSSaI6:
SiSeSFOLLOW(S)=i,e移进-归约冲突根据最近匹配原则选择移进动作10/27/202225编译原理10/27/202226编译原理I0:
SiSeSFOLLOW(S)=i,e移进-归约冲突根据最近匹配原则选择移进动作10/27/202227编译原理根据最近匹配原则选择移进动作图图4-49LR分析表分析表10/27/202228编译原理处理处理iiaea的语法分析动作的语法分析动作10/27/202229编译原理4.8.3LR分析的错误恢复qLR分析器在什么情况下发现错误访问动作表时若遇到出错条目,就检测到一个语法错误访问转移表时不会遇到出错条目若发现当前已扫描的输入不可能存在正确的后续,LR语法分析器立刻报错(决不做任何无效归约)SLR和LALR分析可能会在报错之前执行几步归约,但决不会把不正确的后继移进栈10/27/202230编译原理紧急方式错误恢复(panicmode)q退栈,直至出现状态s,它有预先确定的A的转移;
q抛弃若干个输入符号,直至找到a,它是A的合法后继;
q再把A和状态gotos,A压进栈,恢复正常分析。
10/27/202231编译原理s.栈栈.a.A发现错误发现错误s:
CAAb.CA.AAb.b10/27/202232编译原理s.栈栈.a.A发现错误发现错误sgoto(s,A).栈栈.a.A继续分析继续分析10/27/202233编译原理例4.49EE+E|E*E|(E)|ide1:
id(状态)3进栈,缺少运算对象e2:
从输入删除“)”,右括号不匹配e3:
+(状态)4进栈,缺少操作符e4:
)(状态)9进栈,缺少右括号10/27/202234编译原理输入id+)的分析和出错恢复分析栈输入串动作和错误信息0id+)$移进0id3+)$归约,Eid0E1+)$移进0E1+4)$e2右括号不匹配,从输入删除“)”0E1+4$e1缺少运算对象,假想的id进栈0E1+4id3$归约,Eid0E1+4E7$归约,EE+E0E1$accept10/27/202235编译原理4.9语法分析器的生成器语法分析器的生成器qYacc:
yetanothercompiler-compiler基于LALR
(1)的语法分析程序的生成器qYacc的GNU版叫做Bison。
qYacc是一种工具,根据编程语言的语法生成针对该语言的Yacc语法分析器。
它用巴科斯范式(BNF,BackusNaurForm)来书写。
10/27/202236编译原理491分析器的生成器分析器的生成器Yaccq按照惯例,Yacc源文件的后缀为y。
q调用Yacc编译器:
yaccYacc编译器编译器Yacc源程序源程序translateyytabcC编译器编译器ytabcaoutaout输入输入输出输出10/27/202237编译原理语法规则语法规则(.y文件文件)yyparse()YaccLex词法规则词法规则(.l文文件件)yylex()输出输出10/27/202238编译原理用用Yacc创建语法分析器包括四个步骤:
创建语法分析器包括四个步骤:
q通过在语法文件上运行Yacc生成一个解析器。
q说明语法:
编写一个y的语法文件(同时说明C在这里要进行的动作)。
写一个词法分析器来处理输入并将标记传递给解析器。
这可以使用Lex来完成。
编写一个函数,通过调用yyparse()来开始解析。
编写错误处理例程(如yyerror())。
q编译Yacc生成的代码以及其他相关的源文件。
q将目标文件链接到适当的可执行解析器库。
10/27/202239编译原理Yacc源程序的组成部分源程序的组成部分%C声明%对词法单元的声明%文法规则及翻译规则%用C语言编写的辅助性支持例程声明部分10/27/202240编译原理翻译规则翻译规则q产生式1|2|nq写成:
1语义动作|2语义动作|n语义动作;
10/27/202241编译原理q带单引号的单个字符终结符q语义动作:
$表示左部非终结符的属性值,$i表示右部第i个文法符号关联的属性值。
默认动作是$=$1;
expr:
exprexpr+term+term$=$1+$3;
$=$1+$3;
|term|term;
10/27/202242编译原理例例4.50台式计算器台式计算器EE+T|TTT*F|FF(E)|digitdigitq读入一个算术表达式,计算它的值并输出。
10/27/202243编译原理%#include#include%tokenDIGIT%tokenDIGIT%line:
exprnline:
exprnprintf(“%dn”,$1);
printf(“%dn”,$1);
expr+termexpr:
expr+term$=$1+$3;
term:
term*factor$=$1*$3;
|factor|factor;
factor:
(expr)$=$2;
|DIGIT|DIGIT;
%10/27/202244编译原理yylex()yylex()i