我正在尝试创建Java类,从ANTLR 4创建的解析树中建立AST(在我的自定义类层次结构中的抽象语法树)。 我正在为一阶逻辑语言做这件事。https:/github.comantlrgrammars-v4blobmasterfolfol.g4。
具体来说,我是在寻找以下规则 formula
:
formula
: formula bin_connective formula
| NOT formula bin_connective formula
| NOT formula
| FORALL LPAREN variable RPAREN formula
| EXISTS LPAREN variable RPAREN formula
| pred_constant LPAREN term (separator term)* RPAREN
| term EQUAL term
;
ANTLR 4已生成以下类,用于 formula
我在这里只介绍了部分内容(为了简洁起见,我删除了实现--它是标准的,由ANTLR 4生成,只是调用了一些技术方法)。
public static class FormulaContext extends ParserRuleContext {
public TerminalNode NOT() { ... }
public List<FormulaContext> formula() { ... }
public FormulaContext formula(int i) { ... }
public Bin_connectiveContext bin_connective() { ... }
public TerminalNode FORALL() { ... }
public TerminalNode LPAREN() { ... }
public VariableContext variable() { ... }
public TerminalNode RPAREN() { ... }
public TerminalNode EXISTS() { ... }
public Pred_constantContext pred_constant() { ... }
public List<TermContext> term() { ... }
public TermContext term(int i) { ... }
public List<SeparatorContext> separator() { ... }
public SeparatorContext separator(int i) { ... }
public TerminalNode EQUAL() { ... }
public FormulaContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_formula; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof FOLListener ) ((FOLListener)listener).enterFormula(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof FOLListener ) ((FOLListener)listener).exitFormula(this);
}
}
所以,我们可以看到:如果有一个规则,它包含了: NOT
,那么就有了方法 TerminalNode NOT
有一个或多个方法包含一个或多个公式,那么有2个方法 - 一个返回 FormulaContext
和其他回返 ArrayList<FormulaContext>
. 没有更有价值的方法。
假设我有 FormulaContext
例如,我想进一步检查它。我应该怎么做呢? 我的期望是知道这个实例的规则。FormulaContext
的构造,然后我就知道哪些方法(比如说 formula(0); bin_connective(); formula(1);
我知道哪些方法(例如第一条规则)可以调用,而且我可以安全地调用这些方法。
问题是--我找不到决定用于构造的规则的方法,这是非终结性的吗?当然,我可以尝试为每条规则创建测试方法(例如testRule1, testRule2, ...),它调用上述方法并检查公式、NOT、bin_connective和所有这些子项的可用性,然后可以推断出使用的是哪条规则,然后相应地进一步消化考虑中的实例。
但这样的测试方法是否正确呢?我不相信这些都是如此粗糙的。此外,这样的测试方法可以由ANTLR 4自动生成,有所有的信息,但还是--ANTLR没有这样的功能。
那么--对于Non Terminal类,最好的做法是什么?
你可以 标明你的替代品 使用 #
像这样的操作符。
formula
: formula bin_connective formula #BinaryFormula
| NOT formula #Negation
| ...
;
这样就可以创建班级 NegationContext
等继承自 FormulaContext
. 因此,你可以根据你得到的类来判断选择了哪种选择。在访问者和监听者中,你现在可以过载 visitNegation(NegationContext)
等来访问该特定类型的配方。