2012-01-26 17 views
5

Consulte el código fuente disponible en: https://gist.github.com/1684022.¿La forma correcta de resolver las ambigüedades de la regla LExer ANTLR?

Tengo dos fichas definidas:

ID : ('a'..'z' | 'A'..'Z') ('0'..'9' | 'a'..'z' | 'A'..'Z' | ' ')*; 

PITCH 
    : (('A'|'a') '#'?) 
    | (('B'|'b') '#'?) 
    | (('C'|'c') '#'?); 

Obviamente, la letra "A" sería una ambigüedad.

defino más:

note : PITCH; 
name : ID; 
main : name ':' note '\n'? 

Ahora, si entro en "A: A" como entrada para el analizador, siempre me sale un error. O bien, el analizador espera TONO o ID en función de si o ID de tono depende en primer lugar:

mismatched input 'A' expecting ID 

¿Cuál es la forma correcta de resolver este modo que funcione como se pretende?


Como se describe, a pesar de que tiene un sentido intuitivo de cómo el análisis debería funcionar, antlr no hace lo "correcto". Es decir, aunque la regla main dice que un name/ID debe ser lo primero, el lexer parece ignorar esto e identifica "A" como PITCH porque sigue la regla de "coincidencia más larga"/"que viene primero" en lugar de la regla más razonable de "lo que dice la regla".

¿Es la única solución para falsificarlo/hackearlo haciendo coincidir ID y PITCH, y luego recombinándolos más tarde como dice dasblinkenlight?

+0

Sí. ¿Qué tiene que ver el espacio con la pregunta? – Ana

+1

Mira, Bart. Si entiendo o no a ANTLR, el punto por el que sigues insistiendo es irrelevante. Estoy buscando una solución que tenga sentido y aunque hayas proporcionado una respuesta y cuatro comentarios, ninguno de ellos es una solución, solo comentarios sobre mi publicación o mi comprensión. Si entiendes ANTLR y entiendes mi problema mejor que yo, entonces publica una solución real. – Ana

Respuesta

4

Aquí es cómo iba a volver a factor de esta gramática para que funcione:

ID : (('a'..'z' | 'A'..'Z') ('0'..'9' | 'a'..'z' | 'A'..'Z' | ' ')+) 
    | ('d'..'z' | 'D'..'Z'); 

PITCH : 'a'..'c' | 'A'..'C'; 

SHARP : '#'; 

note : PITCH SHARP?; 

name : ID | PITCH; 

main : name ':' note '\n'? EOF 

Esto separa los nombres largos de nombres de las notas de un solo carácter, que se obtiene "reunidos" en el analizador. Además, el token "nítido" tiene su propio nombre y se reconoce en el analizador como un token opcional.

+0

Gracias, dasblinkenlight. Lo aprecio. Esperaba que hubiera una manera más limpia, pero esto servirá. – Ana

+0

@Ana Este es el enfoque estándar de ANTLR para permitir el uso de palabras clave como identificadores. En su caso, 'PITCH' desempeña el papel de una" palabra clave ", mientras que los identificadores siguen siendo identificadores. – dasblinkenlight

Cuestiones relacionadas