【问题标题】:C++: parsing with simple regular expression or shoud I use sscanf?C++:用简单的正则表达式解析还是我应该使用 sscanf?
【发布时间】: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)。

【问题讨论】:

    标签: c++ c regex parsing scanf


    【解决方案1】:

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

    func1(stuff);
    

    并把它变成func1stuff

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

    【讨论】:

      【解决方案2】:

      Boost Spirit怎么样?

      【讨论】:

      • 我觉得Boost::Spirit 有点乱……还有谷歌的RE2。
      • 好吧,我发现 RE 很乱。各有各的。 8v)
      【解决方案3】:

      如果这是 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 可以做到。

      【讨论】:

        猜你喜欢
        • 2016-12-17
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 2011-04-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多