1. 程式人生 > >《編譯原理-龍書》練習第4章

《編譯原理-龍書》練習第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 | 01

1)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