2009-11-02 10 views
6

Estoy tratando de construir una gramática antlr que analiza frases etiquetadas como:antlr: "falta de acceso atributo en alcance de una regla" problema

DT The NP cat VB ate DT a NP rat 

y tienen la gramática:

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 gramática generador genera el "missing attribute access on rule scope: nounPhrase" en la última línea.

[Sigo siendo nuevo en ANTLR y, aunque algunas gramáticas funcionan, sigue siendo de prueba y error. También recibo con frecuencia un error de "OutOfMemory" cuando ejecuto gramáticas tan pequeñas como esta, cualquier ayuda de bienvenida.]

Estoy usando ANTLRWorks 1.3 para generar el código y estoy corriendo bajo Java 1.6.

Respuesta

1

Respondiendo a la pregunta después de haber encontrado una mejor manera ...

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

El problema era que estaba recibiendo confusa entre el léxico y el analizador (esto es al parecer muy común). Los elementos en mayúsculas son léxicos, los minúsculos en el analizador. Esto ahora parece funcionar. (NB he cambiado NP a NN).

2

En la gramática original, por qué no incluir el atributo que está pidiendo, lo más probable:

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

Cada una de sus reglas (chunker siendo el que yo puedo detectar rápidamente) tienen atributos (información adicional) asociados con ellos. Puede encontrar una lista rápida de los diferentes tipos de reglas en http://www.antlr.org/wiki/display/ANTLR3/Attribute+and+Dynamic+Scopes, sería bueno si las descripciones se pusieran en la página web para cada uno de esos atributos (como para el atributo de inicio y detención para las reglas del analizador se refieren a tokens) de su Lexer, lo que le permitiría volver al número de línea y posición).

Creo que su regla de chunker solo debe cambiarse ligeramente, en lugar de $nounPhrase debe usar $nounPhrase.text. text es un atributo para su regla nounPhrase.

Es posible que desee hacer un poco de otra formateo, así, por lo general las reglas del analizador (comenzar con letra minúscula) aparecerá antes de las reglas analizadoras (empezar con letra mayúscula)

PS. Cuando escribo en el cuadro, la regla de chunker está comenzando en una nueva línea, pero en mi respuesta original no comenzó en una nueva línea.

+0

¿Podría aclarar más, por favor? No estoy seguro de qué es un atributo –

8

"falta de acceso atributo" significa que usted ha hecho referencia a un ámbito de aplicación ($nounPhrase) en lugar de un atributo de el alcance (como $nounPhrase.text).

En general, una buena forma de solucionar problemas con los atributos es observar el método del analizador generado para la regla en cuestión.

Por ejemplo, mi primer intento de crear una nueva regla cuando estaba un poco oxidado:

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

dio lugar a "atributo desconocido para el nombre completo regla".Así que traté

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

que se traduce en "falta de acceso atributo". Al observar el método del analizador generado, quedó claro lo que tenía que hacer. Si bien hay algunas piezas crípticos, las partes correspondientes a ámbitos (variables) son fáciles de entender:

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 
} 

Después de mirar el código generado, es fácil ver que la regla fullname está volviendo instancias de la clase Name, por lo lo que necesitaba en este caso era simplemente:

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

la versión que necesita en su situación puede ser diferente, pero tendrá por lo general será capaz de entenderlo muy fácilmente mirando el código generado.

1

Si accidentalmente hace algo tonto como $thing.$attribute donde se refiere a $thing.attribute, también verá el mensaje de error missing attribute access on rule scope. (Sé que esta pregunta fue respondida hace mucho tiempo, ¡pero este poco de trivia puede ayudar a alguien más a ver el mensaje de error!)

Cuestiones relacionadas