【问题标题】:How to keep a value taken from a rule in a variable and reuse it in the ANTLR grammar?如何在变量中保留从规则中获取的值并在 ANTLR 语法中重用它?
【发布时间】:2019-05-25 09:14:34
【问题描述】:

我在我的语法中声明了字符串变量,vAttributeNamevClassName,并为它们分配了标记的文本值:className属性名称。当我使用通常应在错误替代中包含值的变量之一时,因此在另一条规则中,它在消息中返回 null ... 为什么我的变量不保留这些值?我该如何解决?

grammar TestExpression;

@parser::members {
            String vAttributeName;
            String vClassName;
            }

/* SYNTAX RULES */
textInput               : classifierContext ;
classifierContext       : 'context' c=className attributeContext {vClassName = $c.text;};
attributeContext        : '::' a=attributeName ':' dataType initDefinition {vAttributeName = $a.text;};
initDefinition          : 'init' ':' initExpression ;

initExpression          : boolExpression
                        | decimalExpression
                        | dateTimeExpression
                        | .+? {notifyErrorListeners("Corriger - "l'attribut "+vAttributeName+" de l'entité "+vClassName+" ne correspond pas");}

我正在尝试解析一个表达式,该表达式描述了一个具有 false 值属性的类。

我预期的信息是:“Corriger - l'attribut seat de l'entité Car ne compatible pas”。

但实际消息是:“Corriger - l'attribute null de l'entité null ne compatible pas”。

【问题讨论】:

    标签: java antlr4


    【解决方案1】:

    如果您有类似a: b c {action}; 的规则以及与该规则匹配的输入,则事件将按以下顺序发生:

    1. 应用规则b,如果有则执行其操作。
    2. 应用规则c,如果有则执行其操作。
    3. 动作 action 被执行,并且能够访问 bc 规则的结果(包括由它们的动作设置的任何内容,这就是为什么这些动作首先运行很重要)。

    如果您改为使用a: b {action} c;,则该操作将在b 之后但在c 之前执行(因此将无法访问c 的结果)。

    因此,对于您的代码,这意味着 initExpression 的操作在 classifierContextattributeContext 的操作之前运行,这就是未设置变量的原因。您可以通过移动操作来解决问题,使其在所需部分(即className/attributeName)被解析后直接发生。

    您也可以完全摆脱变量,而是通过从祖父母上下文中获取所需的信息。

    【讨论】:

    • 哦,是的,您的操作顺序是正确的。谢谢@sepp2k。我是 ANTLR4 的新手,所以你的意思是我可以从祖父母上下文中获得所需的信息?我如何在行动中做到这一点?
    • @talohsa 可以使用$ctx获取当前节点的上下文对象,然后可以访问parent获取父节点。所以在initExpression 的动作中,$ctx 会给你InitExpressionContext 对象,$ctx.parent 会给你InitDefinitionContext$ctx.parent.parent 将是AttributeContextContext。但是静态类型将是ParseRuleContext,因此您需要强制转换才能访问来自AttributeContextContext 的方法。因此,要获取属性名称,您可以使用((AttributeContextContext)$ctx.parent.parent).a.getText()
    • 请注意,这假定一个特定的树结构,如果您以改变树结构的方式更改语法,或者如果您从语法中的多个位置调用initExpression 规则(其中attributeContext 不是(总是)父母的父母)。
    • 好的,我现在明白了。它现在正在工作。你帮了我很多,谢谢@sepp2k。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 2021-08-14
    相关资源
    最近更新 更多