C++ 正则表达式:获取 SubMatch 匹配的捕获组的索引

hak*_*010 5 c++ regex tokenize lexer capturing-group

语境。我正在开发一个 Lexer/Tokenizing 引擎,它将使用正则表达式作为后端。词法分析器接受定义令牌类型/ID 的规则,例如

<identifier> = "\\b\\w+\\b"。

正如我所设想的,为了进行基于正则表达式匹配的标记化,正则表达式定义的所有规则都包含在捕获组中,并且所有组都由 OR 分隔。

当执行匹配时,我们生成的每个匹配都必须有一个与其匹配的捕获组的索引。我们使用这些 ID 将匹配映射到令牌类型。

那么这个问题的问题就出现了——如何获取群组的ID?

这里有类似的问题,但它没有为我的具体问题提供解决方案。

这正是我的问题,但它是在 JS 中,我需要一个 C/C++ 解决方案。

假设我有一个正则表达式,由用 OR 分隔的捕获组组成:

(\\b[a-zA-Z]+\\b)|(\\b\\d+\\b)

它匹配整数或字母单词。

我的问题要求可以知道正则表达式子匹配匹配的捕获组的索引,例如在匹配字符串时

foo bar 123

将进行 3 次迭代。每次迭代的匹配项的组索引将为0 0 1,因为前两个匹配项与第一个捕获组匹配,最后一个匹配项与第二个捕获组匹配。

我知道在标准std::regex库中这并不完全可能(regex_token_iterator不是解决方案,因为我不需要跳过任何匹配)。

boost::regex我对PCRE 正则表达式库了解不多。

完成这项任务的最佳方法是什么?使用哪个库和方法?

Wik*_*żew 4

您可以使用sregex_iterator来获取所有匹配项,一旦有匹配项,您可以分析结构std::match_results并仅获取参与匹配的组的 ID-1 值(注意,这里只有一个组会匹配,要么是第一个组,要么是第一个组)或第二个),可以使用以下命令方便地检查m[index].matched:

std::regex r(R"((\b[[:alpha:]]+\b)|(\b\d+\b))");
std::string s = "foo bar 123";
for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
                         i != std::sregex_iterator();
                         ++i)
{
    std::smatch m = *i;
    std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';

    for(auto index = 1; index < m.size(); ++index ){
        if (m[index].matched) {
            std::cout << "Capture group ID: " << index-1 << std::endl;
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅C++ 演示。输出:

Match value: foo at Position 0
Capture group ID: 0
Match value: bar at Position 4
Capture group ID: 0
Match value: 123 at Position 8
Capture group ID: 1
Run Code Online (Sandbox Code Playgroud)

请注意,这R"(...)"是一个原始字符串文字,不需要在其中使用双反斜杠。

另外,在循环开始时index设置为,因为第 0 组是整个匹配,但您希望组 ID 从零开始,这就是为什么稍后要减去的原因。1for1