簡體   English   中英

LL(1)解析器中FIRST和FOLLOW的目的是什么?

[英]Purpose of FIRST and FOLLOW sets in LL(1) parsers?

任何人都可以向我解釋如何在LL(1)語法中使用FIRST和FOLLOW? 我知道它們用於語法表構造,但我不明白如何。

在LL(1)解析器中,解析器通過維護最初接種到起始符號的工作空間,然后是字符串結束標記(通常表示為$)來工作。 在每個步驟中,它執行以下操作之一:

  • 如果工作空間的第一個符號是終端,則它將它與下一個輸入標記匹配 (或者如果它不匹配則報告錯誤。)
  • 如果工作空間的第一個符號是非終結符號,它會預測用非終結符號替換哪個生成。

預測步驟是FIRST和FOLLOW出現的地方。 解析器需要能夠完全基於當前的非終結符和輸入的下一個標記來猜測要使用的生產。 問題是如何做到這一點。

假設當前的非終結符號為A,輸入的下一個標記為t。 如果你知道A的制作,你會選擇哪一個? 有一個簡單的例子要考慮:如果有一個形式A→tω的產生,其中ω是一些任意的字符串,那么你應該選擇那個產量,因為你看作輸入的t將匹配前面的t生產。

還有一些復雜的案例需要考慮。 假設你有A→Bω形式的產生,其中B是非終結符,ω是某個字符串。 在什么情況下你想猜這個產品? 好吧,如果你知道下一個終端符號是,你不會想要猜測這個產生,除非你知道B可以擴展到以終端t開頭的字符串(還有另一個我們將要討論的情況)第二)。 這是FIRST集合的用武之地。在沒有ε產生的語法中,某些非終結符號的集合FIRST(X)是可能出現在從X派生的某個字符串的開頭的所有終端的集合。如果你有形式A→Bω,你看到非終結t,你猜想在t∈FIRST(B)時精確地使用該生產; 也就是說,B可以導出一些以t開頭的字符串。 如果B沒有從t開始得到任何東西,那么就沒有理由選擇它,如果B確實得到以t開頭的東西,你想做出這個選擇,這樣你最終可以匹配它。

當ε產品推出時,事情變得有點棘手。 現在,讓我們假設你有一個形式A→BCω,其中B和C是非終結符,ω是一個字符串。 我們還假設輸入的下一個標記是t。 如果t∈FIRST(B),那么我們就選擇這種生產,如上所述。 但是,如果t∉FIRST(B)會發生什么? 如果語法中有ε產生,如果B可以導出ε和t∈FIRST(C),我們可能仍然想要選擇這個產生。 為什么是這樣? 如果發生這種情況,則意味着我們可能通過產生BCω來匹配t,然后從B產生ε,留下Cω與t匹配。 這是我們可能必須“瀏覽”非終結者的一個背景。 幸運的是,這是由FIRST集處理的。 如果非終結X可以產生ε,那么ε∈FIRST(X)。 因此,我們可以使用FIRST集來檢查我們是否需要通過查看ε∈FIRST(X)來“查看”非終結符。

到目前為止,我們還沒有談到FOLLOW集。 他們來自哪里? 好吧,假設我們正在處理非終結符號A,我們看到終端t,但是A的生成都沒有實際消耗t。 那我們做什么? 事實證明,仍有一種方法可以讓我們吃掉它。 請記住LL(1)解析器通過維護帶有字符串的工作空間來工作。 我們所看到的可能根本不應該與當前的非終結符號A匹配,而是我們應該有A產生ε然后讓工作區中的一些后來的非終結符合t。 這是FOLLOW集合的來源。非終結符號的FOLLOW集合,表示為FOLLOW(X),是在某些派生中可以緊接在X之后出現的所有終端符號的集合。 當選擇為A選擇哪個生產時,我們添加一個最終規則 - 如果終端符號t在A的FOLLOW集合中,我們選擇一些最終將產生ε的生產。 這樣,A將“消失”,我們可以將t與A非終結后出現的某些角色進行匹配。

這不是對LL(1)解析的完整介紹,但我希望它能幫助您了解我們為什么需要FIRST和FOLLOW集合。 有關更多信息,請閱讀一本關於解析的書(我推薦Parsing Techniques: Grune和Jacobs的實用指南 )或參加編譯器課程。 作為一個完全無恥的插件,我在2012-2013夏季教授編譯器課程, 所有的演講幻燈片都可在線獲取

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM