第四章 自顶向下语法分析方法 语法分析的主要工作:是识别由词法分析给出的单词 序列是否是给定的正确句子(程序)。

Slides:



Advertisements
Similar presentations
林園高中適性入學 高雄區免試入學 及 特色招生介紹 1. 國中學生 國中教育會考 1 ( 每年五月 ) 特色招生 術科考試 五專 免試入學 ( 每年六月 ) 特色招生 甄選入學 高中高職 免試入學 擇一報到 林園高中適性入學  入學管道流程 2.
Advertisements

2016/9/41 12 年國教 入學方案宣導資料. 2016/9/42 安全快樂 健康發展 活力多元 創意發展 適性揚才 特色發展 務實致用 卓越發展 學前教育 國中小教育 高級中等教育 大專以上教育 教育促進個人向上發展教育促進個人向上發展 教育是國家最有利的投資教育是國家最有利的投資.
說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
2011年会计初级职称全国统考 初级会计实务 教案 主讲:高峰 2010年12月.
第四章:长期股权投资 长期股权投资效果 1、控制:50%以上 有权决定对方财务和经营.
第八章 互换的运用.
苏教版小学语文 二年级下册(五~八)单元教材分析
第四章 组合逻辑电路 第 四 章 组 合 逻 辑 电 路.
温 度 定义: 表示物体冷热程度的物理量。 国际单位:开尔文(K) 单位 常用单位:摄氏度(℃) 原理: 根据液体热胀冷缩的性质制成的。
簡報大綱 壹、現況說明 貳、改革方案 參、改革效益 肆、信賴保護的問題 伍、公保再修正情形 陸、外界關心的問題 1 1.
第二章 遺傳 2‧4 突變.
第四章 细胞的增殖和分化 第三节 细胞的分化 个体发育的基础.
电路和电流 考点知识梳理 中考典例精析 课堂达标训练 专题训练.
江苏省2008年普通高校 招生录取办法 常熟理工学院学生处
“国培计划(2015)”——吉林省农村 幼儿园教师信息技术应用提升培训
2014年初中生物学业水平抽测分析.
第二章 文法和语言 2.1 文法的基本概念 符号和符号串 2.2 句型的分析 文法和语言的形式定义 推导与递归 文法的分类 语法树
习题与试题 认真复习,重点是掌握基本概念。基本概念掌握了,相当一部分试题的解就有了
第五章 经纪业务相关实务.
巧用叠词,妙趣横生.
第二章 实时系统的特征及其任务 计算机学院 潘薇
第7章 数字信号处理中的有效字长效应.
民法总论 北京师范大学珠海分校 法律与行政学院 白 非.
第2章 LR分 析 法 LR分析法是一种自下而上进行规范归约的语法分析方法,LR指“自左向右扫描和自下而上进行归约”。LR分析法比递归下降分析法、LL(1)分析法和算符优先分析法对文法的限制要少得多,对大多数用无二义的上下文无关文法描述的语言都可以用LR分析器予以识别,而且速度快,并能准确、及时地指出输入串的任何语法错误及出错位置。LR分析法的一个主要缺点是,若用手工构造分析器则工作量相当大,因此必须求助于自动产生LR分析器的产生器。
第五章 电流和电路 制作人 魏海军

