我正在尝试建立一个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下运行。
最佳答案
“缺少属性访问权限”意味着您引用了一个范围($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); };
您所需要的版本可能会有所不同,但是通常您可以通过查看生成的代码来很容易地弄清楚它。