2012-03-07 12 views
5

Sé '+', '?' y '*'. Pero, ¿y si quiero que algo se repita, por ejemplo, 5 veces? Por ejemplo, si un identificador debe ser una cadena de números hexadecimales de longitud 5?cómo definir una regla de un patrón repetido por un número fijo de veces usando la gramática antlr

Para ser más específicos, estoy pensando en definir una regla general de lexer de longitud ilimitada, y luego, en el tiempo de análisis, contar cuántas veces se repite, si es igual a 5, cambiarle el nombre a otro tipo de token pero, ¿cómo puedo hacer esto? ¿O hay alguna manera fácil?

Respuesta

4

en tiempo de análisis cuente cuántas veces se repitió, si es igual a 5, luego renómbrelo como otro tipo de token, pero ¿cómo puedo hacer esto? ¿O hay alguna manera fácil?

Sí, se puede hacer eso con un desambiguantes predicado semántico (explanation):

grammar T; 

parse 
: (short_num | long_num)+ EOF 
; 

short_num 
: {input.LT(1).getText().length() == 5}? NUM 
; 

long_num 
: {input.LT(1).getText().length() == 8}? NUM 
; 

NUM 
: '0'..'9'+ 
; 

SP 
: ' ' {skip();} 
; 

que analiza la entrada 12345 12345678 de la siguiente manera:

enter image description here

Pero también puede cambiar el tipo de token en el lexer en función de alguna propiedad del texto coincidente , De esta manera:

grammar T; 

parse 
: (SHORT | LONG)+ EOF 
; 

NUM 
: '0'..'9'+ 
    { 
    if(getText().length() == 5) $type = SHORT; 
    if(getText().length() == 8) $type = LONG; 
    // when the length is other than 5 or 8, the type of the token will stay NUM 
    } 
; 

SP 
: ' ' {skip();} 
; 

fragment SHORT : ; 
fragment LONG : ; 

lo que hará que la misma entrada que ser analizado como esto:

enter image description here

+0

Gracias, probé el segundo método. Exactamente lo que estoy buscando. – safarisoul

1

Es necesario especificar que 5 veces, por ejemplo:

ZIPCODE: '0'..'9' '0'..'9' '0'..'9' '0'..'9' '0'..'9'; 

Como alternativa, puede utilizar un predicado validación semántica:

DIGIT: '0'..'9'; 
zipcode 
@init { int N = 0; } 
    : (DIGIT { N++; })+ { N <= 5 }? 
    ; 

Ver: What is a 'semantic predicate' in ANTLR?

+0

Hola, esto funciona en el Analizador gramática. ¿Es posible hacerlo en la gramática Lexer? – safarisoul

+0

Bien, ya lo tengo funcionando en la gramática de Lexer. Pero solo puedo tener una de esas reglas. ¿Es posible si quiero nombrar un token de longitud 5 como CORTO, y al mismo tiempo nombrar un token de longitud 8 como LARGO? Queja de Antlr "Las siguientes definiciones de tokens nunca pueden coincidir". – safarisoul

+0

Quiero decir, de esta manera, ¿cada vez que {}? evaluado como falso, esos personajes serán ignorados, pero quiero que el lexer verifique otras coincidencias potenciales. – safarisoul

Cuestiones relacionadas