第四章 时间序列的分析 本章教学目的:①了解从数量方面研究社会经济现象发展变化过程和发展趋势是统计分析的一种重要方法;②掌握时间数列编制的基本要求;③理解和掌握水平速度两方面指标的计算及运用④理解和掌握长期趋势分析和预测的方法。 本章教学重点:现象发展的水平指标和速度指标。 本章教学难点:现象变动的趋势分析。
第16课 抗日战争.
离散数学 Discrete mathematics
出入口Y27 往塔城街口/中興醫院 出入口Y25 往延平北路一段/中興醫院 出入口Y23往延平北路一段 出入口Y21往延平北路一段
第1节 光的干涉 (第2课时).
第4章 种群和群落 第3节 群落的结构 自主学习案   合作探究案 课后练习案. 第4章 种群和群落 第3节 群落的结构 自主学习案   合作探究案 课后练习案.
编译原理与技术 课程总结.
Part5语法分析 授课:胡静.
自上而下分析 4.4.
自上而下分析 4.4.
第6章 自底向上优先分析法 自底向上优先分析概述 简单优先分析 算符优先分析 返回目录.
第六章 采用中、大规模 集成电路的逻辑设计.
第九讲 旅游资源调查报告的撰写 旅游资源调查 旅游资源评价 调查报告格式.
語法與修辭 骨&肉 老師:歐秀慧.
LR(1)分析方法.
第四章 语法分析.
Part5语法分析 授课:胡静.
编译原理实践 5.给定语法的语法分析程序构造.
LL分析法 LL分析法的分析器由一张预测分析表(LL(1)分析表),一个控制程序(表驱动程序)及一分析栈组成 输入
第五章 语法分析——自下而上分析 自上而下分析法(Top-down) 自下而上分析法(Bottom-up) 国防科技大学计算机系602教研室.
第三课时 匀变速直线运动的位移与时 间的关系
第三章 文法和语言 本章目的为语言的语法描述寻求工具,以便: 对源程序给出精确无二义的语法描述。(严谨、简洁、易读)
10.2 排列 2006年4月6日.
练习: 由三个不同的英文字母和三个不同的阿拉伯数字组成一个六位号码(每位不能重复),并且3个英文字母必须合成一组出现,3个阿拉伯数字必须合成一组出现,一共有多少种方法?
编译原理 第四章 语法分析—自上而下分析 编译原理.
语法分析 本章内容 语法分析器:把词法分析生成的词法单元流翻译成语法分析树(parse tree)
公務人員退休制度未來改革方向 銓敘部 中華民國102年2~3月(座談會).
中级会计实务 ——第三章 固定资产 主讲:孙文静
「基本學力測驗」與「學科 能力測驗」國文試題評析
第二部分 集合论 第六章 集合代数 主要内容 集合的基本概念 属于、包含 幂集、空集 文氏图等 集合的基本运算 并、交、补、差等 集合恒等式
107上五年級〈社會科〉學校日簡報 教師個人檔案 ★民國77年8月開始任職本校 ★在本校擔任自然科任1年、導師8年、
電子白板百萬小學堂 本活動建議搭配電子白板 學生最多可分成2~6組(請按組別按鈕) 老師可以視時間多少,來進行活動 每一組要回答十個問題。
9.1.2不等式的性质 周村实验中学 许伟伟.
两个变量的线性相关 琼海市嘉积中学 梅小青.
SLR(1)分析方法.
第四章 语法分析 南京大学计算机系 戴新宇
递归下降法 1 递归下降法语法分析原理 递归子程序方法/递归下降法 对每个非终极符按其产生式结构产生相应语法分析子程序。
1.8 完全平方公式(一) 锦州市实验学校 数学组(3).
知识点5---向量组的最大无关组 1. 最大线性无关组的定义 2. 向量组秩的定义及求法 向量组的秩和对应矩阵秩的关系 3.
编译原理 第一章 编译程序概述 第二章 PL/0编译程序的实现 第三章 文法和语言 第四章 词法分析 第五章 自顶向下语法分析方法
幂的乘方.
圣经概論 09.
利用十字交乘法將二次多項式化為兩個一次式的乘積。
编译原理 第一章 编译程序概述 第二章 PL/0编译程序的实现 第三章 文法和语言 第四章 词法分析 第五章 自顶向下语法分析方法
Presentation transcript:

第四章 自顶向下语法分析方法 语法分析的主要工作:是识别由词法分析给出的单词 序列是否是给定的正确句子(程序)。 语法分析常用的方法:自顶向下的语法分析和自底向 上的语法分析两大类。

