2011-02-18 50 views
1

我目前正在嘗試爲編程語言編寫一個(非常)小的解釋器/編譯器。我已經爲該語言設置了語法,現在我需要寫下該語言的語法。我打算使用LL(1)解析器,因爲經過一些研究後,它似乎是最容易使用的。寫入正確的LL(1)語法?

我是這個領域的新手,但是從我收集的內容來看,強烈推薦使用BNF或EBNF來形式化語法。但是,似乎並非所有語法都適合使用LL(1)解析器來實現。因此,我想知道以LL(1)形式編寫文法的正確(或推薦)方法是什麼。

謝謝你的幫助, 查理。

PS:我打算使用Haskell的Parsec庫編寫解析器。編輯:此外,根據SK邏輯,Parsec可以處理一個無限的前瞻(LL(k)?) - 但我想這個問題仍然代表了這種類型的語法。

+0

秒差距能夠無限先行的。出於表現以外的原因,您不需要限制LL(1)。 – 2011-02-18 14:00:19

+0

它不一定是LL(k),它可以是上下文相關的。所以,你唯一需要擔心的是避免左遞歸。 – 2011-02-18 14:09:35

回答

3

我不是這方面的專家,因爲我只用LR(0)解析器創建了一個類似的小項目。我會推薦的一般方法:

  1. 讓算法工作。通過這個,爲+, -, /, *等制定規則和派生,並確保解析器產生一個有效的抽象語法樹。測試並評估不同輸入中的樹,以確保它正確執行算術。 讓事情一步一個腳印。如果遇到任何衝突,請在繼續之前先解決它。

  2. 獲得像if-then-elsecase表達式一樣工作的simper構造。

  3. 更進一步依賴於您正在編寫語法的語言。

Definetly看看其他編程語言的語法作爲參考(可惜我沒在1分鐘內發現任何完整LL語法任何語言上網,但LR語法應作爲參考有用的太)。例如:

ANSI C grammar

Python grammar

,當然在維基百科關於LL的一些小例子文法Wikipedia LL Parser,你可能已經簽出。

我希望你能找到一些這方面的東西有用

2

同時有確定的算法,如果一個語法是LL(K)。解析器生成器實現它們。如果可能,還有將語法轉換爲LL(k)的啓發式。

但你並不需要限制你的簡單的語言來LL(1),因爲大多數現代解析器生成(JavaCCANTLRPyparsing,和其他人)可以處理LL(k)的任意k。

更重要的是,它很可能是語法,你考慮你的語言最佳要求2和4之間的k,因爲幾個常見的編程結構做。

1

所以第一關,你不一定要你的語法是LL(1)。它使得編寫解析器變得更簡單並且可能提供更好的性能,但這確實意味着你的語言可能最終比通常使用的語言更冗長(通常不是LL(1))。

如果沒關係,你的下一步是通過語法精神上步驟,想象可以在這一點上出現的所有可能性,並檢查他們是否可以通過他們的第一個標誌來區分。

有拇指的兩個主要規則來進行語法LL(1)

  1. 如果選擇題可以在給定的點出現,他們可以 開始同樣的道理,在前面講添加關鍵字你選擇了哪一個 。
  2. 如果你有一個可選的或重複的部分,使 確保它之後結束令牌,該令牌不能作爲可選/重複部分的第一個標記。在可能的地方生產的開始
  3. 避免選裝件。它使前兩步變得更容易。