1

我需要解析一个像func1(arg1, arg2); func2(arg3, arg4);. 这不是一个非常复杂的解析问题,所以我宁愿避免使用 flex/bison 或类似的实用程序。

我的第一个方法是尝试使用 POSIX Cregcomp/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旨在捕获除最后一个之外的参数,后者由 group 捕获n

当我将此正则表达式应用于时,说func(arg1, arg2, arg3)我得到的结果是一个数组{func, arg2, arg3}。这是错误的,因为arg1不在其中!

问题是在标准正则表达式库中,子标记只捕获最后一个匹配项。换句话说,例如,如果您将正则表达式"((a*|b*))*"应用于"babb",则内部匹配的结果将是bb并且所有先前的捕获都将被遗忘。

让我烦恼的另一件事是,如果出现错误,则无法知道哪个字符未被识别,因为当输入被拒绝时,这些函数提供的有关解析器状态的信息非常少。

所以我不知道我是否在这里遗漏了一些东西......在这种情况下我应该使用sscanf或类似的东西吗?

请注意,我更喜欢使用 C/C++ 标准库(也可能是 boost)。

4

3 回答 3

2

提升精神怎么样?

于 2010-04-19T14:37:26.023 回答
2

如果您想使用正则表达式,将其分为两步会更简单。在第 1 步中,您发现

func1(stuff);

把它变成func1stuff

在下一步中,您解析“stuff”以找到该函数的所有单独参数。

于 2010-04-19T14:41:53.543 回答
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*/)将参数分开。我认为splitC++ 标准库中没有任何等效的东西,但是我认为 boost::regex_split 可以做到。

于 2010-04-19T14:40:43.040 回答