《編譯原理-龍書》練習第4章
4.2 上下文無關文法
**4.2.7節中L={a^nb^n|n>=1}怎麼用文法表示? S -> aAb A -> ab|ε4.2.1
1) E -> EE*
-> EE+E*
-> aa+a*
左到右依次a
2) 與1)一樣,只是最後一步右到左依次a
3) E
E E *
E E +
id id id
4)無二義性,但是怎麼證明呢?
5)+*組成的字尾表示式
4.2.3 如果是正則表示式,可以採用4.2.7的方法轉成文法
1) (0*1+)* 根據DNF推出:
S -> 0A
S -> 1S
S -> ε
A -> 1S
2)
S -> ABA
A -> BB
B -> 0|1|ε
4.2.4
對於A->X[Y]Z,可以表示為
A->XBZ
B->Y|ε
對於A->X{YZ},可以表示為
A->XB
B->CC
C->YZ|ε
4.2.5 stmt -> if expr then stmt [ else stmt ] | begin stmt{; stmt} end
4.2.6 基本的正則表示式還剩*,表示為A->Z*,可以改寫為:
A->BB
B->Z|ε
4.2.7 1)
建立一個集合表示所有非“無用符號”集合T,開始置為所有終結符號
集合A表示所有推導式,預設不打標記
for(所有沒有打標記的A中推導式)
{
if( 如果右邊只有T中符號集合)
{
將這個表示式打標記
表示式左邊符號加入集合T
}
if(一個迴圈結束沒有新的表示式被打標記)
迴圈退出
}
將開始符號加入T
2)非“無用符號”集合T會依次加入{0, B, S},所以A是無用符號
4.2.8 讀懂這道題費了好大勁,不知到是因為最後一道題了還是比較晚了(2012-12-20 22:49,離世界末日不遠了)
1)前2行不變,後面改為:
option -> A1|A2|...|An
A1 -> a1|b1
...
An -> an|bn
2)又花了一段時間讀懂了這個題目,生成的串固定長度n,不考慮<n的串
n!*n的產生式是這樣的,1)中的第一行改為:
option->Aa1|Aa2...|Aan
其中a1有n種選擇(A1-An),a2有剩下的n-1種.....an為剩下的一種。
這些產生式一共包括n!個長度為n的產生式,即O(n!*n)
如果有一個O(n*2^n)的產生式序列,那麼可能是n個長度為2^n的產生式,具體構造方法沒想出來
4.3 設計文法
4.3.1 1)沒有左公因子
2)有左遞迴,不能自頂向下語法分析
3)
rexpr -> rterm | E1
E1 -> +rterm | ε
rterm -> rfactor | F1
F1 -> rfactor | ε
rfactor -> rprimary | P1
P1 -> * | ε
rprimary -> a|b
4)目前沒有左遞迴、左公因子,可以自頂向下語法分析
4.3.3 考慮 if E1 then if E2 else if E3 then MATCHED1 else MATCHED2
if E3 then MATCHED1 else MATCHED2不能確定跟前面兩個if中的哪個匹配
4.4 自頂向下的語法分析
4.4.1 1)S -> 0S1 | 01 S -> 0T T -> S1|1 FIRST(S) = {0} FIRST(T) = {0,1} FOLLOW(S) = {1,$} FOLLOW(T) = {1,$}0 | 1 | $ |
S | S->0T | |
T | T->S1 | T->1 |
4.4.2 S -> SS+ | SS* | a 提取左公因子 S -> SST|a T -> +|* 消除左遞迴
S -> aX
X -> STX |ε
T -> +|*
FIRST(S) = {a} FIRST(X) = {a} FOLLOW(S) = {+,*,$} FOLLOW(X) = {+,*,$} 提取左公因子a | + | * | $ | |
S | aX | |||
X | STX | ε | ε | ε |
T | + | * |
4.4.5 感覺可以識別aaaaaa,為啥不行呢?
aaaaaa aSa
aaaaa Sa
aaaaa aSaa 如果可以向前看4個輸入符號,則可以識別aaaaa,否則,會繼續採用S -> aSa
aaaa Saa aSaaa
aaa aSaaaa
aa Saaaa aSaaaaa
a Saaaaa 需要回溯,回溯到一定程度就可以識別
4.4.6 1)如果產生式左邊只能生成ε,則將其在文法中所有出現的地方刪除即可
否則,就是類似T -> X | ε,這種情況下,將T在其他推導中出現的地方用這兩個替換
這樣有可能粗先左遞迴或左公因子。
2)
S -> aSbS => S -> aaSbSbaSbS | abSaSbbSaS | aSbS
S -> bSaS => S -> baSbSaaSbS | bbSaSabSaS | bSaS
S -> ε
綜合得到S -> aaSbSbaSbS | abSaSbbSaS | aSbS | baSbSaaSbS | bbSaSabSaS | bSaS
4.4.7 1)如果有A=》B,則將B進行替換,替換為B可推導得到的表示式
2)E -> E+T | T T -> T*F | F F->(E) | id 進行替換如下:
T -> T*F | (E) | id
E -> E+T | T*F | (E) | id
3)一步推導得到的環可以直接刪除,如果是多步,不失一般性,假設為2步,由於文法中不存在ε,所以必然存在這樣的推導:
A->B B->A,我們可以愛用上面方法將B去掉,並去掉一步環。
4.4.8 根據4.4.7不難得到,但是得到的結果有左遞迴
4.4.9 如果n*n的表能夠構造成功直到j-i=n-1,說明串在這個語言中
4.5 自底向上的語法分析
4.5.1 S -> 0S1 | 011)000111 最右推導:S -> 0S1 -> 00S11 -> 000111
最中間的01
2)00S11 最右推導: S -> 0S1 ->00S11
中間的0S1
4.5.2 S -> SS+ |SS* | a
1)SS+A*+ SS+
2)SS+a*a+ SS+
3)aaa*a++ a
4.5.3
1)
$ 000111$
$0001 11$
$00S 11$
$00S1 1$
$0S 1$
$0S1 $
$S $
2)
aaa*a++
Saa*a++
SSa*a++
SSS*a++
SSa++
SSS++
SS+
S
4.6 LR語法分析技術介紹:簡單LR技術
4.6.1
1) 0,0S,00S....
2)
4.6.2 S -> SS+| SS* | a
採用圖4-33中演算法處理
(1) S`->S
(2) S -> SS+
(3) S -> SS*
(4) S -> a
0 | 1 0S | 2 0a | 3 1S | 4 3+ | 5 3* |
S`->.S S->.SS+ S->.SS* S->.a |
S`->S. S->S.S+ S->S.S* S->.a 1$ = accept |
S->a. |
S->SS.+ S->SS.* |
S->SS+. | S->SS*. |
採用演算法4.46
FOLLOW(S) = {+, *,a $} FOLLOW(+)={+, *, a} FOLLOW(*)={+, *, a} FOLLOW(a)={+, *, a}
a | + | * | $ | S |
0 | s2 | 1 | ||
1 | s2 | acc | 3 | |
2 | r4 | r4 | r4 | |
3 | s4 | s5 | ||
4 | r2 | r2 | r2 | |
5 | r3 | r3 | r3 |
沒有發現哪個ACTION既有歸約又有移入操作,應該是SLR文法
4.6.3
棧 | 符號 | 輸入 | 動作 |
0 | aa*a+$ | 移入 | |
02 | a | a*a+$ | 歸約S->a |
01 | S | a*a+$ | 移入 |
012 | Sa | *a+$ | 歸約S->a |
013 | SS | *a+$ | 移入 |
0135 | SS* | a+$ | 歸約S->SS* |
01 | S | a+$ | 移入 |
012 | Sa | +$ | 歸約S->a |
013 | SS | +$ | 移入 |
0134 | SS+ | $ | 歸約S->SS+ |
01 | S | $ | 接收 |
對於下面兩題
LL(1)文法特點:需要滿足4.4.3中的三個條件
SLR(1)文法特點:在輸入某個表示串以後,有移入/規約衝突或規約/規約衝突
LL文法是LR文法的一個真子集,而不是SLR的
4.6.5
S`->S
S -> AaAb | BbBa
A ->ε
B ->ε
構造LR(0)自動機
0
S`->.S
S->.AaAb
S->.BbBa
A->.ε
B->.ε
1 0S
S`->S
沒法繼續構造下去
4.6.6
FIRST(SA)與FIRST(A)都包含{a}。所以不是LL(1)的
4.6.7 1)
S -> Aibi n個
Ai -> ajAi n^2-n個
Ai -> aj n^2-n個
2)考慮其中某個i和j
index | 項集 |
貢獻數量 |
|
0 |
S`->.S S->.Aibi Ai->.ajAi Ai->.aj |
1 | S`->.S S->.A1b1 ... S->.Anbn A1->.a2A1... A1->.anA1... ... An->.a1An... An->.an-1An |
1 0->S |
S`->S. | 1 | S`->S. |
2 0->Ai |
S->Ai.bi | n | n個S->Ai.bi |
3 0->aj |
Ai->aj.Ai Ai->aj. Ai->.ajAi Ai->.aj |
n | 對於a1 A2->a1.A2... An->a1.An A2->.ajA2 A2->.aj ...an |
4 2->bi |
S->Aibi. | n | n個S->Aibi. |
5 3->Ai, 6Ai |
Ai->ajAi. | n*(n-1) | 對於a1 輸入A2...An |
6 3->aj,6->aj |
Ai->aj.Ai Ai->.ajAi Ai->.aj |
n*n | 對於a1 輸入a1,a3...an A2->aj.A2 A2->aj. |
這樣算下來是2n*n+2n+2
結果應該是2^n+n^2+n,看來我算錯了,求高手指點
如果勢2^n那說明狀態數量太多了,手工構造太困難了,做4.6練習過程感覺中間太容易出錯了(手動計算的情況)
4.6.8
4.6.9
index | 項集 | |
0 | S'->.S S->.AS S->.b A->.SA A->.a |
|
1 0->S |
S'->S. A->S.A A->.SA A->.a |
->$ accept |
2 0->A |
S->A.S S->.AS S->.b A->.SA A->.a |
|
3 0->a 1->a 2->a 5->a 7->a |
A->a. | |
4 0->b |
S->b. | |
5 1->S 5->S 7->S |
A->S.A A->.SA A->.a |
|
6 1->A 5->A 7->A |
A->SA. | |
7 2->S |
S->AS. A->S.A A->.SA A->.a |
|
8 2->A 8->A |
S->A.S S->.AS S->.b |
|
9 8->S |
A->AS. |
FIRST(A)、FIRST(S)、FOLLOW(A)、FOLLOW(S)都是{a,b},7可能有衝突,因為當前狀態輸入a的情況下,不能確定按S->AS.規約還是移入a。
4.7 更強大的LR語法分析器
學習編譯原理真是個痛並快樂的過程,網上說龍書翻譯的還行,個人感覺也是如此,只是學習的時候如果希望從頭讀一遍就理解是不可能的,通常要看3-4次才能理解,而且每次閱讀的時候都會有新的收穫。
學習4.7.5的時候怎麼都想不明白例4.64怎麼得出的自發向前看符號,再回頭看一遍4.7,並且手動構造下LR項集族,馬上明白了。
學習這一節最重要的是理解4.7.2開頭對於演算法4.53的解釋,明白了以後這一節基本也就沒問題了
為理解4.7.5中演算法執行過程,構造例4.6的規範LR項集族
index | 項集 | GOTO |
0 | S`->.S ,$ S->.L=R ,$ S->.R ,$ L->.*R ,= L->.id ,= R->L ,$ |
|
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
8 |
4.7.1 FIRST(S) = {a}
S'->S
S->SS+
S->SS*
S->a
構造LR項集族如下
index | 項集 | GOTO |
0 | S`->.S , $ S->.SS+ ,a S->.SS* ,a S->.a ,a |
|
1 0->S |
S'->S. ,$ S->S.S+ ,a/+ S->S.S* ,a/* S->.a ,a/+/* |
|
2 0->a |
S->a. ,a | |
3 1->S |
S->SS.+ ,a/+ S->SS.* ,a/* S->.A ,a/+/* |
|
4 1->a |
S->a. ,a/+/* | |
5 3->+ |
S->SS+. ,a/+ | |
6 3->* |
S->SS*. ,a/* |
LALR項集族只需要將上面2/4合併即可
4.7.3 演算法4.6.3前後看了至少5遍,稍微有了些理解
INIT | 1 | 2 | ||
0 | S'->.S | $ | $ | $ |
1 | S'->S. S->S.S+ S->S.S* |
a | a | a |
2 | S->a. | a | a | a |
3 | S->SS.+ S->SS.* |
a/+/* | a/+/* | |
4 | S->SS+. | a/+ | ||
5 | S->SS*. | a/* |
4.7.4/4.7.5 類似例4.58
index | 項集 | GOTO |
0 | S`->.S ,$ S->.L=R ,$ S->.R ,$ L->.*R ,= L->.id ,= R->L ,$ |
|
1 | ||
2 | ||
3 | ||
4 | ||
5 | ||
6 | ||
7 | ||
8 | ||
8 |