程序设计语言 编译原理 陈火旺 (第三版) 期中考试 复习笔记 第4章 语法分析—自上而下分析

语法分析器

  • 语法分析的任务:对任⼀给定 w ∈ VT*,判断 w ∈ L(G)?
  • 语法分析器:按照产生式规则,做识别w的工作

语法分析方法

  • 自上(顶)而下分析
    • LL(1)分析法
    • 递归下降分析法
    • 预测分析法
  • 自下(底)而上分析
    • 算符优先分析法
    • LR分析法

自上而下分析

  • 从文法的开始符号出发,向下推导,推出句子
  • 对任何的输入串(单词符号),试图用⼀切可能的办法, 从文法的开始符号出发,自上而下地为输入串建立⼀棵语法树,即为输入串寻找⼀个最左推导

LL(1)分析法

  • 从左(Left)到右扫描输入串;构造最左(Leftmost)推导;分析时每步向前看⼀个(1)字符。
  • 目的:构造不带回溯的自上而下分析算法
    • 左递归的消除
    • 消除回溯,提左因子
    • FIRST集合,FOLLOW集合
    • LL(1)分析条件
    • LL(1)分析方法

左递归文法

  • ⼀个文法含有下列形式的产生式时,
    a)直接递归
    A->A β \beta β A ∈ \in VN, β \beta β ∈ \in V*
    b)间接递归
    A->B β \beta β
    B->Aa A,B ∈ \in VN, a,b ∈ \in V*
    称为左递归文法。
  • 如果⼀个文法是左递归时,则不能采用自顶向下分析法。
  • 例1. 文法S -> Sa, S -> b 是直接左递归
    语言是:L={ ban | n≥0}
  • 例2. 文法 A -> aB, A->Bb, B->Ac, B->d 是间接左递归

消除直接左递归

  • P -> Pα│β(α≠ε,β不以P开头)
    ↓ \downarrow
    P -> βP’
    P’ -> αP’ │ε
  • 例. 文法
    E→E+T│T
    T→T*F│F
    F→(E)│i
    ↓ \downarrow
    E→TE’
    E’ → +TE’ │ε
    T→FT’
    T’ → *FT’ │ε
    F→(E)│i
  • 有很多个 α \alpha α β \beta β
    ⼀般地, 假定P关于的产生式是
    P→Pα1│Pα2 │… │Pαm │β1 │β2 │… │βn
    其中:αi≠ε,βi不以P开头,则改写为:
    P→ β1 P’ │β2 P’ │…│βn P’
    P’ →α1 P’ │ α2 P’ │… │αm P’ │ε

消除左递归算法

(1)排序 (2)改写并消除左递归 (3)化简删除永不使用的产生式

  • 例1.文法G(S) R→Sa|a, Q→Rb|b, S →Qc|c
    有推导:S ⇒ Qc ⇒ Rbc ⇒ Sabc, 存在左递归。
    • 按R(1)、Q(2)、S(3)排序
    • 执行算法
      按照排序顺序带入
      Q->Sab|ab|b
      S->Sabc|abc|bc|c
      消除左递归
      α \alpha α=abc, β \beta β=abc|bc|c
      S->abcS’|bcS’|cS’
      S’->abcS’| ϵ \epsilon ϵ
    • 消除无用产生式
    • 结果:
      S->abcS’|bcS’|cS’
      S’->abcS’| ϵ \epsilon ϵ
  • 例2. 消去下面文法的左递归
    T → T,S|S
    S → a|+|(T)
    • 过程: α \alpha α=,S, β \beta β=S
      T->ST’,T’->,ST’| ϵ \epsilon ϵ
    • 结果:
      T->ST’
      T’->,ST’| ϵ \epsilon ϵ
      S->a|+|(T)

回溯解决方法

提取公共左因⼦,将文法改造成任何非终结符的所有候选首符集两两不相交。

  • 例1. 文法G:S→aSb|aS|ε
    • 解:提取: S →aS(b|ε)
      S→ε
    • 引入新符: S →aSA
      A→ b|ε
      S→ε
  • 例2. 文法G:S→abc|abd|ae
    • 解:提取: S →a(bc|bd|e)
    • 引入新符: S →aA
      A→ bc|bd|e
    • 引入新符:B->c|d
    • 结果:
      S->aA
      A->bB|e
      B->c|d