自顶向下分析思想 自顶向下的方法: 从文法的开始符号(设为〈程序〉)开始进行分析,逐渐 推导的往下构造语法树,使其树叶正好构造所给定的源程序串。 自顶向下方法的关键: 是确定在推导过程中选择候选式的问题。当进行推导时, 一个非终结符可能对应多个产生式,这样我们就无法事先知道 应该用哪个产生式,因此必须对文法作一些限制,以便在任何情况下都能确定应该用的产生式。 自顶向下的主要思想: 从开始符出发导出句型并一个符号一个符号地与给定终结 符串进行匹配。如果全部匹配成功,则表示开始符号可推导出 给定的终结符串。因此判定给定终结符号串是正确句子。

自顶向下的缺点: 在推导过程中,如果对文法不做限制。那么产生式的选择成为无根据的,只好一一去试所有可能的产生式,直至成功为止。这种方法的致命弱点是不断地回溯,大大影响速度。 所以自顶向下分析法又分为确定的和不确定的两种: 确定的分析方法需对文法有一定的限制,但由于实现方法简单,直观,便于手工构造或自动生成语法分析器,因此仍是目前常有的方法之一。 不确定的方法即回溯的分析方法。这种方法实际上是一种穷举的试探方法,因此效率低,代价高,因此极少使用。

4.2 自上而下分析面临的问题 解:推导过程为: 例4.1若有文法G[S]: S → pA S → qB A → cAd A → a 4.2 自上而下分析面临的问题 例4.1若有文法G[S]: S → pA S → qB A → cAd A → a 若有输入串w = pccadd. S p A c d a 考察自顶向下的推导过程。 解:推导过程为: pA pcAd pccAdd pccadd S     其相应的语法树见右图: 这个文法的特点: [1]每个产生式的右部都由终结符号开始。 [2]如果两个产生有相同的左部,那么它们的右部由不同的终结符开始。 显然对于这样的推导中完全可以根据当前的输入符号决定选择哪个产生式往下推导。因此分析过程是唯一的。

解:自顶向下的推导过程为: 例4.2 若有文法G2[S]: S Ap S Bq A a A cA B b B dB 若有输入串w = ccap. 考察自顶向下的推导过程。 S p A c a 解:自顶向下的推导过程为: Ap cAp ccAp     ccap S 其相应的语法树见右图: 这个文法的特点: [1]产生式的右部不全是由终结符号开始。 [2]如果两个产生式有相同的左部,它们的右部由不同的终结符或非终结符开始。 [3]文法中无空产生式。

小结: 在上述推导过程中,对于产生式中相同左部含有非终结符打头的右部时,在推导中选用哪个产生式是不能直接知道的。 对W=ccap为输入串时,其第一个符号为c,这时从S出发选择S → Ap,还是选择S →Bq。其根据是要知道 A或B它们是否能推导以c打头的符号串,即它们的首符集是什么。若c是Ap的首符集的元素,且不在Bq的首符集中,则选择S →Ap往下推导。反之,若c在Bq的首符集中,不在Ap的首符集中,则选择S →Bq往下推导。其它情况为不确定推导或出错。 因此,在推导前有必要求出每个文法符号的首符集。

设G=(VN ,VT ,P,S)是上下文无关文法,α是G的任一符号串,则有: 一.首符集,后继符集与选择集的定义: 定义4-1(首符集定义): 设G=(VN ,VT ,P,S)是上下文无关文法,α是G的任一符号串,则有: FIRST(α)={a | α * aβ,a∈ VT, α、β ∈V* }  特别地,若α * ε,则规定ε ∈FIRST(α)  即: FIRST(α)是从α出发推导出的所有符号串首终结符或可能的ε构成的集合。

文法G2[S]: S Ap S Bq A a A cA B b B dB 这样在文法 G2中,关于S的两个产生式虽然都以非终结符开始,但它们右部符号串可以推导出首符集合互不相交,因此可根据当前的输入符号是属于哪个产生式右部的首符号集合而决定选择相应产生式进行推导。因此是确定的自顶向下分析。

解: 当文法中有空产生式时,如例: 例4.3: 若有文法G3[S]: S→aA S →d A→ bAS A→ε 若有输入串W=abd。 考察自顶向下的推导过程。 S a A b A S 解: ε d S abAS abS abd  aA    相应语法树为右图:

