2010-08-29 38 views
8

我正在使用新的編程語言,但是我一直對每個人都使用yaxx/lex來解析代碼這一事實感到困惑,但我不是。yacc/lex還是手工編碼?

我的編譯器(已經工作)在C++/STL中被手動編寫,我不能說它很複雜或花費太多時間。它既有某種詞法分析器也有解析器,但它們不是自動生成的。

早些時候,我用同樣的方式編寫了一個C編譯器(不是完整的spec) - 它能夠在1遍中編譯程序,所有這些反向引用都可以解析&預處理 - yacc/lex絕對不可能。

我只是不能說服自己放棄所有這些,並開始潛入yaxx/lex--這可能需要相當大的努力來實現,並可能會引入一些語法限制。

當沒有使用yacc/lex時,是否有我想念的東西?我做了一件壞事嗎?

回答

3

的Yacc是不靈活的,在某些方面:

  • 好的錯誤處理硬(基本上,它的算法只定義正確解析正確的字符串,否則,所有的賭注都關閉,這是原因之一該GCC移至手寫解析器)
  • 上下文依賴是很難表達,而用手寫的遞歸下降解析器可以將參數簡單地添加到功能

此外,我注意到該lex/yacc目標代碼是錯誤的比手寫遞歸下降解析器更大(源代碼往往是相反的方式)。

我還沒有使用ANTLR,所以我不能說這是否更好在這些點。

1

也許你錯過了ANTLR,這對於可以用遞歸下降解析策略定義的語言來說是很好的。

使用Yacc/Lex可能有一些優點,但它不是強制使用它們。使用Yacc/Lex也有一些缺點,但優點通常超過了缺點。尤其是,維護Yacc驅動的語法通常比手工編寫的語法更容易,並且您從Yacc提供的自動化中受益。

但是,從頭開始編寫自己的解析器並不是一件壞事。這可能會使未來難以維持,但也可能使它更容易。

6

使用任何類型的詞法分析器/分析器生成器的主要優點是,如果您的語言發展,它會給您更多的靈活性。在一個手工編碼的詞法分析器/解析器中(尤其是如果你在一次傳遞中混合了許多功能!),對語言的改變相當快,而使用解析器生成器進行更改,重新運行發電機,並繼續與您的生活。總是手工編寫所有內容肯定沒有固有的技術限制,但我認爲自動化無聊位的可演化性和可維護性是值得的!

+2

良好的模塊化設計(例如,詞法分析器和詞法分析器應該完全分離)可以減少這個問題。仍然重要。 – delnan 2010-08-29 11:23:40

3

使用生成器的另一個巨大優勢是它們保證能夠精確處理並且只處理您在語法中指定的語言。你不能說任何手寫代碼。 LR/LALR變體也保證是O(N),這也是你不能斷言的任何手工編碼,至少在構建證明時不需要很多努力。

我已經寫了兩個都住在一起,我再也不會手動編碼了。我只做了那個,因爲當時我沒有在平臺上使用yacc

+0

那麼,我不需要一個數學證明來知道我的代碼是快速的 - 通常很明顯它在O(N)或O(N * LogN)中的某處。 – BarsMonster 2010-08-29 02:23:05

+2

我沒有說'快'的任何內容。我在談論算法的複雜性,你需要一個證明。 – EJP 2010-08-29 02:57:46

+0

那麼,當我編寫代碼時,我總是知道它很複雜。如果工具爲我編寫代碼 - 那麼我肯定會需要一個證明。 – BarsMonster 2010-08-29 03:26:41

0

這當然取決於你的語言語法的複雜性。一個簡單的語法意味着有一個簡單的實現,你可以自己做。

看看也許是最糟糕的可能的例子:C++ :)(除了自然語言之外,是否有人知道另一種語言,這些語言更難以正確解析?)即使使用Antlr這樣的工具,也很難做對,儘管它是可以管理的。因此,在另一方面,即使很困難,似乎一些最好的C++解析器,例如GCC和LLVM也大都是手寫的。

如果您不需要太多的靈活性,並且您的語言不是太簡單,那麼您將通過使用Antlr確保一些工作/時間安全。

+0

我的語言的複雜性只比C++少一點。 – BarsMonster 2010-08-29 02:14:49

+1

經典的Fortran很難解析:DO10I = 12.43'「和DO循環」DO10I = 12,43'「的分配甚至不能準確地分解成單詞,直到你到達逗號vs句號。 (第一個涉及一個浮點變量'DO10I',第二個涉及一個整數變量'I'和一個標籤'10':'DO 10 I = 12,43')。這往往會讓它變得相當困難! – 2010-08-29 09:07:11

相關問題