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

「missing attribute access」とは、スコープの属性( など$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にあります。これらの各属性のWebページ(パーサールールの開始属性と停止属性のように、レクサーからのトークンを参照します。これにより、行番号と位置に戻ることができます)。

$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 ;

問題は、レクサーとパーサーの間で混乱していたことです (これは明らかに非常に一般的です)。大文字の項目は語彙的であり、パーサーでは小文字です。これでうまくいくようです。(NB を NN に変更しました)。

于 2009-11-02T01:24:40.680 に答える