それを行う簡単な方法はないと思います。次のようにルールを作成できます。
function
: ID PERIOD function
-> ^(function ID)
| ID
;
ただし、それは最後のノードをルートにし、他のすべてのノードをその子にするだけです。たとえば、次のソース:
a.b.c.d.e
次のツリーになります。
e
/ / \ \
d c b a
最初に を解析するときはとの再帰呼び出しにa.b.c.d.e
なるa
ため、簡単な修正方法はわかりません。ID
b.c.d.e
function
a.b.c.d.e
| +-----+
| |
| `-----> function
|
`----------> ID
その結果、それはその子としてb.c.d.e
持つことになります。a
then にb
なるとID
、こちらも子として の隣に追加されa
ます。あなたの場合、a
を子として削除してから、 の子のリストに追加する必要がありますb
。しかし、私の知る限り、それはANLTRでは不可能です(少なくとも、文法内できれいな方法ではありません)。
編集
さて、回避策としてエレガントなものを考えていましたが、期待どおりには機能しませんでした。last
したがって、洗練されていない解決策として、ノードを書き換えルールのルートとして一致させることができます。
function
: (id '.')* last=id -> ^($last)
;
次に、演算子を使用して、すべての可能な先行ノード ( children
) を収集します。List
+=
function
: (children+=id '.')* last=id -> ^($last)
;
パーサーでカスタム メンバー メソッドを使用して、これらchildren
をツリーのルートに「注入」します (! で右から左に移動しますList
)。
function
: (children+=id '.')* last=id {reverse($children, (CommonTree)$last.tree);} -> ^($last)
;
ちょっとしたデモ:
grammar ReverseTree;
options {
output=AST;
}
tokens {
ROOT;
}
@members {
private void reverse(List nodes, CommonTree root) {
if(nodes == null) return;
for(int i = nodes.size()-1; i >= 0; i--) {
CommonTree temp = (CommonTree)nodes.get(i);
root.addChild(temp);
root = temp;
}
}
}
parse
: function+ EOF -> ^(ROOT function+)
;
function
: (children+=id '.')* last=id {reverse($children, (CommonTree)$last.tree);} -> ^($last)
;
id
: ID
;
ID
: ('a'..'z' | 'A'..'Z')+
;
Space
: ' ' {skip();}
;
そして、ちょっとしたテストクラス:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
ANTLRStringStream in = new ANTLRStringStream("a.b.c.d.e Stack.Overflow.Horse singleNode");
ReverseTreeLexer lexer = new ReverseTreeLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ReverseTreeParser parser = new ReverseTreeParser(tokens);
ReverseTreeParser.parse_return returnValue = parser.parse();
CommonTree tree = (CommonTree)returnValue.getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
次のような AST が生成されます。

入力文字列の場合:
"a.b.c.d.e Stack.Overflow.Horse singleNode"