Re: [問題] 如何學寫COMPILER? [純拋磚引玉]

看板Programming作者時間18年前 (2007/04/27 14:32), 編輯推噓2(200)
留言2則, 2人參與, 最新討論串27/38 (看更多)
※ 引述《tinlans.bbs@whshs.cs.nccu.edu.tw (汀)》之銘言: > 你好像已經忘記我更前面說「context-free LALR(1) parser」了: BNF is context-free only > 一個 grammer 能用 BNF 表示, > 並不會代表它的 parser 好寫, > 因為 BNF 可以隨你高興寫, > 但寫出來的 form 不見得適合 context-free LALR(1) parser 去 parse。 > 換句話說我只要隨便舉個 context-sensitve 的 BNF, > context-free LALR(1) parser 就 parse 不出來, > 這跟「不能用 machine 做 parse」是不一樣的意思。 > > 3GL 是 50 年代 programming 技術, template 從 lisp(196x), forth 就有 > > OO 語言的歷史比 C 還久, smalltalk(1969) 就有 dynamic typing > > yacc 遠比 template, OO 先進得多! > 只不過是去 parse 一個 .y file, > 然後照內訂的機制去產生 .c 和 .h, > 再擺上一堆 #line 進去輔助 debug 而已, > 可惜這堆 #line 也拯救不了它產生出來的 code 難 debug 的特性, > 相信你有用 debugger 跳進去看過的話應該就會有所感想。 如果所用的 yacc 可靠, 你也不該追進去看 只應該看人寫的部份的 C, 好的 debugger 是支援 yacc 的 spirit 是 boost 之中特別容易讓 compiler 掛點的東西之一, 光 boost 要編起來就很麻煩, 遇到 compile error 比 yacc 更頭大 只因為是 C++ 就一定好 debug? error message 的數量就可說明 > 比較晚寫出來並不代表它比較先進, > 名詞比較早出來並不代表它永遠比較落後, > 但是一樣東西從出來到現在都沒有改變, > 卻顯然是落後的一種證明。 > 何況 parser generator 跟 language 誰早誰晚, > 並不會代表早的一方比較先進, > 今天用 C++ 的 boost::spirit library 寫出的 parser, > 顯然就是比 yacc generator 出來的 parser 容易 debug, > 因為 boost::spirit 用的技術比較先進 (無關它是否較晚被做出來), 看起來跟 yacc 很像, 卻是 C++, 比較先進是說用 C++ 就先進? xxx = a|b; yyy = xxx|c; 因 C++ 語法限制所以還不能像 yacc 用 LR, spirit 是 LL only 從來沒有比 yacc 先進的說法 > 而 yacc 使用的技術卻一直停留在舊時代, > 如此而已。 > > C++ 只是把這些 196x-197x 的東西換個用辭, 大家基本上停留在 3GL > > 舊沒有不好, 像 assembly 還不是要學會, > 舊的東西本來就沒有不好, > 但是沒有隨著技術進步而更新實作內容就是不好 (白話就是不長進), > 工程上 legacy system 本來就是一個很沈重的負擔。 > assembly 永遠不是舊的東西, PPC, MIPS, x86 assembly 不夠舊? 為了 binary 相容一個指另集最少活 20 年 CPU 效能看法也一直在變, 古代 ram 少, cisc>>risc, risc 不划算 民初 ram 多, risc>>cisc, 工作站用 RISC 成王道 近代 cache 少, ram 慢, cisc >> risc, x86 幹掉 PPC,SPARC,MIPS 現代多核心 vliw>>cisc>>risc, 只是 compiler 難搞 何種 CPU instruction 叫先進? > 每當一個新的 CPU 被設計出來, > 新的 assembly language 也再次出現, > > 商用 compiler 也還是在用 4GL, 含 yacc > > 很多所謂的 "library" 是 4GL interpreter, 如 SQL > > 寫 compiler 用 4GL 很快很省事, bug 好不好抓跟程式架構有關, > 這跟我看到的情形差很多, > 商用的 compiler, > 如 ACE Cosy、MetaWare 的 C/C++ Compiler Tool Suite、Target 的 CHESS, > 還有 Altium TASKING 的 Viper, > 它們的 front-end 都不是 4GL 做出來的。 microchip c18, m$ visual c 都是 bsd yacc 只要在檔案中有很大的非人寫成的 table, 都是 code gen 產生的 不一定是 yacc, 但是通常 compiler/interpreter 走兩個極端: 1. 4GL, 最快速完成 2. 用 3GL 硬幹, 執行最快速, 如 turbo pascal, 大多 interpreter visual c 有 "grammar.y", c18 有 "yacc stack overflow" 在 compiler 執行檔找 yacc 的收獲會不少 > 照你上面講的, > 那還不是要去背 interface 跟 abstract 是什麼東西? > 還不是要背 interface 跟 abstract 還有啥都沒寫差在哪? > 事實上在 Java 也不是把 virtual 換成 interface, > 而是把 C++ 某種 abstract base class 的特例制訂成一個語言機制, > interface 在 C++ 就是只含有 pure virtual function, > 且沒有任何 data members 的 abstract base class, > 沒有 constructor、有一個 pure virtual destructor (Java 無 destructor); > 這只是把一個 C++ 沒有明確描述的東西用明確的語言機制去描述, > 但同時也是帶給 programmer 一個限制, > 我想你應該也注意到了, > interface 不能有 data members, > 但是 C++ 可以, > 這就是所謂的限制。 > C++ 跟 Java 的取向不同, > 賦予 programmers 自由和責任也大相逕庭, > 要互相比較是很困難的。 照這樣說, 那 yacc 跟 spirit 比 C++ 和 java 之間差更多 要互相比較是更困難囉, 為啥不能比較 C++ & java > 所以我要強掉的:「C + 一堆 tricks」 == 「C++ + 很少 tricks 」 > 就是這個原因。 C++ 的 template 不算 tricks 的話, 比 template 更簡單的 C 語法何來 tricks C 的語法能作的變化更簡單 > C++ 在 performance 上的問題沒你想的誇張, > 甚至是 memory 的佔用上; > 就算是使用純 OOP 撰寫程式也不會比 C 差到 10% 以上, > 擅長使用 template + OO 的人可以降到 1.5 - 3% 左右, template 為何會比 C 省 memory, 舉個例吧 C 一定可以做出和 C++ 產生的 machine code 一樣的東西, 最多就是 source 大點 obj C 的 dynamic typing 才是 C 一類 static typing 不能比的 > 而且 memory space 也不會因為使用 template 佔用太多; > 使用 template 來搭 OO 可以壓低繼承樹增加 performance, > 甚至是將 runtime 的 recursive call 改寫成一連串相異函式的 tail-call, > 懂得如何幫 template 瘦身的人更不會因為 template 而讓程式特別吃記憶體, > 這些都有書可以學。 > > C 連 calling convention 都標準化, 跨 compiler 的 linking 都可以, > > C++ 原來 function name encoding 還算有標準, 現在不同家的 obj file 無法互通 > 事實上 C 那個不是標準化, > 只是 x86 上有特別訂一套而已, > 你去別的 architectrue 上 try 也是死成一片, MIPS, ARM, PPC, FR 都有標準, 但 C++ 各家 compiler 差太多, 怎麼定 一個 pointer to class method 就有 n 種作法 > 因為 gcc3 用 bison 做的 parser 實在有夠爛, bison is a version of yacc, bison != yacc 一堆 compiler 用 byacc > 如果你真的熟悉 C++ 標準, > 你應該知道有很多東西在舊的 compiler 放很鬆, > 以 eMule 的 source code 來說最大的差異就是 typename 的檢查, > 如果 T<X>::type 的 T 是一個 class template, > type 是 T<X> 裡面的一個 typedef, > 根據 C++ 標準, > 你用 T<X>::type 宣告一個變數需要在前面冠上 typename, > 但許多舊的 compiler 自行放寬了這個限制, > 這個光 VC 6 (C++98 標準制訂前發售) -> VC 7.1 就會遇上了, > 大學時代我同學把我叫去幫他編, > 我就解過一次, > 其它軟體在 GCC 上也遇到過這個問題。 > > C 從來沒發生過舊 code 不能 compile, 或 obj file 不能 link > 是嗎? > 我國 BBS 的 source code 就慘遭以下大地震屠殺: > 我手上的環境是 GCC 4.3: > /usr/include/varargs.h:35:2: #error "Change your code to use <stdarg.h> instead." > 如果你說這只是 C standard 改了 library header 又沒什麼, > 那我把它改成 #include <stdarg.h> 好了 (其實這個例子什麼都不用 #include), > 結果又出現: > test2.c:3: error: ISO C requires a named argument before '...' > 很遺憾, > 這段純 C 程式碼在 15 - 20 年前可以正確無誤的通過編譯, > 連一個警告訊息都不會有, > 我從 K&R C 一路玩到 C99, > legacy code 會遇上什麼問題都遇過了, > 說 C 不會遇到 ARM -> C++98 -> C++03 -> C++0x 的問題, > 那是絕對不可能的。 > 知道 GCC 為什麼會有 -fstrict-aliasing 這個 option 嗎? > 因為 C standard 後來有放鬆一些 aliasing 的判定方式, > 讓 compiler 能做出更多的 optimization, > 以致於有些做過 pointer casting 的老舊 code (GCC 手冊的範例是 union), > 在 -O2 以上編譯出來的程式碼, > 在「執行期」發生了與過去完全不同的意外行為。 如果用了非標準的 pointer access, 是寫的人有問題 就如 ++i 的問題一樣 較少人使用 (...) 的 function, 這是個很少出現的問題, 也很好改 search/replace 舊的 binary 和新的還是能相容 C++ 的問題如 pointer to class method != fucntion pointer, callback 剛好是 function pointer 主要用途, 又常是 class method 造成很多 GUI 程式的 callback 大改, 又無法 binary 相容 include, export 等讓書上的 hello world 都要改, 程度上很不同 > 照標準寫哪怕換了 compiler 就會炸掉? > 更何況那種東西搭一堆 #ifdef 就好了, > 如果不是寫 linux kernel (cross-compiling), > 那還有 autoconf 可以搭上去用。 > 問題是很多人不懂標準, > 而且標準也會隨著時間修改, > linux kernel 算還好的, > 雖然沒有直接重寫成 C++, OS 不能用 C++ 寫, 因為會有 compiler/archiecture 相依性, object 的 memory allocation, method calling 不同 compiler 都做不一樣 dynamic linking 也完全沒定義, 這種東西不能寫 portable 的 OS kernel 古早的 OS 有用 PL/I 等高階語言寫, 都不好 port, 才會弄出萬用的 C > 但是至少 code 跟 implementation 有在改進, > 所以我一直都沒有把它當成 yacc 來罵。 -- ┌─────KKCITY─────┐KKMAN團隊 全新力作 ◎◎KKBOX◎◎ bbs.kkcity.com.tw 知名歌手通通都有 所有新歌想聽就聽 └──From:59.120.53.7 ──┘※※ 內容豐富多元的線上音樂台 ※※ --

04/27 15:40, , 1F
spirit是LL(k),這個 k 確實比 yacc 厲害
04/27 15:40, 1F

04/27 18:13, , 2F
偷瞄的效果真顯著 :p
04/27 18:13, 2F
文章代碼(AID): #16CPZZ00 (Programming)
討論串 (同標題文章)
文章代碼(AID): #16CPZZ00 (Programming)