为CPython 3.9新增~=运算符后语法无法识别的问题排查
~=运算符后Python无法识别的问题排查 问题背景
我正按照CPython内部指南第7.5章的内容添加近似等于运算符(~=),但遵循指定步骤并额外排查后,实现仍未达到预期效果。使用的是Python 3.9.19+(heads/3.9-dirty:40d77b9367)的64位调试版本,通过Visual Studio构建项目,VSCode编辑代码,在VSCode终端运行/PCbuild/build.bat --regen。
已完成的操作
1. 语法文件修改
- 更新
Grammar/Grammar第141行,添加~=:comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'|'~=' - 修改
Grammar/python.gram第413行,在compare_op_bitwise_or_pair[CmpopExprPair*]下添加| ale_bitwise_or。 - 在第425行新增规则:
ale_bitwise_or[CmpopExprPair*]: '~=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, AlE, a) }
2. 令牌定义
- 在
Grammar/Tokens第56行添加TILDEEQUAL '~='。
3. AST定义
- 更新
Parser/Python.asdl第102行,添加AlE:cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn | AlE
4. 手动代码补充
- 因
/Parser/token.c未自动更新,手动添加:case '~': switch (c2) { case '=': return TILDEEQUAL; } break; - 在
token.h中定义缺失的TILDEEQUAL。
问题现象
多次重建项目甚至重新克隆后,运行以下Python代码仍收到语法错误:
import ast ast.parse("1 ~= 1") 1 ~= 1
错误信息:
SyntaxError: invalid syntax
问题
导致Python无法识别新增~=运算符语法的遗漏步骤是什么?
遗漏步骤排查
针对Python 3.9版本的CPython,你可能遗漏了以下关键步骤:
1. 确保旧解析器代码(Parser/parser.c)被重新生成
你修改了Grammar/Grammar(旧pgen解析器的语法文件),但如果Parser/parser.c没有被重新生成,旧解析器仍然无法识别新运算符。执行build.bat --regen时,需要确保该命令成功完成,且Parser/parser.c文件的时间戳有更新。如果自动生成失败,可以手动在CPython源码根目录运行:
python -m parser.gen Grammar/Grammar Parser/parser.c
2. 补充AST常量定义
在Include/ast.h中需要添加AlE的常量定义,比如在现有cmpop常量的末尾添加:
#define AlE 11 // 编号需根据现有常量顺延,确保不重复
没有这个定义,AST无法将语法解析的结果映射到正确的操作符类型。
3. 更新AST处理代码
修改Python/ast.c,在比较操作的处理逻辑中添加AlE的支持:
- 在
ast_for_comp_op函数中,添加对AlE的判断,返回对应的AST节点。 - 在
PyAST_Compare等相关函数中,确保AlE类型被正确处理。
同时,更新Modules/_ast.c,添加AlE的类型映射,使得Python层面的AST模块能识别该操作符。
4. 清理缓存并重新构建
Visual Studio的构建缓存可能导致旧的二进制文件被使用。执行以下操作:
- 在Visual Studio中选择Build > Clean Solution
- 重新运行
/PCbuild/build.bat --regen - 再次构建解决方案
5. 检查词法分析的边界情况
确保tokenizer.c中没有阻止~=被识别为单个令牌的逻辑。比如,检查是否有代码将~后面的=视为单独的令牌,需要确保词法分析器在遇到~后紧跟=时,返回TILDEEQUAL令牌。
内容的提问来源于stack exchange,提问作者Damarion Abendanon