小 结: 从上述推导过程中我们可以在第二步到第三步的推导 中,即abAS abS时,因当前面临输入符号为d,而最左非终结符A的产生式右部的开始集合都不包括d,但有ε,因此对于d的匹配自然认为只能依赖于在可能的推导过程中A的后面的符号。所以这时选用产生式A →ε 往下推导,而当前A后面的符号为S,S产生式右部的开始符号包括了d,所以匹配。  由此可以看出,当某一非终结符的产生式中含有空产 生式时,它的非空产生式右部的首符号集两两不相交,并与在推导过程中紧跟该非终结符右边可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。为此可定义一个文法符号的后继符集合为: (定义4.2)

定义4.2: 设G=(VN , VT ,P,S)是上下文无关文法,A∈VN的后继符集合为: FOLLOW(A)={a | S * …Aa… ,a∈VT}  特别地,若S * …A,则#∈FOLLOW(A) (这里#不是文法中的符号,而一个特别的表示输入串的结束符或称句子括号如 #输入串#) 表示:所有在句型中紧挨着A出现的终结符或#均是 FOLLOW(A)的元素。   因此当文法中含有形如: A→α和 A→β的产生式时,其中A∈VN ,α,β∈V*,当α和β不同时推导出空串时,设α * ε,β * ε,则当FIRST(α) ∩(FIRST(β)∪FOLLOW(A))=φ时,对于非终结符A的替代仍可唯一地确定候选。 \

定义4.3 定义选择集合SELECT如下: 定义4.3:对于给出上下文无关文法的产生式A→α,A∈ VN,α∈V*,则 FIRST(α), 当α ε时 FIRST(α)∪FOLLOW(A),否则 ﹨ * 

三种集合的构造算法: 注:三种集合均为终结符集 (一) 求FIRST(X)的算法 对每一文法符号X∈(VN∪VT),求FIRST(X). (a)若X∈VT,则令FIRST(X)={X}; (b)若X∈VN,且有产生式X→a….,(a∈VT),则令a∈FIRST(X); (c) 若X∈VN,有X→ε,则令 ε∈FIRST(X); (d)若 X∈VN, y1, y2,…..yi都∈VN,且有产生式X→ y1 y2…..yn, (e)当(d)中所有yi * ε(i= 1,2,….,n),  当y1, y2,…..yi-1 都 * ε时,(其中1≤i≤n),则FIRST(y1)-ε, FIRST(y2)-ε,….,FIRST(yi-1 )-ε,FIRST(yi)都包含在 FIRST(X)中。 则 FIRST(X)=FIRST(y1)∪FIRST(y2)∪….∪FIRST(yn)∪{ε} 反复使用上述(b)~(d) 步直到每个符号的FIRST集合不再增加 为止。

(二)求 FIRST(α)的算法(α= x1 x2 …. xn): 1.若n=0,即α=ε,则令FIRST(α)={ε}; 2.否则,对1≤i≤n,求FIRST(xi) 3.若n=1,则令 FIRST(α)=FIRST(x1); 4.若n≥2且对一切j=1,2,….,i-1都有ε∈FIRST(xj). 则令FIRST(xi )-{ε} FIRST(α),其中2≤i≤n; 若对一切 j=1,2,…,n都有ε∈FIRST(xj),则令ε∈FIRST(α) 或:1.把FIRST(x1)中所有非ε元素加入到FIRST(α)中,即 FIRST(α )=FIRST(x1)-{ε }; 若FIRST(x1)包含有ε,则把FIRST(x2)的所有非ε元素加入到 FIRST(α)中,即FIRST(α)=FIRST(α)∪ (FIRST(x2)-{ε}); 若FIRST(x1)和FIRST(x2)都包含有 ε,则把FIRST(x3)的所有 非ε元素加到FIRST(α)中;…… 照此方法继续,一直到考察到xn。 2.若FIRST(xi ),i= 1,2,…,n;即每个FIRST(xi )中都有ε。则将ε加 到FIRST(α)中。特别地, 若 α=ε ,则FIRST(α)={ε}.

