8

我正在尝试构建一个 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”错误 - 欢迎任何帮助。]

我正在使用 ANTLRWorks 1.3 生成代码并在 Java 1.6 下运行。

4

4 回答 4

11

“缺少属性访问”意味着您引用了范围 ( $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); };

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

于 2011-08-29T20:58:29.340 回答
4

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

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

您的每条规则(chunker我可以快速发现的规则)都有与之相关的属性(额外信息)。您可以在http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes 找到不同类型规则的不同属性的快速列表,如果在每个属性的网页(例如解析器规则的开始和停止属性引用来自词法分析器的标记 - 这将允许您返回行号和位置)。

我认为你的分块规则应该稍微改变一下,而不是$nounPhrase你应该使用$nounPhrase.text. text是您的nounPhrase规则的属性。

您可能还想做一些其他格式,通常解析器规则(以小写字母开头)出现在词法分析器规则之前(以大写字母开头)

PS。当我在框中键入时,分块规则从新行开始,但在我原来的答案中,它没有从新行开始。

于 2009-11-12T04:04:39.040 回答
1

如果您不小心做了一些愚蠢的事情,就像$thing.$attribute您的意思一样$thing.attribute,您也会看到missing attribute access on rule scope错误消息。(我知道这个问题很久以前就已经回答过了,但是这个琐事可能会帮助其他看到错误消息的人!)

于 2013-11-27T21:41:06.693 回答
0

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

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

问题是我在词法分析器和解析器之间感到困惑(这显然很常见)。大写的项目是词法的,小写的项目在解析器中。现在这似乎奏效了。(注意我已将 NP 更改为 NN)。

于 2009-11-02T01:24:40.680 回答