Java ANTLR-如何确定哪种解析树“最适合”某些代码

Java ANTLR-如何确定哪种解析树“最适合”某些代码,java,parsing,compiler-construction,antlr,antlr4,Java,Parsing,Compiler Construction,Antlr,Antlr4,我正在用ANTLR构建一个程序,其中我要求用户输入一些Java代码,它会输出等效的C代码。在我的程序中,我要求用户输入一些Java代码,然后对其进行解析。到目前为止,我一直假设他们输入的东西将作为一个有效的编译单元单独解析,例如 package foo; class A { ... } class B { ... } class C { ... } 然而,情况并非总是如此。他们可能只是从类内部输入代码: public void method1() { ... } public vo

我正在用ANTLR构建一个程序,其中我要求用户输入一些Java代码,它会输出等效的C代码。在我的程序中,我要求用户输入一些Java代码,然后对其进行解析。到目前为止,我一直假设他们输入的东西将作为一个有效的编译单元单独解析,例如

package foo;

class A { ... }
class B { ... }
class C { ... }
然而,情况并非总是如此。他们可能只是从类内部输入代码:

public void method1() {
    ...
}

public void method2() {
    ...
}
或方法的内部:

System.out.print("hello ");
System.out.println("world!");
甚至只是一个表达:

context.getSystemService(Context.ACTIVITY_SERVICE)

如果我试图通过调用parser.compilationUnit来解析这些代码段,它将无法正常工作,因为大多数代码都被解析为错误节点。我需要根据代码的性质调用正确的方法,例如parser.expression或parser.blockStatements。但是,我不想要求用户明确指出这一点。推断我正在解析哪种代码的最佳方法是什么?

与其尝试猜测有效的语法规则入口点来解析未知范围的语言片段,不如逐步向源文本添加范围包装,直到实现有效的顶级规则解析

也就是说,对于每个连续的解析失败,逐步添加伪包、类和方法语句作为源文本包装器

为成功解析而添加的任何包装器都将是已知数量。因此,可以容易地识别表示原始源文本的解析树节点

可能想要使用一个快速失败的解析器;使用BailErrorStrategy构造解析器以获得此行为。

中的算法尝试从定义的规则集中选择最合适的解析规则。此web服务将Objective-C代码片段转换为Swift,您可以自己立即估计转换的质量

算法 我们使用开源软件。算法的详细步骤如下所示:

使用以下规则解析输入的Objective-C代码片段 翻译单位 实现定义列表 接口声明列表 表示 复合语句 若特定规则的解析结果不包含任何错误,则返回 立刻统治。 选择最接近结束分析错误的规则。 如果有两个或多个规则具有相同的最接近结束错误 位置,选择语法错误数最少的规则。 演示 存在使用不同解析规则解析的测试代码示例:

翻译单位: 实施定义列表: 接口声明列表: 复合声明: 即使输入不正确,我们的算法也能够检测到适当的解析规则:

有错误的复合语句:
在语法中创建一个新的顶级解析器规则,该规则将所有可能的输入作为备选输入,然后依赖它。你的语法中已经有了所有需要加入新规则的规则。对于Java,应该很少有冲突——除了字段和局部变量、方法和构造函数、内部类型和封闭类型之外,我认为您不会有问题。但是,您没有指定可能输入的确切分辨率。@predi我不确定您最后一句话的意思。我喜欢你的方法,但有一个问题:如果用户犯了语法错误,比如在多行代码的单个语句中忘记了分号,该怎么办?那么ANTLR将不会匹配任何备选方案,即使某些方案显然比其他方案更适合。请确保您的新规则将EOF令牌指定为最后一个预期令牌-如果没有任何备选方案匹配,甚至部分匹配,这可能是原因。我所说的分辨率是指允许用户向下钻取的距离,例如,如果是输入,您希望它被识别吗?只是福怎么样?这些都是有效的Java代码段。对于代码生成器来说,即使只是一个代码片段,也需要语法正确的输入,这不是一个奇怪的要求。@predi-Huh,你是说即使存在非零数量的语法错误,ANTLR也会匹配另一个选项?我并没有从经验上尝试过,我只是假设即使是一个错误也会使它完全排除另一种选择。我不喜欢新的顶级解析规则,因为它污染了语法。