はじめてTree作成できた
Lexer/Parserは作成できてたのに、Treeだけは中々できなかったところ、はじめて出力できた(変換ができた…というだけで実際に動くかどうか分からないけど)。
なぜできなかったか理由を列挙しておく。
- まずLexerの定義*1は全て消す。Lexerのコメント宣言(@lexer::header)も消す。
- これを先にしておかないとヌルポの嵐
- (Lexer/Parser).g をジェネレートした結果に含まれる、(Lexer/Parser).tokens が tree.g と同じ場所にいないといけない
- 結局、.g も geneate先もソースも全て同じディレクトリじゃないとダメ。javaとresourcesを分けたいのになー。
- (Lexer/Parser)のチェックとジェネレートでは、リライトのチェックが不十分で、ミスがあっても作成できてしまう。しかしtreeではアウト。
- これにはまった。ミスがあっても(Lexer/Parser)でASTツリーがちゃんと作れる(リライトがちゃんと適用される)ので気付きにくい。
例えば以下のようなことになる。
// for Parser: ジェネレートOK binding : '=' -> ^('=') | 'in' -> ^('in') ; // for Tree: ジェネレートNG binding : ^('=') | ^('in') ; // for Tree: ジェネレートOK binding : ^('binding' '=') | ^('binding' 'in') ;
Parsarの場合は中間のbindingという要素を省略して一足飛びができるが、Treeだと許されないということらしい。
…それより、はてなのシンタックスハイライト、antlrにまで対応しているとは。まにあっくだな。
追記
というか、^(...) は、「先頭の文字列をラベルにもつ親ノードとして、そこに以降を属させる」の意味だから当たり前だった。bindingノードを作りたくない場合は、以下で良いんじゃない。
// for Tree: ジェネレートOK binding : '=' | 'in' ;
*1:頭文字が大文字の識別子