【问题标题】:How to visit node of ANTLR tree without using children如何在不使用子节点的情况下访问 ANTLR 树的节点
【发布时间】:2021-01-20 15:03:02
【问题描述】:

我在使用 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 方法跳转到我的类 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 语句中是否可以在不使用子节点的情况下访问包含令牌“+”的 ANTLR 树的节点值?我不想也为“+”标记使用标签替代品或其他规则。

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

    添加:'+';

    SUB : '-' ;

比我能够在 IF 语句中(在相等的右侧)通过这个命令使用而不是属于标记“+”的“+”号:

questParser.ADD

我不知道如何在我的上下文中正确找到标记“+”的数量(不使用子代)。如果我可以在我的 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

有人可以帮帮我吗?

【问题讨论】:

    标签: tree token antlr grammar


    【解决方案1】:

    我建议,您的语法越复杂,您就越想使用显式 Lexer 规则(例如:ADD: "+";),并且您想标记解析器规则的各个部分(例如 op= )。

    这些为您提供了编写访问者/侦听者代码的工具,这些代码更易于遵循且不易出错。

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

    真的没有办法让事情变得更容易,同时不做你说你不想做的事情。

    相信我,开始使用诸如显式 Lexer 规则之类的工具并标记解析器规则的各个部分。从长远来看,您会很高兴自己做到了。

    【讨论】:

    • 我不确定,但我会听取您的建议。非常感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多