【发布时间】:2010-04-19 14:34:13
【问题描述】:
我需要解析像func1(arg1, arg2); func2(arg3, arg4); 这样的字符串。这不是一个非常复杂的解析问题,所以我宁愿避免使用 flex/bison 或类似的实用程序。
我的第一个方法是尝试使用 POSIX C regcomp/regexec 或 C++ 的 Boost 实现 std::regex。我写了以下正则表达式,但它不起作用(我将进一步解释原因)。
"^"
"[ ;\t\n]*"
"(" // (1) identifier
"[a-zA-Z_][a-zA-Z0-9_]*"
")"
"[ \t\n]*"
"(" // (2) non-marking
"\["
"(" // (3) non-marking
"[ \t]*"
"(" // (4..n-1) argument
"[a-zA-Z0-9_]+"
")"
"[ \t\n]*"
","
")*"
"[ \t\n]*"
"(" // (n) last argument
"[a-zA-Z0-9_]+"
")"
"]"
")?"
"[ \t\n]*"
";"
请注意,1 组捕获标识符,4..n-1 组旨在捕获除最后一个之外的参数,后者由组 n 捕获。
当我将此正则表达式应用于func(arg1, arg2, arg3) 时,我得到的结果是一个数组{func, arg2, arg3}。这是错误的,因为arg1 不在其中!
问题在于,在标准正则表达式库中,子标记仅捕获最后一个匹配项。换句话说,如果您在"babb" 上应用了正则表达式"((a*|b*))*",则内部匹配的结果将是bb,并且所有之前的捕获都将被遗忘。
这里让我烦恼的另一件事是,如果出现错误,则无法知道哪个字符未被识别,因为当输入被拒绝时,这些函数提供的解析器状态信息非常少。
所以我不知道我是否在这里遗漏了什么......在这种情况下我应该使用sscanf 或类似的代替吗?
请注意,我更喜欢使用 C/C++ 标准库(也许还有 boost)。
【问题讨论】: