假设我想匹配“啤酒”,但不关心大小写。
目前我将一个标记定义为 ('b'|'B' 'e'|'E' 'e'|'E' 'r'|'R') 但我有很多这样的标记并且没有真的很想处理“verilythisisaverylongtokenindeedomyesitis”。
antlr wiki 好像提示说做不到(在antlr中)...但是我只是想知道有没有人有一些聪明的技巧...
我想补充一下已接受的答案:可以在case insensitive antlr building blocks找到现成的集合,为了方便起见,相关部分包含在下面
fragment A:[aA];
fragment B:[bB];
fragment C:[cC];
fragment D:[dD];
fragment E:[eE];
fragment F:[fF];
fragment G:[gG];
fragment H:[hH];
fragment I:[iI];
fragment J:[jJ];
fragment K:[kK];
fragment L:[lL];
fragment M:[mM];
fragment N:[nN];
fragment O:[oO];
fragment P:[pP];
fragment Q:[qQ];
fragment R:[rR];
fragment S:[sS];
fragment T:[tT];
fragment U:[uU];
fragment V:[vV];
fragment W:[wW];
fragment X:[xX];
fragment Y:[yY];
fragment Z:[zZ];
举个例子
HELLOWORLD : H E L L O W O R L D;
如何为每个允许的标识符字符定义一个词法分析器标记,然后将解析器标记构造为一系列这些标记?
beer: B E E R;
A : 'A'|'a';
B: 'B'|'b';
等
ANTLR 刚刚添加了一个不区分大小写的选项
options { caseInsensitive = true; }
https://github.com/antlr/antlr4/blob/master/doc/options.md#caseinsensitive
旧链接现已断开,这些应该继续有效。
用
定义不区分大小写的标记BEER: [Bb] [Ee] [Ee] [Rr];
ANTLR GitHub 存储库中出现了新的文档页面:Case-Insensitive Lexing。您可以使用两种方法:
我认为,最好使用第一种方法并拥有描述所有规则的语法。但是如果你使用众所周知的语法,例如 Grammars written for 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;
}
}