Rustのマクロが面白かったのでBrainfuckの処理系を作ってしまった

タイトルの通りです

Rustのマクロを初めて触ったのですが、結構いろいろできそうでした(というかチューリング完全らしい)

条件付きですが自分で構文のパースもできるようで、これは何かできないかとおもったところで思いついたのがBrainfuckでした

Rustのマクロについては、こちらの記事がかなり詳細に書いてくださっているので構文などはこちらをご参照ください qiita.com

また、Brainfuckの仕様についてはWikipediaのものに従ったつもりです ja.wikipedia.org

コード

さて、私が書いたBrainfuckを処理するマクロがこちらです

3-43行がマクロの定義です 9パターンの分岐があります

まずいちばん上のパターンは最初に呼ばれ、メモリやポインタの定義を担当します memoryという配列がBrainfuckが扱えるメモリ領域になります

2番目は一番最後に呼ばれ、処理内容をすべて処理し終わったときに該当し、何もしないという命令を返します

3番目以降で実際に命令を処理しています 慎重に見れば、一番前の命令のみパターンマッチし、2番目以降は再帰的に処理していることがわかると思います(1番下のみ例外)

46,47行目がこのマクロの呼び出し側です このコードはABCと出力するBrainfuckのコードです コンパイル時にマクロによりRustのコードに置換され、コンパイルされます

問題点

このコードの問題点として、字句解析は基本的にRustのパーサ(トークナイザ?)が行うため、Rustの言語仕様で演算記号として定義されてる>>などが正常に処理されません 間にスペースを入れれば正常に動くのですが、このあたりはできればもう少し柔軟にできればよかったですね

ちなみに、マクロの書き方を調べてたのは、これでパーサを定義できないかなとか考えてたからなんですけど、変数名等の識別子に関して自分で1文字ずつパースすることは同じ理由でできなさそうなので諦めました... マクロにBNF渡してパーサを定義するとかちょっと便利そうだったんですけどね 残念


追記

>><<> >< <に置換するようなルールを作れば対応できるという提案をいただいた
私のコードだと実は>><<以外にも->等がエラーになりますが、同様に対応するルールを作れば対応できそう

(この方法でもやはりパーサの定義までは繋がりそうにないのが悲しいところ)