antlr:“规则范围上缺少属性访问”问题

gj3fmq9x  于 2021-07-05  发布在  Java
关注(0)|答案(4)|浏览(403)

我正在尝试构建一个antlr语法来解析标记句,例如:

DT The NP cat VB ate DT a NP rat

并掌握语法:

fragment TOKEN  :   (('A'..'Z') | ('a'..'z'))+;
fragment WS :   (' ' | '\t')+;
WSX :   WS;
DTTOK   :   ('DT' WS TOKEN);
NPTOK   :   ('NP' WS TOKEN);
nounPhrase:  (DTTOK WSX NPTOK);
chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase+")");};

语法生成器生成“ missing attribute access on rule scope: nounPhrase “在最后一行。
[我对antlr还是一个新手,虽然有些语法可以工作,但它仍然是一种尝试和错误。在运行这么小的语法时,我也经常遇到“outofmemory”错误—欢迎任何帮助。]
我正在使用antlrworks1.3生成代码,并在java1.6下运行。

piah890a

piah890a1#

在最初的语法中,为什么不包括它所要求的属性,很可能是:

chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase.text+")");};

你的每一条规则( chunker 作为一个我可以很快发现)有属性(额外的信息)与他们相关。您可以在上找到不同类型规则的不同属性的快速列表http://www.antlr.org/wiki/display/antlr3/attribute+and+dynamic+scopes,如果在网页上对这些属性进行描述(比如解析器规则的start和stop属性引用来自lexer的标记,这将允许您返回行号和位置),那就太好了。
我认为你的chunker规则应该稍微改变一下,而不是 $nounPhrase 你应该使用 $nounPhrase.text . text 是您的 nounPhrase 规则。
您可能还需要执行一些其他格式化,通常解析器规则(以小写字母开头)出现在lexer规则(以大写字母开头)之前
另外,当我在框中输入时,chunker规则是从一个新行开始的,但在我原来的答案中,它没有从一个新行开始。

ztmd8pv5

ztmd8pv52#

如果你不小心做了些傻事 $thing.$attribute 你的意思是什么 $thing.attribute ,您还将看到 missing attribute access on rule scope 错误消息(我知道这个问题很久以前就有答案了,但这一点琐事可能会帮助其他看到错误消息的人!)

brjng4g3

brjng4g33#

在找到更好的方法后回答问题。。。

WS  :    (' '|'\t')+;
TOKEN   :   (('A'..'Z') | ('a'..'z'))+;
dttok   :   'DT' WS TOKEN;
nntok   :   'NN' WS TOKEN; 
nounPhrase :    (dttok WS nntok);
chunker :  nounPhrase ;

问题是我在词法分析器和语法分析器之间搞混了(这显然是很常见的)。大写项是词法的,在解析器中是小写的。现在看来这是可行的(注意,我已将np改为nn)。

jfgube3f

jfgube3f4#

“缺少属性访问”意味着您引用了一个范围( $nounPhrase )而不是范围的属性(例如 $nounPhrase.text ).
一般来说,解决属性问题的一个好方法是查看为所讨论的规则生成的解析器方法。
例如,当我有点生疏时,我最初尝试创建一个新规则:

multiple_names returns [List<Name> names]
@init {
    names = new ArrayList<Name>(4);
}
 : a=fullname ' AND ' b=fullname { names.add($a.value); names.add($b.value); };

导致“规则全名的未知属性”。所以我试过了

multiple_names returns [List<Name> names]
@init {
    names = new ArrayList<Name>(4);
}
 : a=fullname ' AND ' b=fullname { names.add($a); names.add($b); };

这将导致“缺少属性访问”。通过查看生成的解析器方法,我清楚地知道我需要做什么。虽然有一些神秘的部分,但与作用域(变量)相关的部分很容易理解:

public final List<Name> multiple_names() throws RecognitionException {
    List<Name> names = null;        // based on "returns" clause of rule definition
    Name a = null;                  // based on scopes declared in rule definition
    Name b = null;                  // based on scopes declared in rule definition
    names = new ArrayList<Name>(4); // snippet inserted from `@init` block

    try {
        pushFollow(FOLLOW_fullname_in_multiple_names42);
        a=fullname();
        state._fsp--;
        match(input,189,FOLLOW_189_in_multiple_names44); 
        pushFollow(FOLLOW_fullname_in_multiple_names48);
        b=fullname();
        state._fsp--;
        names.add($a); names.add($b);// code inserted from {...} block
    }
    catch (RecognitionException re) {
        reportError(re);
        recover(input,re);
    }
    finally {
        // do for sure before leaving
    }
    return names;                    // based on "returns" clause of rule definition
}

在查看生成的代码之后,很容易看出 fullname 规则正在返回 Name 同学们,所以在这个例子中我需要的只是:

multiple_names returns [List<Name> names]
@init {
    names = new ArrayList<Name>(4);
}
 : a=fullname ' AND ' b=fullname { names.add(a); names.add(b); };

在您的情况下,您需要的版本可能不同,但是通过查看生成的代码,您通常可以很容易地找到它。

相关问题