次のようなサブツリーを持つantlrグラマーがあります。
^(type ID)
に変換したい:
^(type DUMMY ID)
type は 'a'|'b' です。
注: 私が本当にやりたいことは、ダミーの名前を生成して、匿名のインスタンス化を明示的に変換することです。
以下の文法に絞り込みましたが、次のようになります。
(a bar) (b bar)
got td
got bu
Exception in thread "main" org.antlr.runtime.tree.RewriteEmptyStreamException: rule type
at org.antlr.runtime.tree.RewriteRuleElementStream._next(RewriteRuleElementStream.java:157)
at org.antlr.runtime.tree.RewriteRuleSubtreeStream.nextNode(RewriteRuleSubtreeStream.java:77)
at Pattern.bu(Pattern.java:382)
エラーメッセージは続きます。これまでの私のデバッグ:
- 入力は、2 つのツリーを生成する最初の文法を通過しました。a バーと b バー。
- 2 番目の文法はツリーに一致します。tdとbuを印刷しています。
- 書き換えがクラッシュしますが、理由がわかりませんか? RewriteEmptyStreamException とはどういう意味ですか?
この種の書き換えを行う適切な方法は何ですか?
私の主な文法 Rewrite.g:
grammar Rewrite;
options {
output=AST;
}
@members{
public static void main(String[] args) throws Exception {
RewriteLexer lexer = new RewriteLexer(new ANTLRStringStream("a foo\nb bar"));
RewriteParser parser = new RewriteParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.test().getTree();
System.out.println(tree.toStringTree());
CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
Pattern p = new Pattern(nodes);
CommonTree newtree = (CommonTree) p.downup(tree);
}
}
type
: 'a'
| 'b'
;
test : id+;
id : type ID -> ^(type ID["bar"]);
DUMMY : 'dummy';
ID : ('a'..'z')+;
WS : (' '|'\n'|'r')+ {$channel=HIDDEN;};
そしてPattern.g
tree grammar Pattern;
options {
tokenVocab = Rewrite;
ASTLabelType=CommonTree;
output=AST;
filter=true; // tree pattern matching mode
}
topdown
: td
;
bottomup
: bu
;
type
: 'a'
| 'b'
;
td
: ^(type ID) { System.out.println("got td"); }
;
bu
: ^(type ID) { System.out.println("got bu"); }
-> ^(type DUMMY ID)
;
コンパイルするには:
java -cp ../jar/antlr-3.4-complete-no-antlrv2.jar org.antlr.Tool Rewrite.g
java -cp ../jar/antlr-3.4-complete-no-antlrv2.jar org.antlr.Tool Pattern.g
javac -cp ../jar/antlr-3.4-complete-no-antlrv2.jar *.java
java -classpath .:../jar/antlr-3.4-complete-no-antlrv2.jar RewriteParser
編集 1: antlr4 も使用してみましたが、同じクラッシュが発生します。