2010-01-31 12 views
5

Tengo lo que creo que es una simple pregunta ANTLR. Tengo dos tipos de tokens: ident y special_ident. Quiero que mi special_ident coincida con una sola letra seguida de un solo dígito. Quiero que el ident genérico coincida con una sola letra, seguido opcionalmente por cualquier número de letras o dígitos. Mi (incorrecta) gramática es a continuación:¿Cómo puede mi ANTLR lexer hacer coincidir un token hecho de caracteres que son subconjunto de otro tipo de token?

expr 
    : special_ident 
    | ident 
    ; 

special_ident : LETTER DIGIT; 
ident   : LETTER (LETTER | DIGIT)*; 

LETTER : 'A'..'Z'; 
DIGIT : '0'..'9'; 

Cuando intento para comprobar esta gramática, consigo esta advertencia:

Decisión puede coincidir con la entrada como "Cifra Letra" utilizando múltiples alternativas: 1, 2. como resultado, alternativa (s) 2 eran discapacitados para esa entrada

entiendo que mi gramática es ambigua y que de entrada como A1 podría coincidir con cualquiera ident o special_ident. Realmente solo quiero que el special_ident se use en el más estrecho de los casos.

Aquí hay algo de entrada de la muestra y lo que me gustaría que al partido:

A  : ident 
A1  : special_ident 
A1A : ident 
A12 : ident 
AA1 : ident 

¿Cómo puedo formar mi gramática I tal que me identifico correctamente mis dos tipos de identificadores?

Respuesta

2

Ampliando el pensamiento de Carl, yo supongo que tiene cuatro casos diferentes:

  1. Un
  2. UN
  3. AA (A | N) *
  4. UN (A | N) +

sólo OP la 2 debe ser un token special_ident y las otras tres deben ser ident. Todos los tokens se pueden identificar solo por sintaxis. Aquí hay una gramática rápida que pude probar en ANTLRWorks y me pareció que funcionaba correctamente. Creo que Carl podría tener un error al tratar de verificar AA, pero obtener un 99% es un gran beneficio, por lo que esta es solo una pequeña modificación a su pensamiento rápido.

prog 
    : (expr WS)+ EOF; 

expr 
    : special_ident {System.out.println("Found special_ident:" + $special_ident.text + "\n");} 
    | ident {System.out.println("Found ident:" + $ident.text + "\n");} 
    ; 

special_ident : LETTER DIGIT; 

ident   : LETTER 
    |LETTER DIGIT (LETTER|DIGIT)+ 
    |LETTER LETTER (LETTER|DIGIT)*; 

LETTER : 'A'..'Z'; 
DIGIT : '0'..'9'; 
WS 
    : (' '|'\t'|'\n'|'\r')+; 
+0

Gracias ... Creo que todo esto tiene más sentido. ¿La última opción en 'ident' es redundante? ¿No 'CARTA DE LETRA' haría que toda la regla sea equivalente? Además, ¿sería equivalente para toda la regla decir 'LETTER LETTER?| LETRA DIGIT (LETRA | DIGIT) + '? –

+0

Hay varias maneras diferentes en que puede tener las reglas (creo), solo me estaba asegurando de que la LETRA DIGIT tenga otra letra o un dígito después para separarla de la regla special_ident. La opción LETTER LETTER ya no requiere más tokens. Es por eso que uno tiene un signo más y el otro tiene el asterisco. – WayneH

3

Parece que tiene 3 casos:

  • A
  • AN
  • A(A|N)(A|N)+

Se podría clasificar como un medio special_ident y los otros dos como ident; parece que debería hacer el truco.

Estoy un poco oxidado con ANTLR, espero que esta pista sea suficiente. Puedo tratar de escribir las expresiones para usted, pero que podría estar equivocado:

long_ident : LETTER (LETTER | DIGIT) (LETTER | DIGIT)+ 
special_ident : LETTER DIGIT; 
ident   : LETTER | long_ident; 
Cuestiones relacionadas