我目前正在c++中开发一个项目,将regex用作HTTP FRC规则。在RFC 1945第2.2章-基本规则中,有以下规则:
CHAR = <any US-ASCII character (octets 0 - 127)>
CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
CR = <US-ASCII CR, carriage return (13)>
LF = <US-ASCII LF, linefeed (10)>
SP = <US-ASCII SP, space (32)>
HT = <US-ASCII HT, horizontal-tab (9)>
CRLF = CR LF
LWS = [CRLF] 1*( SP | HT )
word = token | quoted-string
token = 1*<any CHAR except CTLs or tspecials>
tspecials = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | "" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
quoted-string = ( <"> *(qdtext) <"> )
qdtext = <any CHAR except <"> and CTLs, but including LWS>
我感兴趣的是像[:digit:]
这样的字符类的使用,或者至少是回收regex。伪代码会变成这样(已经转义,regex已经是字符串形式(:
CHAR = "\x00-\x7F"
CTL = "\x00-\x19\x7F"
CR = "\r"
LF = "\n"
SP = "\x20"
HT = "\t"
//here I start "recycling" old regexes
CRLF = "[:CR:][:LF:]"
LWS = "[:CRLF:]* ( [:SP:] | [:HT:] )+"
//here a declaration might happen before using the token or quoted_string class
word = "[:token:] | [:quoted_string:]"
token = "( (?= [[:CHAR:]] ) [^[:tspecial:][:CTL:]] )+"
tspecials = "()<>@,;:\\\"/\[\]?={}[:SP:][:HT:]"
quoted_string = " ( \" ([:qdtext:])* \" ) "
//Little trick to allow LWS but not CTLs: https://stackoverflow.com/a/18017758/9373031
qdtext = "(?=[[:CHAR:]]) ( [:LWS:] | [^\"[:CTL:]] )"
到目前为止,我尝试的是将它们存储为字符串,然后用+
将它们链接在一起,但看起来很难看,也不是很优化。当然,我可以重复一些正则表达式,但我越走越远,它就开始变成一个巨大的怪物。
我试着在谷歌上搜索了一段时间,但也没有发现任何关于添加自定义POSIX类的信息,也没有发现关于回收(和优化?(regexs的信息。
我需要做的是优化和美化正则表达式的原始字符串,这样它们就可以被解析为一个新的类POSIX,或者以其他方式(C/C++中的代码(:
std::regex CR ("\r");
std::regex LF ("\r");
std::regex CRLF ("[:CR:] [:LF:]");
选项1:[:CR:] [:LF:]
将扩展为\r \n
,编译时将变为:std::regex CRLF ("\r \n");
选项2:[:CR:] [:LF:]
将是";展开的";作为";两个功能";以在运行时优化regex。
到目前为止,我发现std::ctype_base
具有用于std::regex_traits<CharT>::lookup_classname
函数中类名的静态方法,该方法应用于查找已定义的类名:是否可以扩展所使用的掩码?
您需要一种元语言和一些编译器。这不是的任务,只是C++预处理器或/和编译器的常量折叠或其他编译阶段功能。
使用元语言,您将描述您的扩展RE变体。然后,您的编译器将解析该变体,并为主项目生成一些输入-要么只是一组用作传统RE输入的字符串,要么是更智能、更复杂的字符串。
用于您任务的工具确实存在:http://www.nongnu.org/bnf/、flex/bison等。它们不仅允许您只生成一组RE字符串,还可以为您的元语言创建整个解析器(您已经要求进行优化(——如果您的项目允许这样的概念的话。
或者,您可以从头开始编写自己的解析器。