如何在不使用 children 的情况下访问 ANTLR 树的节点

How to visit node of ANTLR tree without using children

我在使用 antlr 和我的 c# 时遇到了这个非常简单的语法问题:

grammar quest;

prog:   stat+ ;

stat:   expr NEWLINE
    ;

expr:   INT '+' INT 
    |   INT '-' INT 
    ;

INT :   [0-9]+ ;
NEWLINE:'\r'? '\n' ;

在我的 Main 方法中,我使用从 prog 规则开始的输入 3+24 遍历语法。在代码从 Main 方法跳转到我的 class EvalVisitor 之后,所有的魔法都发生了,我的问题也出现了。

class EvalVisitor : questBaseVisitor<int>
{
    public override int VisitStat([NotNull] questParser.StatContext context)
    {
        int value = Visit(context.expr());
        Console.WriteLine(value);
        return 0;
    }

    public override int VisitExpr([NotNull] questParser.ExprContext context)
    {
        int left = int.Parse(context.INT(0).GetText());
        int right = int.Parse(context.INT(1).GetText());

        if (context.children[1].GetText() == "+")
        {
            return left + right;
        }
        else
        {
            return left - right;
        }
    }
}
  1. 在 IF 语句中是否可以在不使用 children 的情况下访问包含标记“+”的 ANTLR 树的节点值?我不想对“+”标记也使用标签替代或其他规则。

  2. 如果我要在语法末尾为标记“+”和“-”添加新规则:

    添加:“+”;

    SUB : '-' ;

比我在 IF 语句(在相等的右侧)中能够通过此命令使用属于标记“+”的数字代替“+”:

questParser.ADD

我又一次不知道如何在我的上下文中正确找到标记“+”的数量(不使用 children)。如果我可以在我的 IF 语句中比较,对我来说将是最好的解决方案:

if (...number_of_token_in_my_context... == questParser.ADD)

这类似于 Terence Parr 的 ANTLR4 参考:

/* expr op=('*'|'/') expr */
    public override int VisitMulDiv([NotNull] LabeledExprParser.MulDivContext context)
    {
        int left = Visit(context.expr(0)); // get value of left subexpression
        int right = Visit(context.expr(1)); // get value of right subexpression
        if (context.op.Type == LabeledExprParser.MUL)
        {
            return left * right;
        }
        else
        {
            return left / right;
        }
    }

但我不想使用任何“op”函数、标签替代品等,因为在我的应用程序中,我有非常复杂和通用的书面语法,我不想编辑它。我还在下面给出了我的树的照片:

picture_of_tree

有人可以帮我吗?

我建议,你的语法越复杂,你就越想使用明确的 Lexer 规则(例如:ADD:“+”;),你就越想标记你的解析器规则的部分(比如op=).

这些为您提供了编写 visitor/listener 更易于理解且不易出错的代码的工具。

“在 IF 语句中是否可以在不使用子节点的情况下访问我的 ANTLR 树的节点值,其中包含标记‘+’?” -> 是的,在您的解析规则中使用 op= 符号标记运算符。然后您可以通过名称而不是它在您的子节点中的位置来引用它。

确实没有办法让事情变得更简单,同时不做你说不想做的事情。

相信我,开始使用诸如显式词法分析器规则之类的工具并标记解析器规则的各个部分。你会很高兴你在漫长的运行.