【问题标题】:Antlr 4 Generate Parse Tree Code in JavaAntlr 4 在 Java 中生成解析树代码
【发布时间】:2015-04-06 13:30:04
【问题描述】:

使用 Antlr4,我想以 Java/JavaScript 代码的形式生成解析树。 这就是我的 main.Java 的样子

 String sql = "SELECT log AS x FROM t1 \n" +
                "GROUP BY x\n" +
                "HAVING count(*) >= 4 \n" +
                "ORDER BY max(n) + 0";

        // Create a lexer and parser for the input.
        SQLiteLexer lexer = new SQLiteLexer(new ANTLRInputStream(sql));
        SQLiteParser parser = new SQLiteParser(new CommonTokenStream(lexer));

        // Invoke the `select_stmt` production.
        ParseTree tree = parser.select_stmt();
        ParseTreeWalker walker = new ParseTreeWalker();
        SQLiteListener listener = new SQLiteBaseListener();
        ParseTreeWalker.DEFAULT.walk(listener, tree);
    System.out.println(listener.);

我应该调用什么函数来生成代码格式的解析树?

【问题讨论】:

  • 你能举个例子你想在标准输出上看到什么吗?
  • @StefanA - 我想要分层 java 类形式的解析树。
  • "hierarchical java classes" 没有更多上下文是没有意义的。你的意思是你想得到一个AST?您需要创建 Java 类并手动构建 AST。这是我能想到的唯一与你的问题有关的事情。

标签: java sql parsing antlr antlr4


【解决方案1】:

我不确定您所说的“分层”视图是什么意思。 antlr 命令行工具有 -gui 选项,如果那是您正在寻找的。否则,您可以通过在 ANTLR 创建的 enter/exist 侦听器方法中添加 Actions 和/或添加 Sysouts 来打印如何评估语法。例如,如果您有以下语法:

grammar Grammar;

@lexer::header{
 //package name where Java files will be created
}

@parser::header{
//package name where Java files will be created
}


value  : letters | number | string;

letters : LETTERS;
number  : NUMBER;
string  : STRING;

LETTERS : '/*' {System.out.println("Found Letters!");};
NUMBER  : [0-9]+ {System.out.println("Found Number!");};
STRING : [a-zA-Z0-9]+ {System.out.println("Found String!");};

WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

ANTLR4 将生成一个 GrammarListener.java(假设您的语法称为 Grammar.g4)如果您在 Eclipse 中右键单击 .g4 文件并选择安装了 ANTRL4 IDE 的“Generate ANTLR Recognizer” .您还可以通过调用静态 org.antlr.v4.Tool.main 使用 Java 生成解析器和词法分析器:

Tool.main(new String[]{grammarFile, "-o", outputDirectory});

生成的接口将包含如下方法:

public interface GrammarListener extends ParserTreeListener {
    void enterValue(GrammarParser.Valuecontext ctx);
    void exitValue(GrammarParser.ValueContext ctx);
    void enterLetters(GrammarParser.StringContext ctx);
    void exitLetters(GrammarParser.StringContext ctx);
    .
    .
}

你需要实现这个接口...

public class GrammarListenerImpl implements GrammarListener {

.
.
@Override
public void enterLetters(GrammarParser.LetterContext ctx) {
 System.out.println("Enter: Letters");
// do other stuff
.
.
}

并添加 Sysouts(在这种情况下)或其他业务逻辑以在语法中出现此匹配时进行处理。 Sysouts 可以生成如下内容:

Enter value
   Enter Letters
     Do something...
   Exit Letters
Exit value

这将显示一个嵌套的(使用制表符/空格等对其进行格式化)评估语法的调用序列。

【讨论】:

  • 一个很好的答案,但它错过了旨在执行侦听器和相关 Sysout 的代码。
【解决方案2】:

这一行:

ParseTree tree = parser.select_stmt();

是你的解析树。查看 API 文档以查看它有什么方法:http://www.antlr.org/api/JavaTool/org/antlr/v4/runtime/tree/ParseTree.html

您可能会对它的getChild(...) 和getParent() 方法感兴趣。

【讨论】:

  • 谢谢巴特,我正在使用这种方法。我想知道这个解析树是否可以以分层 java 类的形式查看。
  • 嗨@user3898179,不知道你所说的“分层java类”是什么意思。我对ParseTree 的理解是:一个可以访问父子节点的Java 类(即“分层Java 类”)。
猜你喜欢
  • 2013-04-23
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
相关资源
最近更新 更多