C ++:使用简单的正则表达式解析或shoud我使用sscanf?

时间:2010-04-19 14:34:14

标签: c++ c regex parsing scanf

我需要解析像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 ++标准库(可能还有提升)。

3 个答案:

答案 0 :(得分:2)

Boost Spirit怎么样?

答案 1 :(得分:2)

如果您想使用Regex,将它分成两个步骤会更简单。在第1步中找到

func1(stuff);

并将其转为func1stuff

在下一步中,您解析'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可以做到。