首页 > 解决方案 > 如何确定 ANTLR 4 用于解析表达式的规则?

问题描述

我正在尝试从 ANTLR 4 创建的解析树创建构建 AST(我的自定义类层次结构中的抽象语法树)的 Java 类。我这样做是为了一阶逻辑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,我在这里仅部分介绍(为简洁起见,我删除了实现 - 它是标准的,由 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);
        }
    } 

所以 - 可以看到:如果有 rule, that contains NOT,那么就有 method TerminalNode NOT,是否有一个或多个方法包含一个或多个公式,那么有 2 个方法 - 一个 returnFormulaContext和另一个 return ArrayList<FormulaContext>。没有比这更有价值的方法了。

让我们假设我有FormulaContext实例,我想进一步检查它。我应该怎么办?我的期望是知道构造这个实例所依据的规则,FormulaContext然后我知道我可以调用哪些方法(formula(0); bin_connective(); formula(1);第一个规则是等),我可以安全地调用这些方法。

问题是 - 我找不到确定用于构造的规则的方法是这个非终结符吗?当然,我可以尝试为每个规则(例如 testRule1、testRule2、...)创建测试方法,它调用上述方法并检查公式、NOT、bin_connective 和所有这些子术语的可用性,然后可以推断出哪个规则是使用,然后相应地进一步消化正在考虑的实例。

但是这样的测试方法是正确的方法吗?我不敢相信这一切都是那么粗暴。此外,这些测试方法可以由 ANTLR 4 自动生成,它们的所有信息都有,但仍然 - ANTLR 没有这样的功能。

那么-推断非终端类规则的最佳实践是什么?

标签: javaantlrantlr4abstract-syntax-tree

解决方案


您可以使用这样的运算符标记您的替代方案#

formula
    : formula bin_connective formula #BinaryFormula
    | NOT formula                    #Negation
    | ...
    ;

这将创建NegationContext继承自FormulaContext. 因此,您可以根据您获得的课程来判断选择了哪个替代方案。在访问者和听众中,您现在可以重载visitNegation(NegationContext)等以访问该特定类型的公式。


推荐阅读