(三).求FOLLOW(A)的算法(A∈ VN): (a)对文法开始符号S,令# ∈ FOLLOW(S). (b)若B→αAβ是一个产生式,则令FIRST(β)-{ε} 属于FOLLOW(A); (c) 若B→αA是一个产生式,或B→αAβ是一个产生 式且有ε∈FIRST(β),则令FOLLOW(B)是 FOLLOW(A)的子集。即把FOLLOW(B)的所有元素 加入到FOLLOW(A)中。 (d)反复使用(b)直到每个非终结符的 FOLLOW集合 不再增加为止。

(四) 求SELECT(A→α)的算法: (a)求FIRST(α); (b)若ε∈FIRST(α),则令SELECT(A→α)=FIRST(α) 否则求FOLLOW(A), 并令SELECT(A→α)=FIRST(α) ∪ FOLLOW(A). 例:有文法:E→TE' E'→+TE' |ε T→FT' T'→*FT' |ε F→i | ( E ) 求其三种集合。

解: 例:有文法:E→TE' E'→+TE'|ε T→FT' T'→*FT'|ε F→i| (E) 求其三种集合。 FIRST(E)=FIRST(T)=FIRST(F)={i, ( } FIRST(E')={+,ε} FIRST(T')={*,ε} FOLLOW(E)=FOLLOW(E')={ ),#} FOLLOW(T)=FOLLOW(T')={+,),#} FOLLOW(F)={*,+,),#} SELECT(E→TE')=FIRST(T)={i,( } SELECT(E'→+TE')=FIRST(+TE')={+} SELECT(E'→ε)=FIRST(ε)∪FOLLOW(E')={ε,),#} SELECT(T→FT')=FIRST(F)={i,(} SELECT(T'→*FT')=FIRST(*FT')={*} SELECT(T'→ε)=FIRST(ε)∪FOLLOW(T')={ε,+,),#} SELECT(F→i)=FIRST(i)={i} SELECT(F→(E))=FIRST(i) ={(}

4.3 LL(1)分析法 例:设有文法G[S]:S→aAS , S→b , A→bA , A →ε 非终结符A的两个不同产生式,A →α ,A →β ;满足 SELECT(A →α ) ∩ SELECT(A →β )= Ф 。 其中, α、 β不能同时 * ε。  例:设有文法G[S]:S→aAS , S→b , A→bA , A →ε SELECT(S→aAS)=FIRST(aAS)={a} SELECT(S→b)={b} SELECT(A→bA)={b} SELECT(A→ε)=FIRST(ε)∪FOLLOW(A)={a,b,ε} ∵SELECT(S→aAS)∩SELECT(S→b)={a}∩{b}=φ SELECT(A→bA)∩SELECT(A→ε)={b}∩{a,bε}≠φ 故文法 G[S]不是LL(1)文法。

文法的等价变换 确定的自顶向下分析要求给定语言的文法必须是 LL(1) 形式,然而,不一定每个语言都是LL(1)文法,对一个语言的 而,我们设法消除文法中的左递归,提取左公共因子对文法 进行等价变换。 1.提取左公共因子 若文法中含有形如:A→α β| α γ的产生式,这导致了对相同的产生式右部的FIRST集相交。 即有SELECT(A→ α β )SELECT(A→ α γ)≠φ 不满足LL(1)文法的充要条件。等价交换为: A→ α(β| γ) A→ α A' A'→ β| γ

更一般地: 结论: 对A→ α β1| α β2 | …| α βn提取左公因子为: A→ α A' A'→ β1| β2 | …| βn 若在βi , βj , βk…中仍含有左公共因子,可再进行提取,这样反复进行提取直到所引进的新非终结符的有关产生式均无左公共因子为止。 结论: 一个文法提取了左公共因子后,只解决了相同左部产生式的 右部FIRST集不相交问题。当改写后的文法不含有空产生式,且 无左递归时,则改写后的文法是LL(1)文法。否则还需用LL(1)文法的判别方法进行判断才能确定是否为LL(1)文法。

2.消除左递归 a)把直接左递归改写为右递归: 一个文法含有下列形式的产生式之一时: 1)A→A β, A∈VN, β∈V* 2)A→B β, B→A α, A,B∈VN, α ,β∈V* 则称该文法是左递归的。 含有左递归的文法不能采取自顶向下分析法。 消除左递归方法有: a)把直接左递归改写为右递归: 设有文法产生式:A→Aβ|γ. 其中β非空, γ不以A打头。 可写为:A→γA' A'→βA' | ε 一般情况下,假定关于A的产生式是: A→A α1| A α2 | … | A αm| β1| β2 | …| βn 其中, αi(1≤i≤m)均不为空, βj(1≤j≤n)均不以A打头。 则消除直接左递归后改写为: A→ β1 A' | β2 A' | … | βn A' A'→ α1 A' | α2 A' | … | αm A' | ε

