正则表达式词法分析器 - 名称和数字相互识别

regex lexer - name and number gets recognized on each other

所以我有这个正则表达式和符号的基本向量:

std::vector<std::pair<std::string, std::string>> patterns = 
{
    {"\+|\\|\*|\-|\%|\=", "OPERATOR"},
    {"[0-9]+", "NUMBER"},
    {"[a-zA-z_][a-zA-Z0-9_]*", "NAME"},
};

这就是我找到模式的方式:

std::map<int, std::pair<std::string, std::string>> matches;
for (auto pattern = patterns.begin(); pattern != patterns.end(); ++pattern)
    {
        std::regex regex(pattern->first);
        std::sregex_iterator words_begin = std::sregex_iterator(_input.begin(), _input.end(), regex);
        std::sregex_iterator words_end = std::sregex_iterator();

        for (std::sregex_iterator it = words_begin; it != words_end; ++it)
        {
            matches[it->position()] = make_pair(it->str(), pattern->second);
        }
    }

输出:

a45 NAME
45 NUMBER
= OPERATOR
77 NUMBER

问题是 a45 是一个名字,但 45 是名字的一部分,但它也是一个数字,但我不希望它被识别为数字。 不知道要克服这种问题...

对于非重叠匹配,为了更好的性能,你应该结合正则表达式,然后检查匹配的部分。

"(\+|\\|\*|\-|\%|\=)|([0-9]+)|([a-zA-z_][a-zA-Z0-9_]*)"

 ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
           group 1          group 2         group 3

如果捕获组 1 匹配,则下一个 "token" 是运算符。
如果捕获组 2 匹配,则下一个 "token" 是一个数字。
如果捕获组 3 匹配,则下一个 "token" 是名称。