简介
Parsing方法分类:
Universal: Cocke-Younger-Kasami Algorithm and Earley‘s Algorithm.
Top-down: LL(k).
Bottom-up: LR(k).
错误恢复模式:
Panic-Mode Recovery:
Phrase-Level Recovery:
Error Production:
Global Correction:
上下文无关文法:
终结符(terminal):组成串的基本符号。
非终结符(nonterminal):表示串的集合的语法变量,给出了语法分析和翻译的关键。
开始符号(start symbol):在一个文法中,一个nonterminal被指定为开始符号。
产生式(production):一条语法产生式,包含一个head/left side,转换符号->/::=,和body/right side。
推导过程:
最左推导(leftmost derivation):总选择每个句型的最左非终结符号展开。
最右推导(rightmost derivation):总选择每个句型的最右非终结符号展开,有时也被称为规范推导(canonical derivation)。
算法1:消除左递归
消除立即左递归:
对于 A -> Aα1 | Aα2 | ... | Aαm | β1 | β2 | ... | βn,将这些A产生式替换为:
A -> β1A‘ | β2A‘ | ... | βnA‘
A‘ -> α1A‘ | α2A‘ | ... | αmA‘ | ε
消除循环左递归:
输入:没有环(A->A)或ε(A->ε)产生式的文法G。
输出:一个等价的无左递归文法G‘,但G‘可能具有ε产生式。
方法:
消除循环左递归算法: 按照某个顺序将非终结符号排列为 A1, A2, ..., An. for i = (1 to n) { for j = (1 to i-1) { 将每个形如 Ai -> Ajγ 的产生式替换为产生式组 Ai -> δ1γ | δ2γ | ... | δ3γ, 其中 Aj -> δ1 | δ2 | ... | δk 是所有的 Aj 产生式; } 消除 Ai 产生式之间的立即左递归; }
算法2:提取左因子
目的:推迟产生式选择。
输入:语法规则G。
输出:等价的提取左因子语法G‘。
方法:对于每个非终结符A,找出最长的公共前缀 α != ε。对于所有 A -> αβ1 | αβ1 | ... | αβn | γ,替换为:
A -> αA‘ | γ
A‘ -> β1 | β1 | ... | βn
重复这样的行为直到没有同一个非终止符的两个产生式含有公共前缀。
Top-Down Recursive-Descent Parsing
递归下降parser典型过程:void A() { Choose an A-production, A ::= X1X2...Xk; for i = (i to k) { if (Xi is a nonterminal) call procedure Xi(); else if (Xi equals the current input symbol a) advance the input to the next symbol; else call error recovery procedure; } }
FIRST和FOLLOW集
FIRST(α):α是任意一个语法符号,该集合是由α推导出来的句子的第一个终止符的集合。
计算时,不断应用下列规则,直至没有新的终结符号或ε可以被加入到任何FIRST集为止:
1) 如果X是一个终止符,则FIRST(X) = {X}。
2) 如果X是一个非终止符,且存在产生式 X ::= Y1Y2...Yk (k ≥ 1)。如果FIRST(Yi)包含a,并且FIRST(Y1), ... FIRST(Yi-1)都可以推导出ε,那就把a加入到FIRST(X)中。如果所有FIRST(Yi)都包含ε,那就把ε加入FIRST(X)中。
3) 如果存在 X ::= ε,那就把ε加入FIRST(X)中。
FOLLOW(A):A是一个非终止符,该集合是可以紧跟在A的句型右边的终止符的集合。
计算时,不断应用下列规则,直至没有新的终结符号被加入到任何FOLLOW集为止:
1) 如果S是开始符号,则把$添加至FOLLOW(S)中,$是输入串结束标记。
2) 如果存在产生式 A ::= αBβ,那么FIRST(β)中除了ε之外所有符号都在FOLLOW(B)中。
3) 如果存在产生式 A ::= αB,或存在产生式 A ::= αBβ 且 FIRST(β) 包含ε,那么FOLLOW(B)包含FOLLOW(A)中所有符号。