以下は、開始することができます。
public class AST {
private final Object payload;
private final List<AST> children;
public AST(ParseTree tree) {
this(null, tree);
}
private AST(AST ast, ParseTree tree) {
this(ast, tree, new ArrayList<AST>());
}
private AST(AST parent, ParseTree tree, List<AST> children) {
this.payload = getPayload(tree);
this.children = children;
if (parent == null) {
walk(tree, this);
}
else {
parent.children.add(this);
}
}
public Object getPayload() {
return payload;
}
public List<AST> getChildren() {
return new ArrayList<>(children);
}
private Object getPayload(ParseTree tree) {
if (tree.getChildCount() == 0) {
return tree.getPayload();
}
else {
String ruleName = tree.getClass().getSimpleName().replace("Context", "");
return Character.toLowerCase(ruleName.charAt(0)) + ruleName.substring(1);
}
}
private static void walk(ParseTree tree, AST ast) {
if (tree.getChildCount() == 0) {
new AST(ast, tree);
}
else if (tree.getChildCount() == 1) {
walk(tree.getChild(0), ast);
}
else if (tree.getChildCount() > 1) {
for (int i = 0; i < tree.getChildCount(); i++) {
AST temp = new AST(ast, tree.getChild(i));
if (!(temp.payload instanceof Token)) {
walk(tree.getChild(i), temp);
}
}
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
AST ast = this;
List<AST> firstStack = new ArrayList<>();
firstStack.add(ast);
List<List<AST>> childListStack = new ArrayList<>();
childListStack.add(firstStack);
while (!childListStack.isEmpty()) {
List<AST> childStack = childListStack.get(childListStack.size() - 1);
if (childStack.isEmpty()) {
childListStack.remove(childListStack.size() - 1);
}
else {
ast = childStack.remove(0);
String caption;
if (ast.payload instanceof Token) {
Token token = (Token) ast.payload;
caption = String.format("TOKEN[type: %s, text: %s]",
token.getType(), token.getText().replace("\n", "\\n"));
}
else {
caption = String.valueOf(ast.payload);
}
String indent = "";
for (int i = 0; i < childListStack.size() - 1; i++) {
indent += (childListStack.get(i).size() > 0) ? "| " : " ";
}
builder.append(indent)
.append(childStack.isEmpty() ? "'- " : "|- ")
.append(caption)
.append("\n");
if (ast.children.size() > 0) {
List<AST> children = new ArrayList<>();
for (int i = 0; i < ast.children.size(); i++) {
children.add(ast.children.get(i));
}
childListStack.add(children);
}
}
}
return builder.toString();
}
}
"f(arg1='1')\n"
次のように、入力の AST を作成するために使用できます。
public static void main(String[] args) {
Python3Lexer lexer = new Python3Lexer(new ANTLRInputStream("f(arg1='1')\n"));
Python3Parser parser = new Python3Parser(new CommonTokenStream(lexer));
ParseTree tree = parser.file_input();
AST ast = new AST(tree);
System.out.println(ast);
}
これは次のように出力されます:
'- file_input
|- stmt
| | |- small_stmt
| | | | |- アトム
| | | | | | '- TOKEN[タイプ: 35, テキスト: f]
| | | | '- トレーラー
| | | | |- TOKEN[タイプ: 47、テキスト: (]
| | | | |- 引数リスト
| | | | | | |- テスト
| | | | | | | | '- TOKEN[タイプ: 35, テキスト: arg1]
| | | | | | |- TOKEN[タイプ: 53、テキスト: =]
| | | | | | '- テスト
| | | | | | '-トークン[タイプ: 36、テキスト: '1']
| | | | '- TOKEN[タイプ: 48, テキスト: )]
| | '- TOKEN[タイプ: 34、テキスト: \n]
'- TOKEN[タイプ: -1, テキスト: ]
これには不要なノードがまだ含まれていることは承知していますが、除外したい一連のトークン タイプを追加することもできます。お気軽にハックしてください!
これは、適切なインポート ステートメントといくつかの JavaDocs およびインライン コメントを含む上記のコードのバージョンを含むGistです。