正则表达式词法分析器 - 名称和数字相互识别
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" 是名称。