ANTLR4中的规则变量 [英] Rule variables in ANTLR4

查看:340
本文介绍了ANTLR4中的规则变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将语法从v3转换为v4,并且遇到了一些麻烦.

I'm trying to convert my grammar from v3 to v4 and having some trouble.

在v3中,我有如下规则:

In v3 I have rules like this:

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的实现方式是什么?

However, with rules in v4 returning these custom context objects instead of what I explicitly told them to return, things are all messed up. What's the v4 way to do this?

推荐答案

这里有多种情况:

  • 访问传入的变量(layout)
  • 访问当前规则的返回值(extractor)
  • 访问局部变量(firstnext)
  • accessing passed-in variables (layout)
  • accessing the current rule's return value (extractor)
  • accessing local variables (first, next)

在访问传入变量或当前规则的返回值时,只需在规则定义中使用$前缀名称即可.

When accessing passed-in variables or the return value of the current rule you simply need to prefix the name given in the rule definition with $.

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

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

Evidently what needs to be done is to reference the variables' member which is named according to the returns clause of the rule which returned the value.

例如,first正在捕获expr规则的结果,并且expr将其返回值命名为ext,表示:

For example, first is capturing the result from the expr rule, and expr names its return value ext, meaning that:

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

不同于在v3中可以将某些变量作为常规java字段引用的情况,在 all 的所有情况下(包括在动作中)在@init@after块中都必须使用$形式,以及将变量传递给其他规则时.

Unlike in v3 where you could reference certain variables as regular java fields, using the $ form is necessary in all cases, including in actions, in the @init and @after blocks, and when passing variables to other rules.

如果要在局部变量中捕获可选标记,则在引用该变量的属性后,可能会遇到空指针异常.

If you're capturing optional tokens in a local variable, you may run into null pointer exceptions now that you're referencing an attribute of that variable.

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

您需要检查$p是否为空,但是大多数情况下,这将导致缺少属性访问"错误. ANTLR4是一个特殊的异常,因此您可以检查它,在if条件下使用时,仅 适用(例如,将其重构为使用三元运算符仍然会导致错误).

You'll need to check whether $p is null, but most of the time this would result in a "missing attribute access" error. ANTLR4 makes a special exception so that you can check this, which only applies when used in an if condition (refactoring this to use the ternary operator, for example, will still result in the error).

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); })* 
    ;

这篇关于ANTLR4中的规则变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