【问题标题】:Rule variables in ANTLR4ANTLR4 中的规则变量
【发布时间】:2013-08-07 17:34:46
【问题描述】:

我正在尝试将我的语法从 v3 转换为 v4,但遇到了一些问题。

在 v3 中,我有这样的规则:

dataspec[DataLayout layout] returns [DataExtractor extractor]
    @init {
        DataExtractorBuilder builder = new DataExtractorBuilder(layout);
    }
    @after {
        extractor = builder.create();
    }
    : first=expr { builder.addAll(first); } (COMMA next=expr { builder.addAll(next); })* 
    ;

expr returns [List<ValueExtractor> ext]
    ...

但是,v4 中的规则返回这些自定义上下文对象而不是我明确告诉它们返回的内容,所以事情都搞砸了。执行此操作的 v4 方法是什么?

【问题讨论】:

    标签: java variables migration rules antlr4


    【解决方案1】:

    这里有多种情况:

    • 访问传入的变量 (layout)
    • 访问当前规则的返回值 (extractor)
    • 访问局部变量(firstnext

    传入的变量和当前规则的返回值

    访问传入的变量或当前规则的返回值时,您只需在规则定义中给定的名称前加上$

    • layout 变为 $layout
    • extractor 变为 $extractor

    局部变量

    显然需要做的是引用根据返回值的规则的returns 子句命名的变量成员。

    例如,first 正在捕获来自expr 规则的结果,而expr 将其返回值命名为ext,这意味着:

    • first 变为 $first.ext
    • next 变为 $next.ext

    何时使用$ 表单

    与 v3 中您可以将某些变量作为常规 java 字段引用的情况不同,在 所有 情况下(包括在操作中、@init@after 块中)都需要使用 $ 表单,以及将变量传递给其他规则时。

    其他陷阱

    如果您要在局部变量中捕获可选标记,您可能会遇到空指针异常,因为您正在引用该变量的属性。

    single_lname returns [String s]
        : p=LNAME_PREFIX? r=NAME { $p.text + toNameCase($r.text); }
    ;
    

    您需要检查$p 是否为空,但大多数情况下这会导致“缺少属性访问”错误。 ANTLR4 做了一个特殊的例外,以便您可以检查这一点,if 条件中使用时适用(例如,将其重构为使用三元运算符仍会导致错误)。

    single_lname returns [String s]
        : p=LNAME_PREFIX? r=NAME { 
            if ($p == null) {
                $s = toNameCase($r.text);
            } else {
                $s = $p.text + toNameCase($r.text);
            }
        }
    ;
    

    更新的规则

    综上所述,dataspec 规则变为:

    dataspec[DataLayout layout] returns [DataExtractor extractor]
        @init {
            DataExtractorBuilder builder = new DataExtractorBuilder($layout);
        }
        @after {
            $extractor = builder.create();
        }
        : first=expr { builder.addAll($first.ext); }
            (COMMA next=expr { builder.addAll($next.ext); })* 
        ;
    

    【讨论】:

    • V4 中$ 的使用规则与V3 的规则几乎相同。语法被破坏的原因是 V3 中的一个实现细节导致生成的代码中的变量名称与它们在语法中出现的名称相同,因此无法使用 $大部分时间 .该实现细节在 V4 中发生了变化。
    猜你喜欢
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 2023-01-08
    相关资源
    最近更新 更多