2012-03-07 5 views
5

Conosco '+', '?' e '*'. Ma cosa succede se voglio qualcosa si ripete per, diciamo, 5 volte? Ad esempio, se un identificatore deve essere una stringa di numeri esadecimali di lunghezza 5?come definire una regola di un pattern ripetuta da un numero fisso di volte usando la grammatica antlr

Per essere più specifici, sto pensando di definire una regola lexer generale di lunghezza illimitata, e quindi, al tempo di analisi conta quante volte ha ripetuto, se è uguale a 5, quindi rinominala come un altro tipo di token , ma come posso fare questo? O c'è un modo semplice?

risposta

4

al tempo di analisi conta quante volte ha ripetuto, se è uguale a 5, quindi rinominalo come un altro tipo di token, ma come posso farlo? O c'è un modo semplice?

Sì, è possibile farlo con un disambiguazione predicato semantico (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();} 
; 

che analizzare l'input 12345 12345678 come segue:

enter image description here

Ma voi può anche cambiare il tipo di token nel lexer in base ad alcune proprietà del testo corrispondente , In questo modo:

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 : ; 

che farà sì che lo stesso ingresso da analizzare in questo modo:

enter image description here

+0

Grazie, ho provato il secondo metodo. Esattamente quello che sto cercando. – safarisoul

1

è necessario specificare 5 volte, per esempio:

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

In alternativa, è possibile utilizzare un predicato validazione semantica:

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

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

+0

Salve, questo funziona in Parser grammatica. È possibile farlo nella grammatica di Lexer? – safarisoul

+0

Ok, ho finito con la grammatica di Lexer. Ma posso avere solo una regola del genere. È possibile se voglio nominare un tale token di lunghezza 5 come SHORT, e allo stesso tempo nominare un tale token di lunghezza 8 come LONG? Reclamo di Antlr "Le seguenti definizioni di token non possono mai essere abbinate". – safarisoul

+0

Intendo, in questo modo, ogni volta che {}? valutato come falso, quei caratteri saranno ignorati, ma voglio che il lexer controlli altre potenziali corrispondenze. – safarisoul