Dart で書いてみました。やっつけなので汚いです。Dart よく知らないけどライフゲームが動いたのでヨシ、というレベルのものです。
移植元
ベースになっているバージョン: tag:46 のあたり
- 追記 2021-03-21: Dart のバージョンアップ(2.9.1 => 2.12.0)に合わせて修正
- null safety まわりを適当に修正
- 追記 2021-03-21: ステップ56の修正まで適用しました
メモ
- アセンブラ・VM は移植対象から外しました。Ruby 版のものを使います。
- トークナイザとパーサを分けてみた
- テストのステップを細かくした
- ファイルを直接まじめに読まなくても、 標準入力が読めればあとはシェルスクリプトでラップしてあげたりすればいいので、 もうそれでいいかなという気持ちになった。
Dart でプログラムを書くのは今回初めてでしたが、JavaScript と Java あたりを知っていればかなりスムーズに書き始められるなーという感想でした。引っかかるところがほとんどなかったです(今回書いた範囲では)。適当にググりながら 1日で書けてしまいました。
今回の実験的な要素としては、パーサをいじって set
を不要にしてみました。
(追記 2021-03-21: この修正はいったん revert しましたが、一応 trial ブランチに残してあります。)
func main() { var a; - set a = 42; + a = 42; }
文の先頭の set
で判別するのをやめて、識別子だったら parseSet_v2()
を呼ぶ。
もうちょっとめんどくさいかなと思ってましたが、これだけだったら意外と簡単ですね。
List parseSet_v2() { // consume("set"); ... これが不要になる final t = peek(); pos++; final varName = t.value; consume("="); final expr = parseExpr(); consume(";"); return ["set", varName, expr]; } List parseStmt() { final t = peek(); if (t.value == "}") { return null; } if (t.value == "func" ) { return parseFunc(); } // ... // else if (t.value == "set" ) { return parseSet(); } // ... else if (t.value == "_cmt" ) { return parseVmComment(); } else { if (t.type == "ident") { return parseSet_v2(); } else { throw notYetImpl([ t ]); } } }