Как сопоставить строку, но без учета регистра?
Вопрос
Допустим, я хочу сопоставить "пиво", но меня не волнует чувствительность к регистру.
В настоящее время я определяю токен как ('b' | 'B' 'e' | 'E' 'e' | 'E' 'r' | 'R'), но у меня их много, и я действительно не хочу обрабатывать 'verilythisisaverylongtokenindeedomyesitis'.
antlr - вики кажется, это наводит на мысль, что это невозможно сделать (в antlr) ...но мне просто интересно , есть ли у кого - нибудь какие - нибудь хитрые трюки ...
Решение
Как насчет определения токена лексера для каждого допустимого символа идентификатора, а затем построения токена синтаксического анализатора в виде серии из них?
beer: B E E R;
A : 'A'|'a';
B: 'B'|'b';
и т.д.
Другие советы
Я хотел бы добавить к принятому ответу:готовый набор можно найти по адресу строительные блоки antlr без учета регистра, и соответствующая часть включена ниже для удобства
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');
Итак, примером является
HELLOWORLD : H E L L O W O R L D;
Определите токены без учета регистра с помощью
BEER: [Bb] [Ee] [Ee] [Rr];
В репозитории ANTLR на GitHub появилась новая страница документации: Лексика без учета регистра.Вы можете использовать два подхода:
- Тот, который описан в ответе @javadba
- Или добавьте поток символов в свой код, который преобразует входной поток в нижний или верхний регистр.Примеры для основных языков вы можете найти на той же странице документа.
Мое мнение, лучше использовать первый подход и иметь грамматику, которая описывает все правила.Но если вы используете хорошо известную грамматику, например, из Грамматики , написанные для ANTLR v4, тогда второй подход может быть более подходящим.
Решение, которое я использовал в C#:используйте код ASCII для перевода символа в меньший регистр.
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;
}
}