2009-11-02 2 views
6

Je suis en train de construire une grammaire ANTLR qui parse phrases taggé comme:ANTLR: « manque d'accès d'attribut sur la portée de la règle » problème

DT The NP cat VB ate DT a NP rat 

et ont la grammaire:

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+")");}; 

La grammaire Le générateur génère le "missing attribute access on rule scope: nounPhrase" dans la dernière ligne.

[Je suis encore nouveau à ANTLR et bien que certaines grammaires fonctionnent, il s'agit encore d'essais et d'erreurs. Je reçois également souvent une erreur "OutOfMemory" lors de l'exécution de grammaires aussi petites que cela - toute aide bienvenue.]

J'utilise ANTLRWorks 1.3 pour générer le code et je cours sous Java 1.6.

Répondre

1

Répondre à la question après avoir trouvé une meilleure façon ...

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

Le problème était que je commençais à me emmêlées le lexer et l'analyseur (ce qui est apparemment très fréquent). Les éléments majuscules sont lexicaux, les minuscules dans l'analyseur. Cela semble maintenant fonctionner. (NB J'ai changé NP à NN).

2

Dans la Grammer originale, pourquoi ne pas inclure l'attribut il demande, le plus probable:

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

Chacune de vos règles (chunker étant celui que je peux repérer rapidement) ont des attributs (informations supplémentaires) associés avec eux. Vous pouvez trouver une liste rapide des différents attributs pour les différents types de règles au http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes, ce serait bien si des descriptions étaient placées sur la page web pour chacun de ces attributs (comme pour l'attribut start et stop pour les règles d'analyseur référez-vous aux jetons de votre lexer - ce qui vous permettrait de revenir à votre numéro de ligne et votre position).

Je pense que votre règle de chunker devrait juste être légèrement modifiée, au lieu de $nounPhrase vous devriez utiliser $nounPhrase.text. text est un attribut de votre règle nounPhrase.

Vous voudrez peut-être faire un peu autre formattage et, généralement les règles de l'analyseur (en commençant par lettre minuscule) apparaissent avant les règles analyseurs lexicaux (en commençant par la lettre majuscule)

PS. Lorsque je tape dans la case, la règle du chunker commence sur une nouvelle ligne mais dans ma réponse d'origine, elle ne commence pas sur une nouvelle ligne.

+0

Pourriez-vous nous éclairer davantage, s'il vous plaît? Je ne suis pas sûr de ce qu'est un attribut –

8

« manque d'accès d'attribut » signifie que vous avez fait référence à une portée ($nounPhrase) plutôt qu'un attribut de la portée (comme $nounPhrase.text).

En général, un bon moyen de résoudre les problèmes liés aux attributs consiste à examiner la méthode de l'analyseur générée pour la règle en question.

Par exemple, ma première tentative de création d'une nouvelle règle quand j'étais un peu rouillé:

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); }; 

a donné lieu à « attribut inconnu pour la règle fullname ».J'ai donc essayé

multiple_names returns [List<Name> names] 
@init { 
    names = new ArrayList<Name>(4); 
} 
: a=fullname ' AND ' b=fullname { names.add($a); names.add($b); }; 

qui se traduit par "manque accès aux attributs". En regardant la méthode de l'analyseur syntaxique générée, j'ai clairement compris ce que je devais faire. Bien qu'il existe des pièces énigmatiques, les parties pertinentes aux étendues (variables) sont faciles à comprendre:

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 
} 

Après avoir regardé le code généré, il est facile de voir que la règle fullname retourne les instances de la classe Name, donc ce que je avais besoin dans ce cas était tout simplement:

multiple_names returns [List<Name> names] 
@init { 
    names = new ArrayList<Name>(4); 
} 
: a=fullname ' AND ' b=fullname { names.add(a); names.add(b); }; 

la version dont vous avez besoin dans votre situation peut être différente, mais vous serez généralement en mesure de le comprendre assez facilement en regardant le code généré.

1

Si vous faites accidentellement quelque chose de stupide comme $thing.$attribute où vous voulez dire $thing.attribute, vous verrez également le message d'erreur missing attribute access on rule scope. (Je sais que cette question a été répondue il y a longtemps, mais cette petite histoire pourrait aider quelqu'un d'autre qui voit le message d'erreur!)