例: 解: E→TE' 有文法G(E):E→E +T |T A→Aβ|γ T→T*F | F 改写为: F→i| (E) A→γA' 消除该文法的直接左递归。 A→Aβ|γ 改写为: A→γA' A'→βA' | ε 解: E→TE' E'→+TE'|ε T→FT ' T'→*FT'|ε F→i| (E)

b)消除间接左递归: 对于间接左递归的消除需要先将间接左递归变为直接左 递归,然后再按a)清除左递归。 以文法G6为例: 消除左递归后得到: (1)A→aB (2)A→Bb (3)B→Ac (4)B→d 消除左递归后得到: B→aBcB' |dB' B'→bcB' |ε 再把原来其余的产生式A→aB,A→Bb加入,最终得到等价文法为: (1) A→aB (2) A→Bb (3) B→(aBc|d)B' (4) B'→bcB'|ε 用产生式(1),(2)的右部代替产生 式(3)中的非终结A得到左部为B的 产生式: (1)B→aBc (2)B→Bbc (3)B→d

c)消除文法中一切左递归的算法 设非终结符按某种规则排序为A1, A2,… An 。 For i:=1 to n do begin For j:=1 to i-1 do 若Aj的所有产生式为: Aj →δ1| δ2 | … | δn 替换形如Ai → Aj γ的产生式为: Ai →δ1γ |δ2γ | … |δnγ end 消除Ai中的一切直接左递归

4.4 递归下降分析程序构造 在程序语言的语法定义中有许多采用递归定义。我们在对 它进行语法分析时,编制的处理程序也采取递归的方式,可使其 4.4 递归下降分析程序构造 在程序语言的语法定义中有许多采用递归定义。我们在对 它进行语法分析时,编制的处理程序也采取递归的方式,可使其 结构简单易读。但由于频繁地调用子程序大大地降低了分析速度。 一、递归下降法的主要思想是:对每个非终结符按其产生式 结构写出相应语法分析子程序。因为文法递归相应子程序也 递归,子程序的结构与产生式结构一致。所以称此种方法 称为递归子程序法或递归下降法。 二、用程序表示递归子程序的内部结构: 设A是一个非终结符:A→β1 A→β2 ┊ A→βn

A→β1 A→β2 ┊ A→βn 则写 ζ(A)  if char∈first(β1 ) thenζ(β1 ) else if char∈first(β2 ) then ζ(β2 ) else… if char∈first(βn ) then ζ(βn) else ERROR 其中ζ(βi)表示调用处理符号串βi的子程序。 A→β1 A→β2 ┊ A→βn 对A的任一右部i 设为: βi = y1 y2 … yn 则定义ζ( βi)  beginζ(y1);ζ(y2);…;ζ(yn) end 其中yj可分为下列两种情况(j=1,…,n): 1) yj∈VT,则 ζ( yj)  if char≠ yj then ERROR else READ(char) 2) yj∈VN,则ζ(yj)表示调用关于yj的递归子程序。 对文法加限制: 1。任一非终结符B都不是左递归的,否则会产生死循环。 2。对A的任意两个右部βi , βj ,有:first(βi)∩first(βj)=φ First(βi)表示βi所能导出串的第一个符号的集合。显然,每个 βi的first(βi)是互不相同的,否则则无法判断应执行哪个ζ(βi )。

