2009-11-02 14 views
6

Sto cercando di costruire una grammatica ANTLR che analizza frasi con tag come:ANTLR: "manca l'accesso attributo regola di ambito" problema

DT The NP cat VB ate DT a NP rat 

e hanno la grammatica:

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 grammatica generatore genera "missing attribute access on rule scope: nounPhrase" nell'ultima riga.

[Sono ancora nuovo su ANTLR e sebbene alcune grammatiche funzionino, è ancora una prova ed un errore. Ricevo spesso un errore "OutOfMemory" quando eseguo grammatiche così piccole - qualsiasi aiuto sia benvenuto.]

Sto usando ANTLRWorks 1.3 per generare il codice e sto funzionando con Java 1.6.

risposta

1

Rispondendo alla domanda, dopo aver trovato un modo migliore ...

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

Il problema era che stavo ottenendo confuso tra il lexer e il parser (questo è apparentemente molto comune). Gli elementi maiuscoli sono lessicali, i caratteri minuscoli nel parser. Questo ora sembra funzionare. (NB Ho cambiato NP in NN).

2

Nella grammatica originale, perché non includere l'attributo si sta chiedendo, molto probabilmente:

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

Ognuna delle vostre regole (chunker essere quello che posso individuare rapidamente) hanno attributi (informazioni supplementari) associati con loro. Puoi trovare un rapido elenco dei diversi attributi per i diversi tipi di regole a http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes, sarebbe bello se le descrizioni fossero inserite nella pagina web per ciascuno di quegli attributi (come per l'attributo start e stop per le regole del parser si riferiscono ai token dal tuo lexer - che ti permetterebbe di tornare al tuo numero di linea e posizione).

Penso che la regola del chunker debba essere modificata leggermente, invece di $nounPhrase dovresti usare $nounPhrase.text. text è un attributo per la tua regola nounPhrase.

Si potrebbe desiderare di fare un po 'di altra formattazione così, di solito le regole del parser (iniziare con la lettera minuscola) comparire di fronte alle regole lexer (Iniziamo con lettera maiuscola)

PS. Quando digito nella casella la regola chunker inizia su una nuova riga ma nella mia risposta originale non è iniziata su una nuova riga.

+0

Potresti chiarire ulteriormente, per favore? Non sono sicuro di cosa sia un attributo –

8

"mancante accesso attributo" significa che hai fatto riferimento un ambito ($nounPhrase), piuttosto che un attributo del il campo di applicazione (come ad esempio $nounPhrase.text).

In generale, un buon metodo per risolvere i problemi con gli attributi consiste nell'esaminare il metodo parser generato per la regola in questione.

Ad esempio, il mio primo tentativo di creare una nuova regola, quando ero un po 'arrugginito:

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

provocato "attributo sconosciuto per la regola fullname".Così ho provato

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

che si traduce in "manca l'accesso all'attributo". Guardando il metodo del parser generato, ho chiarito cosa dovevo fare comunque. Mentre ci sono alcuni pezzi criptici, alle parti pertinenti a raggi (variabili) sono facilmente comprensibili:

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 
} 

Dopo aver guardato il codice generato, è facile vedere che la regola fullname sta tornando istanze della classe Name, così quello che mi serviva in questo caso era semplice:

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

la versione è necessario nella vostra situazione potrebbe essere diversa, ma sarete generalmente in grado di capirlo abbastanza facilmente guardando il codice generato.

1

Se accidentalmente fai qualcosa di sciocco come $thing.$attribute dove intendi $thing.attribute, vedrai anche il messaggio di errore missing attribute access on rule scope. (So ​​che a questa domanda è stata data risposta molto tempo fa, ma questo bit di trivia potrebbe aiutare qualcun altro che vede il messaggio di errore!)

Problemi correlati