我正在尝试构建一个解析标记句子的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下运行。
答案 0 :(得分:9)
“缺少属性访问权限”表示您引用了范围($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); };
您所需的版本可能会有所不同,但您通常可以通过查看生成的代码轻松搞清楚。
答案 1 :(得分:3)
在原始语法中,为什么不包括它要求的属性,最有可能:
chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase.text+")");};
您的每个规则(chunker
是我能够快速发现的规则)都具有与之关联的属性(额外信息)。您可以在http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes找到不同类型规则的不同属性的快速列表,如果在网页上为每个属性添加了描述(例如解析器的start和stop属性),那将会很好规则是指你的词法分析器中的标记 - 这将允许你回到你的行号和位置。
我认为您的chunker规则应该略有改动,而不是$nounPhrase
您应该使用$nounPhrase.text
。 text
是nounPhrase
规则的属性。
你可能也希望做一些其他的格式化,通常解析器规则(以小写字母开头)出现在词法分析器规则之前(以大写字母开头)
PS。当我在框中输入时,chunker规则从一个新行开始,但在我的原始答案中,它并没有从一个新行开始。
答案 2 :(得分:1)
如果你不小心做了$thing.$attribute
,你的意思是$thing.attribute
,你也会看到missing attribute access on rule scope
错误消息。 (我知道很久以前这个问题得到了解答,但这一点琐事可能会帮助那些看到错误信息的人!)
答案 3 :(得分:0)
找到更好的方法后回答问题......
WS : (' '|'\t')+;
TOKEN : (('A'..'Z') | ('a'..'z'))+;
dttok : 'DT' WS TOKEN;
nntok : 'NN' WS TOKEN;
nounPhrase : (dttok WS nntok);
chunker : nounPhrase ;
问题是我在词法分析器和解析器之间变得混乱(这显然很常见)。大写的项是词法,解析器中的小写。这似乎现在有效。 (注意我已将NP更改为NN)。