例1. 设有文法G: A →aABa B→bBb | a 则有ζ(A)  if char=a then ζ(aABa) else ERROR  if char=a then beginζ(a);ζ(A);ζ(B);ζ(a) end else ERROR begin if chara then ERROR else READ(char); ζ(A); ζ(B); if chara then ERROR else READ(char) end

B→bBb | a ζ(B)  if char = b then ζ(bBb) else if char=a then (a) else ERROR  if char =b then begin ζ(b); ζ(B); ζ(b) end else if char=a then(a) else ERROR  if char=b then begin if charb then ERROR else READ(char); ζ(B); if charb then ERROR else READ(char) end else if char=a then if char a then ERROR else READ(char) else ERROR

例2: 关于〈表达式〉的处理: 即:E→T | E +T <表达式>∷=<项>| <表达式>+<项> <项>∷=<因子>| <项>*<因子> <因子>∷=<变量>| (<表达式>) <变量>∷= i | i(<表达式>) 即:E→T | E +T T→F | T *F F→P | (E) P →i | i (E) 为了处理方便,把上述文法变为: E→T{+T} T→F{*F} F→P| (E) P→i| i(E) E: procedure E; begin T; while char="+" do begin READ(char); T end end

E: procedure E; begin T; while char="+" do begin READ(char); T end end E→T{+T} T→F{*F} F→P| (E) P→ i| i(E) T: procedure T; begin T; while char = "*" do begin READ(char); F end end F: procedure F; begin if char ="(" then begin READ(char); E; if ≠ char ")" then ERROR else READ(char) end else P

begin if char ≠" i " then ERROR else begin READ(char); E→T{+T} T→F{*F} F→P| (E) P→ i| i(E) P: procedure P begin if char ≠" i " then ERROR else begin READ(char); if char ="(" then begin READ(char); E; if char≠ ")" then ERROR else READ(char) end 有时间则作递归下降分析的演示

4.5 预测分析程序 LL(k)文法是采取确定的自左至右扫描(输入串)和自顶向下分析技术的最大一类文法。LL系指:自左向右扫描(输入串),自上而下进行最左推导。 一般来说,一个文法当其分析器对输入串进行自左至右扫描并采用自顶向下方法进行分析的过程中,如果每步仅利用当前的非终结符(事实上此时它已位于分析栈顶)和至多向前查看k个输入符号就能唯一 决定采取什么动作,那么这个文法称为LL(K)文法。 对于大多数程序设计语言而言。K=1就足够了。因此我们将主要讨论k=1的情形。

