我如何确定 ANTLR 4 用来解析表达式的规则?
How can I determine the rule which is used by ANTLR 4 to parse the expression?
我正在尝试从 ANTLR 4 创建的解析树创建构建 AST(我的自定义 class 层次结构中的抽象语法树)的 Java class。我正在做这是一阶逻辑语言 https://github.com/antlr/grammars-v4/blob/master/fol/fol.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
生成了以下 class,我在这里只展示了一部分(为了简洁起见,我删除了实现 - 它是标准的,由 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 种方法 - 一种 returns FormulaContext
和另一种 returns ArrayList<FormulaContext>
。没有更多有价值的方法了。
假设我有 FormulaContext
个实例,我想进一步检查它。 我该怎么办? 我的期望是知道 FormulaContext
这个实例的构造规则,然后我知道哪些方法 (e.t。formula(0); bin_connective(); formula(1);
对于第一条规则)我可以调用并且我可以安全地调用这些方法。
问题是 - 我找不到确定用于构造的规则的方法,这是非终结符吗?当然,我可以尝试为每个规则(例如 testRule1、testRule2 等)创建测试方法,它调用上述方法并检查公式、NOT、bin_connective 和所有这些子项的可用性,然后可以推断使用了哪个规则,然后进一步消化正在考虑的实例。
但是这样的测试方法是正确的方法吗?我简直不敢相信这一切都如此简陋。此外,此类测试方法可以由 ANTLR 4 自动生成,有关于它们的所有信息,但仍然 - ANTLR 没有此类功能。
那么 - 推断非终结符规则的最佳做法是什么 class?
您可以 label your alternatives 使用 #
运算符,如下所示:
formula
: formula bin_connective formula #BinaryFormula
| NOT formula #Negation
| ...
;
这将创建继承自 FormulaContext
的 classes NegationContext
等。因此,您可以根据得到的 class 判断选择了哪个备选方案。在访问者和听众中,您现在可以重载 visitNegation(NegationContext)
等来访问特定类型的公式。
我正在尝试从 ANTLR 4 创建的解析树创建构建 AST(我的自定义 class 层次结构中的抽象语法树)的 Java class。我正在做这是一阶逻辑语言 https://github.com/antlr/grammars-v4/blob/master/fol/fol.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
生成了以下 class,我在这里只展示了一部分(为了简洁起见,我删除了实现 - 它是标准的,由 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 种方法 - 一种 returns FormulaContext
和另一种 returns ArrayList<FormulaContext>
。没有更多有价值的方法了。
假设我有 FormulaContext
个实例,我想进一步检查它。 我该怎么办? 我的期望是知道 FormulaContext
这个实例的构造规则,然后我知道哪些方法 (e.t。formula(0); bin_connective(); formula(1);
对于第一条规则)我可以调用并且我可以安全地调用这些方法。
问题是 - 我找不到确定用于构造的规则的方法,这是非终结符吗?当然,我可以尝试为每个规则(例如 testRule1、testRule2 等)创建测试方法,它调用上述方法并检查公式、NOT、bin_connective 和所有这些子项的可用性,然后可以推断使用了哪个规则,然后进一步消化正在考虑的实例。
但是这样的测试方法是正确的方法吗?我简直不敢相信这一切都如此简陋。此外,此类测试方法可以由 ANTLR 4 自动生成,有关于它们的所有信息,但仍然 - ANTLR 没有此类功能。
那么 - 推断非终结符规则的最佳做法是什么 class?
您可以 label your alternatives 使用 #
运算符,如下所示:
formula
: formula bin_connective formula #BinaryFormula
| NOT formula #Negation
| ...
;
这将创建继承自 FormulaContext
的 classes NegationContext
等。因此,您可以根据得到的 class 判断选择了哪个备选方案。在访问者和听众中,您现在可以重载 visitNegation(NegationContext)
等来访问特定类型的公式。