FIRST(X)

  • 终结符是终结符
  • 非终结符
    • 推出空字,空字
    • 推出非终结符,FIRST(非终结符)
  • 例1.
    G: E → TE’
    E’→ +TE’ │ε
    T →FT’
    T’ → *FT’ │ε
    F →(E)│i
    求每个非终结符号的FIRST集合
    解:FIRST (E) = FIRST (T)= FIRST (F)= { (, i }
    FIRST (E’ ) = { +, ε }
    FIRST (T’ ) = { *, ε}
  • 例2.
文法规则FIRST(X)
E → E A T | T{(,n}
A → + | -{+,-}
T → T M F | F{(,n}
M → *{*}
F → (E) | n{(,n}

FOLLOW(X)

对于文法G的每个非终结符,构造FOLLOW(A)的方法是:
(1)若A为文法开始符号,置#于FOLLOW(A)中
(2)若有产生式B→αAβ,则将FIRST(β) - {ε}加到FOLLOW (A)中;
(解释:忽略空字)
(3)若有B→αA或B →αAβ, 且β =*=> ε,则将FOLLOW(B)加到FOLLOW(A)中;
(解释:右侧非终结符后面没有字符或能推出空字,加左侧非终结符的FOLLOW到后继符集。特别注意:如果遇到 B-> α \alpha αAC 这种,而C能推出空字,则加入FOLLOW(B);如果遇到 B-> α \alpha αAC | ϵ \epsilon ϵ 这种,C推不出空字,但因为后面有空字,所以既加入FIRST( C )又加入FOLLOW(B)!
(4)反复使用以上规则, 直至 FOLLOW(A)不再增大为止。

  • 例1.
    G: E → TE’
    E’ → +TE’ │ε
    T →FT’
    T’ → *FT’ │ε
    F →(E)│i
    求每个非终结符号的FOLLOW集合
    FOLLOW(E)={),#} 起始符加#!
    FOLLOW(E’)={),#}
    FOLLOW(T)={+,),#}
    FOLLOW(T’)={+,),#}
    FOLLOW(F)={*,+,),#}
  • 例2.
文法规则FOLLOW(X)
E → E A T | T{),+,-,#}
A → + | -{(,n}
T → T M F | F{*,),+,-,#}
M → *{(,n}
F → (E) | n{*,),+,-,#}

LL(1)文法

  • LL(1)文法需要满足的条件是?
    1. 文法每一个非终结符A的任何两个不同产生式 A -> α| β,有FIRST(α)∩ FIRST(β) = Φ
    2. 文法不含左递归
    3. 文法每一个非终结符A,若A=*=>ε则 FIRST(A)∩ FOLLOW(A) =Φ
  • LL(1)分析方法
    • 对⼀个LL(1)文法,可以对某个输入串进行有效的无回溯的自上而下分析。
    • 设面临的输入符号为a,要用非终结符A进行匹配,且A→α1│α2│… │αn,则可如下分析:
      1. 若a∈FIRST (αi) ,则指派αi执行匹配任务;
      2. 否则
        1. 若ε∈FIRST(A),且a∈FOLLOW (A),则让A与ε自动匹配;
        2. 否则,a的出现是⼀种语法错误。

递归下降分析程序

  • 程序形式
    (1)对每⼀个非终结符A,编写⼀个相应的子程序P(A);
    (2)对于规则A→α1│α2│…│αn 相应的子程序P(A)构造如下:
 IF ch IN FIRST(α1) THEN P(α1) 
ELSE IF ch IN FIRST(α2) THEN P(α2) 
ELSE ……
ELSE IF ch IN FIRST(αn) THEN P(αn)
ELSE IF (ε∈FIRST(A) )AND (ch IN FOLLOW(A) )
THEN RETURN 
ELSE ERROR

例. E→TE’; E’→+TE’ | ϵ \epsilon ϵ ; T→FT’ ; T’ →*FT’ | ϵ \epsilon ϵ ; F→(E)|i
能推出空字的算一下FOLLOW
FOLLOW(E’)={),#}
FOLLOW(T’)={+,),#}
对于E→TE’

P(E)
BEGIN
	P(T);P(E');
END;

对于E’→+TE’ | ϵ \epsilon ϵ

P(E');
IF ch="+" THEN
BEGIN
	read(ch);P(T);P(E');
END;
ELSE IF (ch=") OR ch="#") THEN
	return;
ELSE ERROR;

对于F→(E)|i

P(F);
IF ch="i" THEN read(ch);
ELSE IF ch="(" THEN
BEGIN
	read(ch);P(E);
	IF ch=")" THEN read(ch);
	ELSE ERROR;
END;
ELSE ERROR;

LL(1)分析表

  • 若文法有m个非终结符n个终结符,则LL(1)分析表是⼀个(m+1)*(n+2)的矩阵M
    • 行标题为文法非终结符
    • 列标题为终结符号和输入结束符#
    • M[A, a]为⼀条关于A的产生式,指出当A面临a时,应使用的产生式或空格(出错标志)
  • 例.
    E→TE’; E’→+TE’ | ϵ \epsilon ϵ ; T→FT’ ; T’ →*FT’ | ϵ \epsilon ϵ ;F→(E)|i
    首先计算FIRST和FOLLOW
FIRSTFOLLOW
E{(,i}{#,)}
E’{+, ϵ \epsilon ϵ}{#,)}
T{(,i}{+,#,)}
T’{*, ϵ \epsilon ϵ}{+,#,)}
F{(,i}{*, ϵ \epsilon ϵ}
i+*()#
EE→TE’E→TE’
E’E’→+TE’E’→ϵE’→ϵ
TT→FT’T→FT’
T’T’→ϵT’ →*FT’T’→ϵT’→ϵ
FF→iF→(E)

  • 栈 STACK存放分析过程中的⽂法符号
    • 分析开始时栈底先放⼀个“#”,再压入文法开始符;当分析栈中仅剩“#”且输入串指针指向串尾的“#”时,分析成功。
  • 例:
    E→TE’; E’→+TE’ | e ;
    T→FT’ ; T’ →*FT’ |e ;
    F→(E)|i
    匹配符号串i + i * i #
    栈:
    栈
  • 结论
    • 输出的产生式就是最左推导的产生式。栈中存放产生式右部,等待与a匹配;
    • 当栈顶X=a时,分析表指出如何扩充语法树,出错能马上发现。
    • 实质:
      • 栈:部分句型,句型右部,还未得到推导的符号。
      • 表:指出VN按哪⼀条扩充,依赖于VT

分析表构造算法

(1)对每个产生式 A→α,执行(2) 和(3)
(2)若 a∈FIRST(α), 置M[ A, a] =A→α
(3)若ε∈FIRST(A),对b∈FOLLOW(A) 置M[A, b] =A→ε
(4)其余置 M[A, a] =ERROR

=>To be continued…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
编译原理期末考试主要涵盖了编译原理课程所学的知识点和理论基础,以及相关的实践能力。在考试中,通常会包含选择题、填空题、简答题和编程题等不同类型的题目。 选择题考察学生对编译原理相关概念的理解和掌握程度,例如词法分析语法分析、语义分析、中间代码生成、代码优化和目标代码生成等方面的知识。 填空题要求学生填写编译过程中的关键参数、关键步骤或关键算法的具体数值或表达式,考察学生对具体细节的掌握情况。 简答题会提出一些编译原理的基本问题,要求学生用自己的语言进行解释和回答,主要考察学生对编译原理的原理和概念的理解和应用能力。 编程题是考察学生对编译原理知识的实际应用能力,通常要求学生编写一个简单的编译器或解释器的某个功能模块,完成对源代码的词法分析语法分析、语义分析等操作。 在备考阶段,需要重点复习编译原理的基本概念、算法和原理,练习做一些相关的习题和编程实践,熟悉不同类型的题目形式和解题思路。此外,深入理解编译原理的原理和实践,尝试设计和实现一个简单的编译器,也有助于加深对知识的理解和应用能力的提升。 总之,编译原理期末考试是对学生在编译原理课程上所学的理论和实践能力的检验,通过复习和实践的准备,能更好地应对考试的各个环节,取得好成绩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值