這個任務的目標就是把一個給定的文法變得“干凈”和“高效”,剔除所有無用的部分。根據幻燈片,無用的(多余的)規則分為兩大類:
- 不可達規則:規則的“頭”(左部非終結符)從起始符號出發根本走不到。就像地圖上一個孤立的島嶼,你永遠無法從大陸到達那里。
- 不活動規則:規則本身或其“身體”(右部)含有無法最終變成終結符串的“死胡同”符號。用了這條規則,你的推導就永遠無法結束。
解決這類問題的標準做法是分兩步走,順序很重要:
化簡文法的兩步法
第一步:消除“不活動”符號 (Eliminate Non-Terminating Symbols)
- 目標:找出所有不能推導出終結符串的非終結符,然后刪除所有包含它們的規則。
- 方法:我們反過來找,找出所有能推導出終結符串的“活動符號”。這是一個迭代的過程:
- 第1輪:找出所有能直接推導出終結符串的非終結符(例如
A → a
)。把它們加入“活動集”。 - 第2輪:找出所有能推導出由“終結符”和“活動集中的符號”組成的字符串的非終結符。把新找到的也加入“活動集”。
- 重復第2步,直到“活動集”不再增大。
- 最后,所有不在“活動集”中的非終結符都是“不活動符號”。
- 第1輪:找出所有能直接推導出終結符串的非終結符(例如
第二步:消除“不可達”符號 (Eliminate Unreachable Symbols)
- 目標:從起始符號
S
出發,找出所有能訪問到的符號,刪除所有訪問不到的。 - 方法:這就像一個圖的遍歷:
- 第1輪:將起始符號
S
加入“可達集”。 - 第2輪:查看“可達集”中所有符號的產生式,把它們右手邊出現的所有新的非終結符都加入“可達集”。
- 重復第2步,直到“可達集”不再增大。
- 最后,所有不在“可達集”中的非終結符都是“不可達符號”。
- 第1輪:將起始符號
解題步驟 walkthrough
讓我們用這個方法來解決你的例題:
原始文法 G[S]:
S -> ABC | CD
A -> Aa | a
B -> Bb
C -> Cc | c
D -> Dd | d
E -> Ee | E
第一步:消除不活動符號
我們要建立一個“活動符號”的集合。
-
第1輪:尋找能直接推導出終結符的規則。
A -> a
=>A
是活動的。C -> c
=>C
是活動的。D -> d
=>D
是活動的。- 當前活動集 = { A, C, D }
-
第2輪:尋找規則右部只包含終結符和活動集成員的。
S -> CD
: 右部的C
和D
都在活動集中。所以S
是活動的。A -> Aa
: 右部的A
在活動集中,a
是終結符。所以A
是活動的(這只是確認,沒有新增)。C -> Cc
: 右部的C
在活動集中,c
是終結符。確認C
。D -> Dd
: 右部的D
在活動集中,d
是終結符。確認D
。- 當前活動集 = { A, C, D, S }
-
第3輪:再次檢查,看看活動集是否能繼續擴大。
S -> ABC
:A
和C
在活動集中,但B
不在。所以這條路走不通。B -> Bb
: 右部的B
不在活動集中。走不通。E -> Ee | E
: 右部的E
不在活動集中。走不通。- 活動集沒有再增大了。
結論:
- 活動符號:
S
,A
,C
,D
- 不活動符號:
B
,E
操作:刪除所有與 B
和 E
相關的規則。
- 刪除
B -> Bb
- 刪除
E -> Ee | E
- 刪除
S -> ABC
(因為它包含了不活動符號B
)
化簡后的文法 (第一步結束):
S -> CD
A -> Aa | a
C -> Cc | c
D -> Dd | d
第二步:消除不可達符號
我們從起始符號 S
出發,建立一個“可達符號”的集合。
-
第1輪:起始符號
S
是可達的。- 當前可達集 = { S }
-
第2輪:查看
S
的規則。S -> CD
: 右部引入了新的非終?符C
和D
。- 當前可達集 = { S, C, D }
-
第3輪:查看新加入的
C
和D
的規則。C -> Cc | c
: 右部只包含C
,已經在可達集中。D -> Dd | d
: 右部只包含D
,已經在可達集中。- 可達集沒有再增大了。
結論:
- 可達符號:
S
,C
,D
- 不可達符號:
A
操作:刪除所有與 A
相關的規則。
- 刪除
A -> Aa | a
最終結果:壓縮后的文法
經過以上兩步,我們得到的最終文法是:
S -> CD
C -> Cc | c
D -> Dd | d
這就是這道題的完整解法和最終答案。這個兩步法是一個標準的、機械化的流程,只要按照步驟來,就一定能正確地化簡任何文法。