一、LL(1)方法的分析过程 设分析的当前格局为(x1x2 …. xn#, y1y2 …. ym#) 其中xi表示句型的前端部分,诸yj表示输入流的后端部分(终结符串)。则可能有下述动作之一: 1.替代:当x1∈VN时,则选相应的候选式去替换x1 。 2.匹配:当x1∈VT时,它与y1进行匹配,其结果为两种可能,如 果匹配成功,则去掉x1和y1(即指针后移一位)否则报错。 3.接受:当格局为(#, #)时,报告分析成功结束。 从实现的角度来说,上述替换过程需要花较多的时间,因为 它除了把一个候选式替换掉x1,还需要x2 … xn统统进行移位处理, 这时很麻烦的。我们的处理方法是用栈来保存x1x2 … xn,而且 是把xn作为栈底, x1作为栈顶,那么上述的替换动作就简单了, 只需在栈顶进行替换。即去掉x1把候选式的符号串按逆序方式 压入栈中即可。

例: 设有文法:S→aBc|bB B→bB|d 且给定输入串abbbdc,看其自顶向下的分析过程。 Bc# bbdc# ↑ 栈: 流: S# bBc# bbbdc# ↑  替  匹  替  匹 bBc# bbdc# ↑ Bc# bdc# ↑ bBc# bdc# ↑  替  匹  替 Bc# dc# ↑ dc# ↑  匹  替 c# ↑ # ↑  匹  匹 接受 结束

分析矩阵的元素M[A,a]中的下标A为非终结符,a为终结符或句子结束标记"#",矩阵元素M[A,a]的内容为一条关于A的产生式。 二、LL(1)方法的实现: LL(1)方法在实现时用到一个LL(1)分析矩阵和一个分析栈以及预测分析程序。 分析矩阵的元素M[A,a]中的下标A为非终结符,a为终结符或句子结束标记"#",矩阵元素M[A,a]的内容为一条关于A的产生式。 它表明当用非终结符A向下推导而当前输入符为a时,所应采用的候选式。当矩阵元素为空时,则表示用A往下推导时遇到了不应该出现的符号,即A与a不能匹配。因此应该转向出错处理。 预测分析程序见下图:

流程图: 开始 "# " "S" 进栈,读输入流一符号 a 栈顶元素出栈并送X 对产生式右部 x1 x2…xn按逆序即xnxn-1…x1 压入栈中 y y X∈VT? X=a? 读入符号 a N y N N M[A,a]为产生式? N X="# "? 出错处理 N y N X=a? 出错处理 此时输入流也到尾部。 y 结束

例:现以表达式文法为例构造预测分析表。 G[E]: E→E+T | T T→T*F | F F→i |(E) SELECT(E→TE')={(,i} SELECT(E'→+TE')={+} SELECT(E'→ε}={ε,),#} SELECT(T→FT')={(, i } SELECT(T'→*FT')={*} SELECT(T'→ε)={ε,+,),#} SELECT(F→i)={i} SELECT(F→(E))={(} 可知具有相同左部的产生式的SELECT集合互不相交,所以该 文法是LL(1)文法。 解:(1)判断G[E]是否为LL(1)文法,因文法中含有左递归,故必须先消去左递归,使文法 变为: E→TE' E'→+TE'|ε T→FT' T'→*FT'|ε F→i|(E) 求三种集合(前面已举例, 图略)最后得到: 有时间则作预测分析的演示

(2)构造预测分析表 对每个终结符或"#"号用a表示,则若a∈SELECT(A→α)。 令M[A,a]=A→α(一般为了简化,取M[A,a]=α) 把所有无定义的M[A,a]标上ERROR(一般在表中用空白表示)。 上例的分析表为: ( E ) i F ε * FT' T' FT' T +TE' E' TE' E # ) ( * + SELECT(E→TE')={(,i} SELECT(E'→+TE')={+} SELECT(E'→ε}={ε,),#} SELECT(T→FT')={(, i} SELECT(T'→*FT')={*} SELECT(T'→ε)={ε,+,),#} SELECT(F→i)={i} SELECT(F→(E))={(}

下面采用预测分析法对输入串i+i*i#进行分析。 ( E ) i F ε * FT' T' FT' T +TE' E' TE' E # ) ( * + 步骤 分析栈 输入队列 动作 所用产生式 1 #E i+i*i# 替代 E→TE' #E'T i+i*i# 替代 T→FT' #E'T'F i+i*i# 替代 F→i #E'T'i i+i*i# 匹配 #E'T' +i*i# 替代 T'→ε #E' +i*i# 替代 E'→+TE'

步骤 分析栈 输入队列 动作 所用产生式 7 #E'T+ +i*i# 匹配 8 #E'T i*i# 替代 T→FT' 9 #E'T'F i*i# 替代 F→i 10 #E'T'i i*i# 匹配 11 #E'T' *i# 替代 T'→FT' 12 #E'T'F* i# 匹配 13 #E'T'F i# 替代 F→i 14 #E'T'i i# 匹配 #E'T' # 替代 T'→ε 16 #E' # 替代 E'→ε 17 # # 接受

作业:1,3