我有一个想法,能不能用常规编程语言来构建正则表达式,基本的实现方案是:
1, 提供一个 Class,类的名字叫 Regex
2, 提供一组基本的 API:
Regex Any(string); //字符群中的任意一个
Regex None(string); //字符群外的任意一个
Regex Between(string); //字符区间的任意一个
Regex NotBetween(string); //字符区外的任意一个
Regex Regex(string); //把 string 转换成 Regex 对象
Regex Mustnot(Regex); //negative look ahead
...
这些 API 接受字符串参数,返回一个 Regex 对象.
此外,Regex 对象本身也有 method,像:
Regex Regex::repeat(min, max); //重复 min 至 max 次
3, Regex 对象之间是可以运算的(通过重载操作符), 运算的结果还是 Regex 对象.
减号是取补集,像:
Between("az") - Any("sdf") 是从 a-z 范围内挖掉 s,d,f 这三个字符.
竖线|是取并集,加号+是连接, 感叹号!是取反,表示该集合之外的所有字符.
4, 通过 Regex 对象,帮用户(一个程序员)生成它想要的 pattern 字符串.
下面举几个例子,先来几个简单点儿的:
匹配数字: Regex digit = Between("09")
匹配字母: Regex alpha = Between("az", "AZ") //可以接受多个 range 参数
匹配空白: Regex space = Any("\n\t\f\r\s")
再来个稍微复杂些的,匹配 c 的变量名:
Regex cword =
Mustnot( Between("09")) //不能以数字开头
+ ( Between("09", "az", "AZ") | "_" ).repeat(1, 255); //变量名长度小于 256
其实能写的更简单点儿,因为之前已经定义过 digit, alpha 这些,可以当模板用:
Regex cword =
Mustnot( digit )
+ (digit | alpha | "_").repeat(1, 255)
前面说过 Regex 对象之间可以运算,所以上面有 digit | alpha | "_" 这样的写法. 只不过第三个运算对象"_"是 string 类型,我是嫌写成 Regex("_")麻烦,string 跟 Regex 对象运算时会自动的隐式转换为 Regex 对象.这是设计细节,就不多说了.
我觉得这种傻瓜式的构建 regex 的好处是,能把初学者从正则表达式的晦涩的文法里解放出来,有精力去体会 Regex 这项发明背后的基本思想. 即使这样写的稍慢一些,但总归能写出来,不至于要去网上求别人.
我现在正在着手写这个库,但总怀疑已经有人设计出来了,如果你知道的话,请一定赶紧告诉我!
最后,如果你有什么想法或建议,请不吝赐教.