ANTLR:「ルールスコープの属性のアクセスが不足している」問題
質問
私は、次のようなタグ付けされた文章を解析し、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に新しいですし、いくつかの文法は、それはまだ試行錯誤の仕事が。 Iこれほどの小さな文法を実行しているときも、頻繁に「のOutOfMemory」エラーが出る - 。任意のヘルプ歓迎]
私はコードを生成するANTLRWorks 1.3を使用していますし、Java 1.6の下で実行しています。
解決 4
...より良い方法を発見した後、質問に答えます
WS : (' '|'\t')+;
TOKEN : (('A'..'Z') | ('a'..'z'))+;
dttok : 'DT' WS TOKEN;
nntok : 'NN' WS TOKEN;
nounPhrase : (dttok WS nntok);
chunker : nounPhrase ;
問題は、私は(これは明らかに非常に一般的です)レクサーとパーサの間で混乱ばかりでした。大文字の項目は、パーサで小文字の語彙です。これは、今動作しているようです。 (NB私はNNにNPを変更しました)。
他のヒント
"不足している属性へのアクセス" あなたではなく(例えば$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); };
あなたがあなたの状況で必要なバージョンが異なる場合がありますが、あなたは一般的に生成されたコードを見て、かなり簡単にそれを把握することができるでしょう。
オリジナルの文法では、なぜそれが求めている属性、最も可能性が高いが含まれていません
chunker : nounPhrase {System.out.println("chunk found "+"("+$nounPhrase.text+")");};
あなたのルール(chunker
が、私はすぐに見つけることができるものである)のそれぞれは、それらに関連付けられた属性(追加情報)を持っています。あなたは<のhref =「http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes」のrel = "nofollowをでのルールの種類ごとに異なる属性の簡単なリストを見つけることができます説明はのためのような(それらの属性ごとにウェブページに置かれた場合noreferrer "> http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes のは、いいだろう開始とパーサールールの属性を止めるには、あなたのレクサーからのトークンを参照してください - あなたの行番号と位置)に戻って取得することが可能と思われる。
私はあなたのチャンカルールがだけではなく、あなたが$nounPhrase
を使用する必要があり$nounPhrase.text
の、若干変更されるべきだと思います。 text
は、あなたのnounPhrase
ルールの属性です。
あなたは(大文字で始まり)レクサールールの前に表示されるだけでなく、通常はパーサー規則は、(小文字で始まる)少し他の整形をしたいかもしれません。
PS。私はボックスに入力するとチャンカルール新しい行で開始しているが、私の元の答えに、それは新しい行で開始されませんでした。
$thing.$attribute
を意味$thing.attribute
のような愚かな何かをする場合は、、あなたもmissing attribute access on rule scope
のエラーメッセージが表示されます。 (私はこの質問は長い時間前に答えた知っているが、トリビアのこのビットがエラーメッセージを見て他の誰かを助けるかもしれない!)