2012-01-26 9 views
5

Si prega di consultare il codice sorgente disponibile a: https://gist.github.com/1684022.Modo corretto per risolvere le ambiguità delle regole del lexer ANTLR?

Ho due token definiti:

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

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

Ovviamente, la lettera "A" sarebbe un equivoco.

I definire ulteriormente:

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

Ora, se entro "A: A" come input per il parser, ho sempre arrivare un errore. O il parser si aspetta PITCH o ID a seconda se ID o PITCH è definita in primo luogo:

mismatched input 'A' expecting ID 

Qual è il modo corretto per risolvere questo in modo che funzioni come previsto?


Come è descritto, anche se ha un senso intuitivo come l'analisi dovrebbe funzionare, ANTLR non fa la "cosa giusta". Cioè, anche se la regola main dice un name/ID dovrebbe venire prima, il lexer sembra essere ignorante di questo e identifica "A" come PITCH perché segue la regola "più lunga corrispondenza"/"che viene prima" piuttosto che più ragionevole è la regola "ciò che la regola dice".

È l'unica soluzione per simulare/hackerare corrispondendo sia ID e PITCH, e quindi ricombinarli in seguito come dice dasblinkenlight?

+0

Sì. Cosa c'entra lo spazio con la domanda? – Ana

+1

Guarda, Bart. Che io comprenda o meno l'ANTLR, il punto su cui continui a discutere, è irrilevante. Sto cercando una soluzione che abbia senso e sebbene tu abbia fornito una risposta e quattro commenti, nessuno di essi è una soluzione, solo un commento sul mio post o la mia comprensione. Se comprendi ANTLR e capisci meglio il mio problema, allora pubblica una soluzione reale. – Ana

risposta

4

Ecco come vorrei ri-fattore di questa grammatica per farlo funzionare:

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 

Questo separa i nomi lunghi dai nomi passo di un carattere, che vengono "riuniti" nel parser. Anche il token "sharp" ottiene il proprio nome e viene riconosciuto nel parser come token opzionale.

+0

Grazie, dasblinkenlight. Apprezzalo. Speravo che ci fosse un modo più pulito, ma questo lo farà. – Ana

+0

@Ana Questo è l'approccio standard di ANTLR per consentire l'uso di parole chiave come identificatori. Nel tuo caso, 'PITCH' ha il ruolo di una" parola chiave ", mentre gli identificatori rimangono identificatori. – dasblinkenlight

Problemi correlati