antlr - ¿Cómo hacer coincidir una cadena, pero sin distinción de mayúsculas y minúsculas?
antlr3 (5)
Digamos que quiero unir "cerveza", pero no me importa la sensibilidad a las mayúsculas.
Actualmente estoy definiendo un token para que sea (''b'' | ''B'' ''e'' | ''E'' ''e'' | ''E'' ''r'' | ''R''), pero tengo mucho de eso y realmente no Quiero manejar ''en verdad, una crisis muy larga en una misa de la sinagitis''.
El wiki de antlr parece sugerir que no se puede hacer (en antlr) ... pero me pregunté si alguien tenía algunos trucos inteligentes ...
¿Qué tal definir un token lexer para cada carácter de identificador permisible, luego construir el token del analizador como una serie de esos?
beer: B E E R;
A : ''A''|''a'';
B: ''B''|''b'';
etc.
Definir tokens insensibles a mayúsculas y minúsculas con
BEER: [Bb] [Ee] [Ee] [Rr];
La nueva página de documentación ha aparecido en el repositorio de ANTLR GitHub: Lexing insensible a mayúsculas y minúsculas . Puede utilizar dos enfoques:
- El descrito en la respuesta de @javadba.
- O agregue un flujo de caracteres a su código, que transformará un flujo de entrada a mayúsculas o minúsculas. Ejemplos de los principales idiomas que puedes encontrar en la misma página de documentos.
Mi opinión, es mejor usar el primer enfoque y tener la gramática que describe todas las reglas. Pero si usa una gramática conocida, por ejemplo, de gramáticas escritas para ANTLR v4 , el segundo enfoque puede ser más apropiado.
Me gustaría agregar a la respuesta aceptada: se puede encontrar un conjunto ya hecho en bloques de construcción antlr insensibles a mayúsculas , y la parte relevante incluida a continuación para su comodidad.
fragment A:(''a''|''A'');
fragment B:(''b''|''B'');
fragment C:(''c''|''C'');
fragment D:(''d''|''D'');
fragment E:(''e''|''E'');
fragment F:(''f''|''F'');
fragment G:(''g''|''G'');
fragment H:(''h''|''H'');
fragment I:(''i''|''I'');
fragment J:(''j''|''J'');
fragment K:(''k''|''K'');
fragment L:(''l''|''L'');
fragment M:(''m''|''M'');
fragment N:(''n''|''N'');
fragment O:(''o''|''O'');
fragment P:(''p''|''P'');
fragment Q:(''q''|''Q'');
fragment R:(''r''|''R'');
fragment S:(''s''|''S'');
fragment T:(''t''|''T'');
fragment U:(''u''|''U'');
fragment V:(''v''|''V'');
fragment W:(''w''|''W'');
fragment X:(''x''|''X'');
fragment Y:(''y''|''Y'');
fragment Z:(''z''|''Z'');
Así que un ejemplo es
HELLOWORLD : H E L L O W O R L D;
Una solución que usé en C #: use el código ASCII para cambiar el carácter a un caso más pequeño.
class CaseInsensitiveStream : Antlr4.Runtime.AntlrInputStream {
public CaseInsensitiveStream(string sExpr)
: base(sExpr) {
}
public override int La(int index) {
if(index == 0) return 0;
if(index < 0) index++;
int pdx = p + index - 1;
if(pdx < 0 || pdx >= n) return TokenConstants.Eof;
var x1 = data[pdx];
return (x1 >= 65 && x1 <= 90) ? (97 + x1 - 65) : x1;
}
}