我需要解析像func1(arg1, arg2); func2(arg3, arg4);
这样的字符串。这不是一个非常复杂的解析问题,所以我宁愿避免使用flex / bison或类似的实用程序。
我的第一个尝试是尝试使用POSIX C regcomp/regexec
或Boost实现的C ++ 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
不在其中!
问题在于,在标准正则表达式库中,子标记仅捕获最后一个匹配项。换句话说,如果您在"((a*|b*))*"
上应用了正则表达式"babb"
,则内部匹配的结果将为bb
,之前的所有捕获都将被遗忘。
另一件令我烦恼的事情是,如果出现错误,就无法知道哪个字符未被识别,因为这些函数在输入被拒绝时提供的关于解析器状态的信息非常少。
所以我不知道我在这里遗漏了什么......在这种情况下,我应该使用sscanf
或类似的吗?
请注意,我更喜欢使用C / C ++标准库(可能还有提升)。
答案 0 :(得分:2)
Boost Spirit怎么样?
答案 1 :(得分:2)
如果您想使用Regex,将它分成两个步骤会更简单。在第1步中找到
func1(stuff);
并将其转为func1
和stuff
在下一步中,您解析'stuff'以查找函数的所有单独args。
答案 2 :(得分:1)
如果这是Ruby,我会先匹配
%r{
([a-zA-Z_][a-zA-Z0-9_]*) #identifier
\s* #whitespace after the identifier
\( #open paren
([^)]*) #all arguments as one string
\) #close paren
}x
然后我会使用$2.split(/\s*,\s*/)
将分段分开。我不认为C ++标准库中有split
的等价物,但我认为boost :: regex_split可以做到。