CPython 3.14扩展pass语句关键字时合并分支写法报错的原因咨询
CPython 3.14扩展pass语句关键字时合并分支写法报错的原因咨询
嘿,我完全懂你碰到的这个坑!之前我在修改CPython语法解析规则的时候也栽过类似的跟头,咱们来拆解一下为什么两种写法会有完全不同的结果:
首先得搞清楚CPython用的语法生成器pgen2的工作逻辑:
- 当你把两个关键字分开写,每个分支都跟着
{ _PyAST_Pass(EXTRA) }的时候,pgen2会为每个关键字分支生成独立的代码逻辑——匹配到pass或者xxxxxx后,都会执行这个动作块,调用_PyAST_Pass生成正确的stmt_ty类型语句对象,自然不会有类型问题。 - 但当你把两个关键字用
('pass'|'xxxxxx')合并成一个分支,再跟动作块的时候,pgen2的代码生成逻辑就“跑偏”了:它会把这个选择组的结果默认当成匹配到的Token本身(也就是指向pass或xxxxxx关键字的Token指针),而不是执行你后面的动作块来生成stmt_ty对象。这就导致生成的代码里直接把_keyword(Token指针)赋值给了需要stmt_ty类型的_res变量,于是就出现了你看到的incompatible pointer types类型不兼容错误。
简单来说,pgen2对动作块{ ... }的绑定逻辑是:它会把动作块关联到紧邻的单个符号,而不是一个用|连接的选择组。当你用选择组的时候,生成器不会自动把动作块应用到组里的每个符号,反而会直接返回匹配到的符号本身。
所以你的第一种写法才是符合pgen2规则的正确姿势,虽然看起来稍微啰嗦一点,但能保证解析器生成正确的代码逻辑。如果想找参考的话,你可以看看CPython源码里其他类似的多关键字对应同一种语句的情况,比如raise语句或者import语句的分支,大多都是分开写每个关键字再绑定动作块的。
内容来源于stack exchange
相关产品推荐
相关产品推荐

