Java 在Antlr中使用访问者编辑AST
我是AntLR的新手,我正在努力做到以下几点: 我想做的是在我解析了一个源文件(当然我有一个有效的语法)并且在内存中有了AST之后,去修改一些东西,然后通过visitor API打印出来 e、 g 并将其转化为:Java 在Antlr中使用访问者编辑AST,java,antlr,antlr4,visitor,Java,Antlr,Antlr4,Visitor,我是AntLR的新手,我正在努力做到以下几点: 我想做的是在我解析了一个源文件(当然我有一个有效的语法)并且在内存中有了AST之后,去修改一些东西,然后通过visitor API打印出来 e、 g 并将其转化为: int foo() { if (x) { y = 1; else { y = 2; } } 到目前为止,我有适当的语法来解析这种语法,并且我还创建了一些访问者方法,当我处于正确的位置时,这些方法会被调用。让我困惑的是,在访问期间,我
int foo() {
if (x) {
y = 1;
else {
y = 2;
}
}
到目前为止,我有适当的语法来解析这种语法,并且我还创建了一些访问者方法,当我处于正确的位置时,这些方法会被调用。让我困惑的是,在访问期间,我无法更改文本
理想情况下,我想要这样的东西:
public Void visitTernExpr(SimpleCParser.TernExprContext ctx) {
ctx.setText("something");
return null;
}
在我的主要观点中,我想让不同的访问者来编辑这个AST,他们每个人都有自己的专长。像这样:
ANTLRInputStream input = new ANTLRInputStream(new FileInputStream(filename));
SimpleCLexer lexer = new SimpleCLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SimpleCParser parser = new SimpleCParser(tokens);
ProgramContext ctx = parser.program();
MyChecker1 mc1 = new MyChecker1();
mc1.visit(ctx);
MyChecker2 mc2 = new MyChecker2();
mc1.visit(ctx);
ctx.printToFile("myfile");
在AntLR中有没有什么方法可以做这些事情,或者我走的方向非常错误?我会使用一个侦听器,是的,您可以在遍历AST时修改它
您可以创建if/else上下文的新实例,然后用它替换三元运算符上下文。这是可能的,因为您有一个对规则父级的引用和一个广泛的API来处理每个规则子级。您可以通过粉碎AST节点和链接来实现这一点。您将创建所有替换子树节点并将它们拼接到位。然后,您必须实现“spit源文本”树漫游;我建议您为此调查“字符串模板” 但最终你必须做很多工作才能达到这个效果。这是因为ANTLR工具的目标主要集中在“解析”上,而“解析”将其余部分推给您 如果您想要做的是用另一组语法替换一组语法,那么您真正想要的是一个。这些工具的设计目的是让上述所有功能都已经内置,这样您就不必重新设计。它们通常还有源代码到源代码的转换,这使得完成像您所展示的任务更加容易实现 为了使用我们的DMS程序转换引擎完成您的示例,您需要编写一个转换规则,然后应用它:
rule replace_ternary_assignment_by_ifthenelse
(l: left_hand_side, c: expression, e1: expression, e2: expression):
statement -> statement
"\l = \c ? \e1 : \e2;"
=> " if (\c) \l = \e1; else \l = \e2 ";
DMS解析您的代码,构建AST,查找重写的匹配项,为您构建/拼接所有这些替换节点。最后
DMS有内置的预打印机来重新生成文本。重点
所有这些都是为了让你继续你的任务,修改你的
代码,而不是在您可以
完成你的任务。轻松阅读我的文章《解析后的生活》
通过我的个人简历或谷歌搜索找到更多关于此主题的信息
如果你去看电影,你会发现很有趣
此变换的逆变换用作示例]
rule replace_ternary_assignment_by_ifthenelse
(l: left_hand_side, c: expression, e1: expression, e2: expression):
statement -> statement
"\l = \c ? \e1 : \e2;"
=> " if (\c) \l = \e1; else \l = \e2 ";