编译原理-LR分析法习题课共25页
7 编译原理-LR分析法
B 是产生式,则项目 B . 对活前缀 = 1 也是有 效的。
:伽马 :艾塔
据假设,存在一个规范推导S *Aw 1 B 2w
设2w
*
rm
xw,
则对任何B
有规范推导
S *Aw 1 B 2w 1 B xw 1 xw
所以 B . 对活前缀 1 也是有效的。
r1 r1 r1 r1
r2 r2 r2 r2
r3 r3 r3 r3
r5 r5 r5 r5
r4 r4 r4 r4
r6 r6 r6 r6
goto AB
6 7
8 9
第十四页,编辑于星期五:十点 三十四分。
三、LR分析器的结构和工作过程
LR分析器的结构如图,它的工作过程由算法1描述。
输入 a1 ... ai ... an #
+
I6 E E+ T
T E E+ T T T*F
I9
T T*F
(
T F F (E)
F I3
*
I4 F ( E)
E E+T E T
( T T*F
T F F (E)
F id
id
T
I8
I5
I7
F
I2
E F (E ) E + E+T
I6
I3
F id
(
id
I5
)
F (E) I11
F I3 T F
4. 其余情况报错.
第十八页,编辑于星期五:十点 三十四分。
SLR分析算法
算法2 (构造SLR分析表)
输入:一个拓广文法G
输出:对于G的分析表的action 子表和goto子表
wsx(编译原理第07章) LR分析法
LR分析法是给出一种能根据当前分析栈中的 符号串(通常以状态表示)和向右顺序查看输入 串的K个(K>=0)符号就可唯一地确定分析器的 动作是移进还是归约和用哪个产生式归约,因而 也就能唯一地确定句柄。 LR分析法的归约过程是规范推导的逆过程, 所以LR分析过程是一种规范归约过程。
LR(k)分析法可分析LR(k)文法产生的语言 –L :从左到右扫描输入符号, –R :最右推导对应的最左归约(反序完成最右推导)
第七章
• • • • • •
LR分析法
LR分析概述 LR(0)分析 SLR(1)分析 LR(1)分析 LALR(1)分析 二义性文法在LR分析中的应用
第1页,102页
• 前一部分我们已讨论过,自底向上分析方法是一种移 进-归约过程。 • 先复习一下:移进-归约分析
• 上一章的优先分析方法是当分析的栈顶符号串形成句 柄时就采取归约动作,因而自底向上分析法的关键问 题是在分析过程中如何确定句柄。 • 算符优先分析法存在的问题 –强调算符之间的优先关系的唯一性,这使得它的 适应面比较窄 –算法在发现最左素短语的尾时,需要回头寻找对 应的头
S
1 * 2 5
d
b
4 3 7
b
e
0
a
A
c B
6 9
第21页,102页
8
步骤 符号栈 输入符号串
动作
移进 移进 归约(A→b) 移进 归约(A→Ab) 移进 移进
S A B
8)
9) 10) 11)
# aAcd
#aAcB #aAcBe #S
e#
e# # #
归约(B→d)
移进 归约(S→aAcBe) 接受
A
对输入串abbcde#的移进-规约分析过程
编译原理 第06章_LR分析法(3)
的。将同心集合并为: I5,12: L→i•, =/# I4,11: L→*•R, =/# R→•L, =/# I7,13: L→*R•, =/# L→•*R, =/# I8,10: R→L•, =/# L→•i, =/#
6.4 LALR(1)分析法
我们看到合并同心集后的项目集其核心 部分不变,仅搜索符合并。对合并同心集后 的项目集的转换函数为GO(I,X)自身的合并, 这是因为相同的心之转换函数仍属同心集, 例如: GO(I4,11, i)=GO(I4, i)∪GO(I11, i)= I5,12 GO(I4,11, R)=GO(I4, R)∪GO(I11, R)= I7,13 GO(I4,11, *)=GO(I4, *)∪GO(I11, *)= I4,11
0. S' →S 1. S →L=R
2. S →R 3. L →*R
4. L →i 5. R →L
6.4 LALR(1)分析法
3. 若LALR(1)项目集族中不存在归约一 归约冲突,则该文法是LALR(1)文法。对例 中的文法,由于合并同心集后不存在归约— 归约冲突,所以该文法是LALR(1)文法。
S'→•S,# I0: R→•L,# S→•L=R,# L I :R→L•,# L→• * R,# S→•R,# 10 L I2:S→L•=R,# L→•i,# L→•*R,=/# L R→L•,# * i L→•i,=/# i R I11: L→*•R,# R→•L,# I3: S→R•,# I12: L→i•,# R→•L,# * i L→• * R,# R L→ * •R,=/# I4: I13:L→*R•,# L→•i,# R→•L,=/# I5: L→i•,=/# L→•*R,=/# R * i I7: L→*R•,=/# L→•i,=/#
《编译原理LR分析》ppt课件
a
– aAb[3]
a,aA
– aAcd[4]
a,aA,aAc
– aAcBe[1]
a,aA,aAc,aAcB
LR分析程序
LR 文法 对于一个cfg 文法, 假如可以构造一张 LR 分析表, 使得它的每一个入口均是唯一的 〔Sj,rj,acc,空白〕,那么称该 cfg 是LR 文法.
LR分析
特征: – .标准的 – .符号栈中的符号是标准句型的前缀,
动作
移进 移进 归约(A→b) 移进 归约(A→Ab) 移进 移进 归约(B→d) 移进 归约 承受
对输入串abbcde#的移进-规约分析过程
符号串abbcde是否是G[S]的子
S aAcBe aAcde aAbcde abbcde
步骤 符号栈 输入符号串 动作
状态栈 ACTION GOTO
1〕 #
LR〔0〕LC〔Ab〕=ab
LR〔0〕LC〔AAb〕=aAb
LR〔0〕LC〔Bd〕=aAcd 的正规式
〔 =VnVt〕上
x
0 S①
2
a 3
b④
5
a
A 6
7
b
⑧
9
a
A
c
10
11
12
d⒀
a
A
c
14 15
16
17
B 18 e ⒆
DFA
a
A
b
x
2
3
6
S
b
1
4
c
B
e
5
7
9
d
8
构造LR〔0〕工程集标准族
活前缀与句柄的关系:
G[S]:
R
=>αβω
《编译原理》第7章LR分析法
7.2 LR(0)分析表的构造4.构造LR(0)分析表——举例G[S′]:[0] S′→S [1] S→S(S)[2] S→εG[S]:[1] S→S(S)[2] S→εG[S]:[0] S′→SS′→.SS→.S(S)S→S.(S)S→.S(S) S→.7.3 SLR(1)分析表的构造1.LR(0)方法的不足LR(0)分析表的构造方法实际上隐含了这样一个要求:构造出的识别规范句型活前缀的有穷自动机中,每个状态均不能有冲突项目,这显然对文法的要求太高,也限制了该方法的应用。
7.3 SLR(1)分析表的构造1.LR(0)方法的不足例如,对文法G[S]:0S→E1 E→E+T2 E→T3 T→T*F4 T→F5 F→(E)6 F→i1I S→E.E→E.+TT→.T*F T→.FFT E #)(*+i G[S]:7.3 SLR(1)分析表的构造2.LR(0)方法的问题分析状态{ E→T.,T→T.*F}该状态含有移进-归约冲突,在分析表中表现为重定义。
7.3 SLR(1)分析表的构造2.LR(0)方法的问题①若U→x.ay ∈Ii ,且GO(Ii,a)=Ij,a∈VT,则ACTION[i,a]=“Sj”。
②若S′→S. ∈Ii,则置ACTION[i,$]=“acc”。
③若U→x. ∈Ii ,则对任意终结符a和$,均置ACTION[i,a]=“rj”或ACTION[i,$]=“rj”。
④若GOTO(Ii ,U)=Ij,其中U∈VN,则置GOTO[i,U]=“j”。
⑤除上述方法得到的分析表元素外,其余元素均置“报错标志”。
7.3 SLR(1)分析表的构造3.解决问题的方法所以在状态{ E→T.,T→T.*F}中,只需要向前看下一输入符号是*,还是FOLLOW(E)中的符号,便可解决冲突了。
7.3 SLR(1)分析表的构造3.解决问题的方法假设一个状态Ii中含有冲突项目I i ={ U1→x.b1y1,U2→x.b2y2,…,Um→x.bmym,V1→x.,V 2→x.,…,Vn→x.}若{b1,b2,…,bm}和FOLLOW(V1)、FOLLOW(V2)、…、FOLLOW(Vn)两两互不相交,就可以采用向前看一个输入符号的方法来解决状态中的冲突。
编译原理-清华大学-第6章-LR分析法(2+1,2+1)
r1 5
三、LR分析算法
状态/符号
Sm Xm Sm-1Xm-1 …… …… …… S1 X1
0#
输入缓冲区 a1…ai…an#
LR主控 程序
动作表 转移表 action goto
产生式 序列
分析表
置ip指向输入串w的第一个符号;
状态0和符号#分别进分析栈;
令S为状态栈的栈顶状态;a是ip指向的符号;
作为DFA的初始状态。
21
3)定义状态转换函数GO (产生新的项目集)
GO(I,X)定义为CLOSURE(J),其中I,J都是项目集, X(VN∪VT), J={AX•|当A•XI}。
J 的构造方法类似于词法分析的 MOVE函数
GO(I,X)类似于 CLOSURE( MOVE(I,X))
4)构造LR(0)项目集规范族的算法
2、S′S• 称为句子识别态或接受项目;
3、转换关系:项目i为XX1…Xi-1•Xi…Xn, 项目j为XX1…Xi • Xi+1…Xn, 则从项目i画一弧线射向j,标记为Xi;
4、若项目i为X•A,其中A是非终结符,则从i项目画 弧射向所有A•的项目,V*
5、规约项目为终态用双圈表示,双圈外有*号者为接受态 18
(最左规约,规范规约)
ab[2]b[3]cd[4]e[1]
(用[2]归约)
<= aAb[3]cd[4]e[1]
<= aAcd[4]e[1] <= aAcBe[1]
(用[3]归约) (用[4]归约) (用[1]归约)
<= S
其中<=表示规约
问题:在归约过程中,那些是可归前缀?
13
4、活前缀:G=(Vn,Vt,P,S'), 若有规范推导 S′* αAωαβω,
编译原理课件04(5)LR分析法
4.5.1 LR分析器的逻辑结构和工作过程
若当前读到的输入符号是‘*’ ,根据文法 可知‘*’的优先级高于‘+’,栈顶尚未形成 句柄,则应将‘*’移入栈中; 若当前读到的输入符号是‘+’或)或‘$’ 时,根据文法可知栈顶已形成句柄,则应将符 号串E+T归约为E; 若当前读到的输入符号不是上述四种符号之 一,则表示输入串有语法错误。 由此可知,LR分析器的每一步分析工作,都 是由栈顶状态和现行输入符号所唯一确定的。
4.5.1 LR分析器的逻辑结构和工作过程
接受(acc): 表示分析成功。此时,分析栈 中只剩文法开始符号S'和当前读到的 输入符号是‘$’。即输入符号串已经 结 束。 报错:表示输入串含有错误,此时出现栈顶 的某一状态遇到了不该遇到的输入符 号。
见表
4.5.1 LR分析器的逻辑结构和工作过程
4.5.2 LR(0)分析法
这也就是说,在LR分析过程中的任何 时刻,栈中的文法符号应是某一规范句型 的活前缀,这是因为一旦句型句柄在栈的 顶部形成,就会立即被归约,因此,只要 输入串已扫描过的部分保持可归约成一个 活前缀,那就意味着所扫描过的部分是正 确的。
4.5.2 LR(0)分析法
这样一来,我们对句柄的识别就变成 对规范句型活前缀的识别。 例如,对前例,文法G[S]的规范句型 aaAbb的句柄是aAb,栈中符号串为aaAb, 此句型的活前缀为ε,a,aa,aaA,aaAb,它们 均不含句柄右边符号b。
例 1 设文法G′为: 0. S'→S 1. S→A 2. S→B 3. A→aAb 4. A→c 5. B→aBb 6. B→d 相应于文法的LR分析表如下表所示。
状 态 a
0 1 2 3 4 5 6 7 8 9 10 S4 r1 r2 S4 r4 r6
编译原理SLR分析法
第21页/共57页
I6:S →bAa·
I A →aS·c 7: A →aS·b S →S·b
b
I9:
A
→aSb· S →Sb·
ห้องสมุดไป่ตู้
4.5.3 SLR(1)分析法
分析所有这些项目集,可知在项目集
I1,I5中存在移进—归约冲突,I9中存在
第23页/共57页
4.5.3 SLR(1)分析法
I9={ A →aSb·, S →Sb· } 由于有 FOLLOW(A) ∩FOLLOW(S) ={a}∩{b, c, $}=Φ, I9中的归约—归约冲突 也可用SLR(1)方法解决。 所以该文法是SLR(1)文法。相应的 SLR(1)分析表如下表:
第7页/共57页
4.5.3 SLR(1)分析法
因此,当一个LR(0)项目集规范族中存 在一个含移进—归约冲突和归约—归约冲 突的项目集时
IK={ X→δ·bB, A→α·, B→r·}
则在分析表第K行中遇输入符号b必然 会出现多重定义元素。
对含冲突的项目集,仅根据LR(0)项目 本身的信息是无法解决冲突的。需要向前 查看一个输入符号以考察当前所处的环境。
根据构造LR(0)分析表的方法,构造 出的LR(0)分析表中在2状态和9状态下 面临输入符号‘*’时含多重定义元素, 见下表。
第4页/共57页
表达式文法的LR(0)分析表
状态
ACTION
id + * ( ) $
0 S5
S4
1
S6
acc
2 r2 r2 S7r2 r2 r2 r2
3 r4 r4 r4 r4 r4 r4
《编译原理》第5章LR分析方法PPT课件
4、LR(0)项目集族 1)基本概念
• 字的前缀:指该字的任意首部。
• 活前缀:指规范句型的一个前缀,它不含句柄之后的 任何符号。在它之后增添一些终结符号后,就可以使 之成为规范句型。即:
• 对于文法G,若 S* ,Vt* ,则称为活前缀。
• 在LR分析的过程中,假定输入串是一个句子,任何时 候符号栈里的文法符号都构成活前缀,配上输入串的 剩余部分,就成为规范句型。
S' E E aA | bB A cA | d B cB | d
5. E aA· 8. A cA ·
13. E bB· 16. B cB ·
2)画出NFA
识别活前缀的NFA
5、LR(0)项目集规范族的构造:
• LR(0)项目集规范族的定义:构成识别一个文 法活前缀的DFA的项目集的全体
• 构造方法有两种: – 1) 使用第三章的子集法将NFA确定化 – 2) 直接使用闭包和状态转换函数进行计算
若原文法g的开始符号为s则增加一个非终结符s和一个产生式s利用go函数对c中的每个项目集和每个符号x计算其下一状态并将下一状态goix加入到c中直到c中状态数不再增加c即为文法g的lr0项目集规范族lr0企业文化就是传统氛围构成的公司文化它意味着公司的价值观诸如进取守势或是灵活这些价值观构成公司员工活力意见和行为的规范
• 归约:按某个产生式A→β进行归约,若产生式的右 端长度为r,则两个栈顶的r个元素同时出栈。将归约后 的符号A进符号栈; 根据新栈顶状态Sm-r和归约符号A查 GOTO表,S=goto[Sm-r, A]进状态栈。三元式变为:
(S0S1 … Sm-r S, # X1X2…Xm-rA, aiai+1…an #)
符号 状态
x1
编译原理(清华)第七章LR分析法
文法的识别活前缀的有穷自动机以“项目”作为它的状态在文法G中每个产生式的右部适当位置添加一个圆点构成项目例:产生式 U→XYZ 对应有4个项目 [0] U→ • XYZ [1] U→X • YZ [2] U→XY • Z [3] U→XYZ • 产生式A→ε只有一个项目A→•
GOTO
ACTION
输入串
符号栈
状态栈
步骤
A
3
3
3
A
3
7
B
7
1
S
1
7.2 LR(0) 分析
使用LR(0)分析表的LR分析器称为LR(0)分析器。LR(0)分析器在分析的过程中只根据符号栈的内容就能确定句柄,不需要向右查看输入符号对文法的限制较大,对绝大多数高级语言的语法分析器不适用构造LR(0)分析表的思想和方法是构造其他LR分析表的基础。
将NFA确定化得到:
S[0],ab[2],aAb[3],aAcd[4],aAcBe[1]
ACTION
GOTO
a
cHale Waihona Puke ebd#
S
A
B
X
S2
1
1
acc
2
S3
4
3
r2
r2
r2
r2
r2
r2
4
S6
S5
5
r3
r3
r3
r3
r3
r3
6
S7
8
7
r4
r4
r4
r4
r4
r4
8
S9
9
r1
r1
r1
r1
r1
r1
对任何一个上下文无关文法只要构造出它的识别活前缀和可归前缀的有穷自动机,就可以构造其相应的分析表(ACTION表和GOTO表),进行LR分析
编译原理张晶 LR分析法图文PPT学习教案
第6页/共113页
第六章 LR分析法及分析程序自动构造(8)
6.1 LR分析器
输入带
下
推
总控程序
输出
栈
分析表
带
二、LR分析器
•一个LR分析器实际上是带有下推栈的确定的有限状 态自动机。可将一个“历史”与这个“历史”下的展 望信息综合为抽象的一个状态
第7页/共113页
第六章 LR分析法及分析程序自动构造(9)
+i #
第24页/共113页
E E+T
ET
T T*F
TF
•F (E)
•F i
第六章 LR分析法及分析程序自动构造(26)
5
i
7
*
2
T
0
#
状态、符号栈
+i #
第25页/共113页
E E+T
ET
T T*F
TF
•F (E)
•F i
第六章 LR分析法及分析程序自动构造(27)
10
F
7
*
2
T
0
#
状态、符号栈
6.1 LR分析器 一、LR分析法的基本思想
在规范归约时,当一串貌似句柄的符号串呈现于栈顶时, LR分析法根据三方面的信息找句柄:
—历史:记录在栈内的符号串移进,归约的历史情况 —展望:预测句柄之后可能出现的信息; —现实:读头下的符号 注:LR分析法的基本思想是符合人的思维习惯的,但实现
有困难,因为基于“历史”对未来的“展望”可能存在多 种可能。当把“历史” 和“展望”材料综合在一起时复杂 性就大大增加。如果简化对“展望”的要求,就可获得实 际可行的分析算法。
6.1 LR分析器 二、 LR分析器
编译原理chapter7LR
10
#
i+(i)#
2 04
#i
+(i)#
3 02
#T
+(i)#
4 01
#E
+(i)#
5 015
#E+
(i)#
6 0153 #E+(
i)#
7 01534 #E+(i
)#
8 01532 #E+(T
)#
9 01536 #E+(E
)#
10 015367 #E+(E)
#
11 0158 #E+T
S9
r4 r4 r4 r4 r4 r4
r1 r1 r1 r1 r1 r1
3 7
步骤 6 7 8 9 10 11
状态栈 023 0235 02358 02357 023579 01
符号栈 #aA #aAc #aAcd #aAcB #aAcBe #S
输入串 cde# de# e# e# # #
ACTION
S5 S8 r4 S9 r1 acc
GOTO
7 1
1) E –> E + T 2) E –> T 3) T –> (E) 4) T –> i
对输入串i+(i)#Байду номын сангаас行分析
1) E –> E + T 2) E –> T 3) T –> (E) 4) T –> i
对输入串i+(i)#进行分析
步骤 状态栈 符号栈 剩余输入串
0 S2 1
1 acc
2
S4
3
S5
S6
4 r2 r2 r2 r2 r2 r2
编译原理上机实验程序(LR分析)
编译原理上机实验程序(LR分析)小型编译程序:高级语言到四元式的编译#include "stdio.h" /*如果使用TC的话,需要配置头文件路径*/ #include "string.h" /*如果使用VC的话,可以配置头文件conio.h*/#define ACC -2/************************/#define sy_if 0#define sy_then 1#define sy_else 2#define sy_while 3#define sy_begin 4#define sy_do 5#define sy_end 6#define a 7#define semicolon 8#define e 9#define jinghao 10#define S 11#define L 12#define tempsy 15#define EA 18 /*E and*/#define E0 19 /*E or*/#define plus 34#define times 36#define becomes 38#define op_and 39#define op_or 40#define op_not 41#define rop 42#define lparent 48#define rparent 49#define ident 56#define intconst 57/*********************************/char ch='\0'; /*从字符缓冲区读取当前字符*/int count=0; /*词法分析结果缓冲区计数器*/static char spelling[10]={""}; /*存放识别的单词符号*/static char line[81]={""}; /*一行字符缓冲区,最多80个字符*/ char *pline; /*字符缓冲区指针*/static char ntab1[100][10]; /*变量名表,共100项,每项长度10*/struct ntab{int tc; /*真值*/int fc; /*假值*/}ntab2[200]; /*在布尔表达式E中保存有关布尔变量的真、假值*/ int label=0; /*指向ntab2的指针*/struct rwords{ /*存放临时变量的表的定义*/char sp[10];int sy;};/*(保留字表)匹配表的结构,用来与输入缓冲区中的单词进行匹配*//*匹配表初始化,大小为10*/struct rwords reswords[10]={{"if",sy_if},{"do",sy_do},{"else",sy_else},{"while",sy_while},{"then",sy_then},{"begin",sy_begin},{"end",sy_end},{"and",op_and},{"or",op_or},{"not",op_not}};struct aa{int sy1; /*存放单词符号的种别编码*/int pos; /*存放单词符号自身的值*/}buf[1000], /*词法分析结果缓冲区,保存识别出来的单词符号*/ n, /*读取二元式的当前符号*/n1, /*当前表达式中的符号*/E, /*非终结符*/sstack[100], /*算术或布尔表达式加工处理使用的符号栈*/ibuf[100], /*算术或布尔表达式使用的缓冲区*/stack[1000]; /*语法分析加工处理使用的符号栈*/struct aa oth; /*四元式中空白位置*/struct fourexp{char op[10];struct aa arg1;struct aa arg2;int result;}fexp[200]; /*四元式的结构定义*/int ssp=0; /*指向sstack栈指针*/struct aa *pbuf=buf; /*指向词法分析缓冲区的指针*/int nlength=0; /*词法分析中记录单词的长度*/int lnum=0; /*源程序行数记数,源程序长度*/int tt1=0; /*变量名表指针*/FILE *cfile; /*源程序文件,~为结束符*//*FILE *mfile;*/int newt=0; /*临时变量计数器*/int nxq=100; /*nxq指向下一个形成的四元式的地址*//*每次执行gen()时,地址自动增1*/int lr; /*扫描LR分析表1过程中保存的当前状态值*/int lr1; /*扫描LR分析表2或表3所保存的当前状态值*/ int sp=0; /*查找LR分析表时状态栈的栈顶指针*/int stack1[100]; /*状态栈1的定义*/int sp1=0; /*状态栈1的栈顶指针*/int num=0; /*算术或布尔表达式缓冲区指针*/struct ll{int nxq1; /*记录下一条四元式的地址*/int tc1; /*真值链*/int fc1; /*假值链*/}labelmark[10]; /*记录语句嵌套层次的数组,*//*即记录嵌套中每层的布尔表达式E的首地址*/ int labeltemp[10]; /*记录语句嵌套层次的数组,*//*即记录每层else之前的四元式地址*/int pointmark=-1, /*labelmark数组指针*/pointtemp=-1; /*labeltemp数组指针*/int sign=0; /*sign=1,为赋值语句;sign=2,为布尔表达式。