Theme NexT works best with JavaScript enabled
0%

昨晚寫完 GobiesVM 裡的IO.readlines函式後,很開心地用了有著100k個單詞的單行文字檔作測試。咦?怎麼一個字都沒有?

第一版的IO.readlines實作,就如同你在stackoverflow上會找到的一樣,是用bufio.Scanner來讀文字檔

1
2
3
4
5
6
input, err := os.Open(filename)
scanner := bufio.NewScanner(input)

for scanner.Scan() {
line := scanner.Text()
}

上面這段code看似沒有問題,在一般的文字檔(例如程式碼本身)測試也都正常,為什麼在遇到大檔的時候就出包了呢?
當我們去看 bufio.Scanner的實作 時,會發現 Scanner 在運作時,會將文字分為一個個的token,並交由SplitFunc決定如何區分token(預設是斷行),由於是buffered IO,所以會有每個token所能用的buffer的最大size(MaxScanTokenSize = 64 * 1024),以上面的檔案為例,因為100k個單字全部都集中於一行內,所以很輕易地就超過了這個限制。因此當我將每個詞分至多行後就可以正常運行。

有鑑於這樣的解決之道只是治標不治本,所以讓我們來看看第二個版本吧:

Read more »

What police did this night is outrageous. What they did afterwards to cover up their actions is disgusting. This is why I’m compiling this to gather all materials I could collect and make sure these can never go away or be deleted.

To sum up:

ALL THE STUDENTS DO IS PEACEFUL PROTESTING

SOME ANTI-RIOT POLICE STRIPPED THEIR IDENTITY OFF TO AVOID BEING CAUGHT USING EXCESSIVE FORCE

If some materials below were gone, please leave your comment in the bottom of this post, I’ll fix them as soon as possible, thanks.

God bless Taiwan.

Read more »

最後的成果在這個repo裡: https://github.com/brucehsu/peg/tree/leg

來龍去脈

決定要用Go寫Ruby VM之後,第一件事情當然就是尋找Go上的parser generator。
Go裡頭就包含了 自己的yacc工具 ,與原先的yacc語法完全相容,加上Ruby(MRI、mruby)都是使用yacc來作為生成parse的方式(詳見各repo底下的parse.y),所以一開始很直覺地就把goyacc列為solution。
但是goyacc在使用上有個要注意的地方,就是 c9s前輩所提到的 :它跟原先的yacc一樣,還需要跟lexer作搭配,但golex這個project卻已經無人維護許久。

之後在 唐鳳前輩的指點下 ,決定採用tinyrb中以LEG/PEG定義出的Ruby subset作為發展的基石,況且在 RubyGoLighty 這個以tinyrb為底並Go實作的project當中,除了提供一個stack-based的Ruby VM外,還手動將LEG/PEG轉換成了Go code,看來可以省下不少麻煩。

但等等…… 因為其年代久遠(四年多前),裡面的Go code看來一點都不像Go,而只是如C的直接貼上(不過我沒有build過或是認真看過,或許可以正常使用也說不準),要修改也有些難度,難不成只能重新再造輪子了?

經過一番搜尋,發現其實之前就已經 有人重新用Go實作了PEG 並加入一些Go限定的功能,而且到去年9月時仍有commit,只是事情有一好沒兩好,這位作者只有實作PEG的部份,不含LEG。

剛好我也打算再跟Go混熟一點,幫這個project加入LEG的支援看來似乎是個不錯的練習,只是我沒想到會拖那麼久…… orz

Read more »