C++中如何用正则表达式捕获Python运算符与分隔符?
Python JIT编译器分词阶段:正则匹配多字符符号与特殊分隔符解决方案
核心思路
要实现保留分隔符的分词,正则必须优先匹配多字符符号(比如-=、//、!=),再处理单字符的运算符/分隔符,同时对正则里有特殊含义的字符([、]、(、)等)做转义,避免匹配逻辑出错。
正确的正则表达式
把所有多字符符号放在正则最前面,确保它们不会被拆成单字符匹配。以下是覆盖Python常见运算符和分隔符的正则:
(-=|\+=|\/=|\*=|==|!=|<=|>=|\/\/|\*\*|\(|\)|\[|\]|,|;|\.|\+|-|\/|\*|=|<|>|!)
正则说明
- 多字符符号组:
-=、+=、/=、*=、==、!=、<=、>=、//、**(Python中的复合运算符) - 转义的特殊字符:
(、)、[、](正则元字符,必须用\转义才能匹配本身) - 普通单字符:
,、;、.、+、-、/、*、=、<、>、!
修改后的C++实现代码
原代码存在两个问题:一是C++的std::string没有substring方法(应使用substr),二是手动修改line会导致正则迭代器失效。改用std::sregex_token_iterator可以更简洁安全地实现需求:
/// @brief 将代码行拆分为词法单元列表,同时保留分隔符本身 /// @param line 待分词的代码行引用 /// @return 可供解析的词法单元列表 std::list<std::string> breakDown(std::string& line) { std::list<std::string> lexemes; // 用原始字符串字面量避免双重转义,优先匹配多字符符号 std::regex delimiters(R"((-=|\+=|\/=|\*=|==|!=|<=|>=|\/\/|\*\*|\(|\)|\[|\]|,|;|\.|\+|-|\/|\*|=|<|>|!))"); // -1 匹配分隔符以外的内容,0 匹配分隔符本身,一次性获取所有token std::sregex_token_iterator it(line.begin(), line.end(), delimiters, {-1, 0}); std::sregex_token_iterator end; for (; it != end; ++it) { std::string token = *it; // 跳过空字符串,比如连续分隔符之间的空白内容 if (!token.empty()) { lexemes.push_back(token); } } return lexemes; }
关键改进点
- 原始字符串字面量:用
R"(...)"包裹正则,不用写双重转义的\\,代码更易读。 - sregex_token_iterator的正确用法:通过
{-1, 0}参数,自动把分隔符和非分隔符内容都提取出来,不需要手动截取字符串,彻底避免迭代器失效问题。 - 空token过滤:处理类似
a+++b这种连续运算符的场景,不会把中间的空字符串加入词法单元列表。
测试效果示例
输入代码行:x += 5 // 2; y != [1,2]
分词后的结果为:"x", " += ", "5", " // ", "2", ";", " y", " != ", "[", "1", ",", "2", "]"
内容的提问来源于stack exchange,提问作者Владислав Король
相关产品推荐
相关产品推荐

