Skip to content

Latest commit

 

History

History
181 lines (136 loc) · 6.8 KB

File metadata and controls

181 lines (136 loc) · 6.8 KB

1.语法分析程序的主要任务是什么?简述自顶向下语法分析的思想。

  • 语法分析程序(也称为解析器)的主要任务是将词法分析器生成的词法单元(tokens)序列,根据所定义的语言语法规则,构建出语法树或抽象语法树,并验证输入程序的语法是否正确。具体来说,语法分析程序需要完成以下几个关键任务:

    • 语法正确性检查:确保输入的程序符合语言的语法规则,识别并报告语法错误。
    • 结构分析:根据语法规则,将词法单元组织成具有层次结构的语法树,反映程序的语法结构。
    • 语法树构建:生成详细的语法树或抽象语法树,为后续的语义分析、优化和代码生成提供基础。
  • 自顶向下语法分析的思想 自顶向下语法分析是一种从语法规则的开始符号(根节点)出发,逐步推导并匹配输入符号串的解析方法。其基本思想包括以下几个方面:

    • 开始于根节点:解析过程从语法树的根节点,即文法的开始符号 递归展开:通过应用文法的产生式规则,将非终结符逐步替换为其右侧的符号(终结符或非终结符),以匹配输入的词法单元序列。

    • 预测选择:在有多个产生式可供选择时,利用预测分析(如预测表或先行符)来决定使用哪一条产生式,从而避免回溯,提高解析效率。

    • 递归下降:常见的自顶向下解析方法之一,通过为每个非终结符编写一个递归函数,实现对输入的逐步匹配和解析。

    • 错误检测与恢复:在解析过程中,当发现输入符号与预期不符时,能够及时检测到语法错误,并尝试进行适当的错误恢复,以继续解析后续部分。

  1. 对文法G[S] S → a | & | (T) T → T,S | S 给出(a, (a, a))和(((a,a), &, (a)),a)的最左推导。
  • S ⇒(T) ⇒(T,S) ⇒(a,S) ⇒(a,(T)) ⇒(a,(T,S)) ⇒(a,(a,S)) ⇒(a,(a,a)) ​
  • S ⇒(T) ⇒(T,S) ⇒((T),S) ⇒((T,S),S) ⇒(((T),S),S) ⇒(((T,S),S),S) ⇒(((a,S),S),S) ⇒(((a,ϵ),S),S) ⇒(((a,ϵ),(T)),S) ⇒(((a,ϵ),(a)),S) ⇒(((a,ϵ),(a)),a) ⇒(((a,&),(a)),a) ​
  1. 判断下面文法是否为LL(1)文法,并说明理由。 (1) S → A B | P Q x A → x y B → b c P → d P | ε Q → a Q | ε

(2) S → T P T → + P T | ε P → ( S ) | a

判断文法是否为 LL(1) 文法

要判断给定的文法是否为 LL(1) 文法,需要检查以下条件:

  1. 消除左递归:文法中不应存在直接或间接的左递归。
  2. 左因子化:对于每个非终结符,其不同产生式的 FIRST 集合应当互不相交。
  3. 处理 ε 产生式:如果某个非终结符可以推导出 ε(空串),则其 FIRST 集合与 FOLLOW 集合应当互不相交。

我们将逐一分析提供的两个文法是否满足上述条件。


文法 (1)

[ \begin{aligned} S &\rightarrow A B \mid P Q \ x \ A &\rightarrow x \ y \ B &\rightarrow b \ c \ P &\rightarrow d \ P \mid \epsilon \ Q &\rightarrow a \ Q \mid \epsilon \end{aligned} ]

步骤 1:检查左递归

  • 文法中不存在直接或间接的左递归。

