YaccLexTools 0.2.2(GPLEX1.2.1)如何定义不区分大小写的令牌?
解决GPLEX 1.2.1(YaccLexTools 0.2.2)中不区分大小写令牌的优雅方案
我之前也踩过GPLEX不支持%option caseless和(?i:)正则选项的坑,你现在逐个字母写大小写的临时方案确实太繁琐,后期维护很容易出错。这里有几个更实用的替代方案,能帮你简化代码:
1. 用字符类简化写法
虽然核心思路和你当前的方法类似,但可以用GPLEX支持的字符类语法让代码更紧凑,比如:
Seconds [Ss][Ee][Cc][Oo][Nn][Dd][Ss] Second [Ss]([Ee][Cc][Oo][Nn][Dd])?
这种写法省去了冗余的括号,可读性也更好,适合短单词令牌的场景。
2. 自定义宏复用大小写逻辑
如果有大量不区分大小写的令牌,你可以定义一个宏来生成单字符的大小写匹配规则,减少重复代码:
%macro caseless(ch) {[ch\l\u]} # 用宏定义令牌 Seconds {caseless(S)}{caseless(E)}{caseless(C)}{caseless(O)}{caseless(N)}{caseless(D)}{caseless(S)} Second {caseless(S)}{caseless(E)}{caseless(C)}{caseless(O)}{caseless(N)}{caseless(D)}
宏的方式让你不用每次手动写大小写字母,后续要调整匹配逻辑时,只需要修改宏的定义即可,维护成本低很多。
3. 预处理统一转换输入大小写(推荐)
这是最优雅的解决方案——在GPLEX处理输入前,把所有字符转换成小写(或大写),这样规则里只需要写统一大小写的字符串即可。你可以通过重载输入函数实现:
%{ // 重载yyinput,将输入字符统一转成小写 int yyinput() { int c = yyFlexLexer::yyinput(); return (c == EOF) ? c : tolower(c); } %} # 现在规则里直接写小写形式即可 Seconds "seconds" Second "second"
这个方法彻底解决了大小写匹配的问题,不管令牌多长都不需要额外处理,代码最简洁。如果你的语法里同时存在区分大小写的令牌,只需要单独处理这类特殊情况即可,整体适用性很强。
内容的提问来源于stack exchange,提问作者Radek Strugalski
相关产品推荐
相关产品推荐