步骤 2:计算 FIRST 集合

  • FIRST(A B)

    • ( A \rightarrow x \ y ),因此 FIRST(A) = { x }。
    • 因此,FIRST(A B) = { x }。
  • FIRST(P Q x)

    • ( P \rightarrow d \ P \mid \epsilon ),因此 FIRST(P) = { d, ε }。
    • ( Q \rightarrow a \ Q \mid \epsilon ),因此 FIRST(Q) = { a, ε }。
    • FIRST(P Q x) 需要考虑 ( P ) 和 ( Q ) 的所有可能组合:
      • 如果 ( P \rightarrow d \ P ),则 FIRST(P Q x) 包含 d
      • 如果 ( P \rightarrow \epsilon ) 且 ( Q \rightarrow a \ Q ),则包含 a
      • 如果 ( P \rightarrow \epsilon ) 且 ( Q \rightarrow \epsilon ),则包含 x
    • 因此,FIRST(P Q x) = { d, a, x }。

步骤 3:检查冲突

  • 对于非终结符 S,有两个产生式:
    • ( S \rightarrow A B ) 的 FIRST 集合为 { x }。
    • ( S \rightarrow P Q x ) 的 FIRST 集合为 { d, a, x }。
  • 这两个 FIRST 集合存在交集 { x }。

结论:

由于 S 的两个产生式在 FIRST 集合上有重叠(都包含 x),在遇到输入符号 x 时,解析器无法确定选择哪一个产生式。因此,文法 (1) 不是 LL(1) 文法


文法 (2)

[ \begin{aligned} S &\rightarrow T \ P \ T &\rightarrow + \ P \ T \mid \epsilon \ P &\rightarrow ( \ S \ ) \mid a \end{aligned} ]

步骤 1:检查左递归

  • 文法中不存在直接或间接的左递归。

步骤 2:计算 FIRST 和 FOLLOW 集合

  • FIRST 集合

    • FIRST(S):由 ( S \rightarrow T \ P ) 推导,依赖于 FIRST(T)
    • FIRST(T)
      • ( T \rightarrow + \ P \ T ),因此包含 +
      • ( T \rightarrow \epsilon ),因此也包含 ε
      • FIRST(T) = { +, ε }。
    • FIRST(T P)
      • 如果 ( T \rightarrow + \ P \ T ),则 FIRST(T P) 包含 +
      • 如果 ( T \rightarrow \epsilon ),则 FIRST(T P) = FIRST(P)
    • FIRST(P)
      • ( P \rightarrow ( \ S \ ) ),因此包含 (
      • ( P \rightarrow a ),因此包含 a
      • FIRST(P) = { (, a }。
    • 因此,FIRST(S) = { +, (, a }。
  • FOLLOW 集合

    • FOLLOW(S):由 ( P \rightarrow ( \ S \ ) ) 推导,FOLLOW(S) 包含 )
    • FOLLOW(T)
      • 由 ( S \rightarrow T \ P ),FOLLOW(T) = FIRST(P) = { (, a }。
    • FOLLOW(P)
      • 由 ( S \rightarrow T \ P ),FOLLOW(P) = FOLLOW(S) = { ) }。

步骤 3:检查冲突

  • 对于非终结符 T,有两个产生式:

    • ( T \rightarrow + \ P \ T ) 的 FIRST 集合为 { + }。
    • ( T \rightarrow \epsilon ),因此需要确保 FIRST(+ P T)FOLLOW(T) 没有交集。
    • FIRST(+ P T) = { + },FOLLOW(T) = { (, a }。
    • 交集为空集,满足 LL(1) 条件。
  • 对于非终结符 P,有两个产生式:

    • ( P \rightarrow ( \ S \ ) ) 的 FIRST 集合为 { ( }。
    • ( P \rightarrow a ) 的 FIRST 集合为 { a }。
    • 这两个 FIRST 集合互不相交,满足 LL(1) 条件。

结论:

所有非终结符的产生式在 FIRSTFOLLOW 集合上均满足 LL(1) 文法的要求。因此,文法 (2) 是 LL(1) 文法


总结

  1. 文法 (1) 不是 LL(1) 文法,因为非终结符 S 的两个产生式在 FIRST 集合上存在交集,导致解析时存在二义性。
  2. 文法 (2) 是 LL(1) 文法,因为所有非终结符的产生式在 FIRSTFOLLOW 集合上均满足 LL(1) 的要求,没有产生任何冲突。