不同优先级一元运算符结合解析问题及Bison自定义<-,->运算符实现咨询
多优先级前缀/后缀运算符链式调用解析错误的核心原因
- Bison的优先级规则仅用于解决移进-归约冲突,只对产生式末尾的终结符生效,优先级匹配错位就会触发冲突或者错误归约
- 后缀运算符的左操作数必须是优先级高于自身的语法单元,否则会出现提前归约:比如如果把低优先级的
<-放到高优先级的post_unary产生式中,1+2<-会被错误归约为1 + (2<-),和需求完全相反 - 前缀运算符的右操作数必须是优先级低于或等于自身的语法单元,否则会出现语法错误:你提到的Python
- not False报错就是因为前缀-优先级高于not,-期望后跟高优先级表达式,而not作为低优先级前缀无法满足该要求,直接触发语法错误 - 同优先级、同结合性的同类型运算符(比如都是左结合后缀运算符)的递归产生式天然支持链式调用,这也是你现有规则中
x ! -- !能正常解析的原因
Bison实现<-/->运算符的具体方案
首先明确两个运算符的优先级定位:后缀<-和前缀->的优先级均低于所有普通二元运算符(加减乘除、比较、逻辑等),后缀<-左结合,前缀->右结合,且完全不影响原有!、++、NOT等高优先级运算符的优先级规则。
步骤1:调整优先级声明
按优先级从低到高的顺序声明运算符,两个新运算符放在最底层,原有高优先级运算符的位置完全不变:
/* 优先级从低到高排列,位置越靠下优先级越高 */ %right "->" // 低优先级前缀运算符,右结合 %left "<-" // 低优先级后缀运算符,左结合 %left '+' '-' %left '*' '/' /* 原有高优先级运算符声明完全保持不变 */ %precedence '!' NOT %left "++" "--"
步骤2:拆分语法产生式,新增独立层级隔离新老运算符
在原有产生式基础上新增两个独立层级分别处理<-和->,原有高优先级运算符的产生式完全不需要修改:
/* 顶层表达式:先处理低优先级前缀-> */ expr: prefix_expr ; prefix_expr: postfix_expr | "->" prefix_expr // 支持前缀链式调用,比如-> -> 1+2 ; postfix_expr: binary_expr | postfix_expr "<-" // 支持后缀链式调用,比如a+b<- <- ; /* 原有普通二元运算层级,优先级高于两个新运算符 */ binary_expr: post_unary | binary_expr '+' binary_expr | binary_expr '-' binary_expr | binary_expr '*' binary_expr | binary_expr '/' binary_expr // 其余二元运算规则保持不变 ; /* 原有高优先级后缀运算符规则完全不变 */ post_unary: copy | post_unary "++" | post_unary "--" | post_unary '!' // 其余高优先级后缀规则保持不变 ; /* 原子单元规则完全不变 */ copy: IDENTIFIER | NUMBER | '(' expr ')' // 其余原子单元规则保持不变 ;
步骤3:适配语义动作
- 后缀
<-的语义动作直接返回左操作数的抽象语法树节点即可,等价于给左侧表达式套了一层隐形括号 - 前缀
->的语义动作直接返回右操作数的抽象语法树节点即可,等价于给右侧表达式套了一层隐形括号 - 原有所有运算符的语义动作不需要任何修改,自然保持原有优先级规则
效果验证
1+2<-*3会被解析为((1+2)<-) * 3,等价于(1+2)*3,符合需求x ! -- <-会被解析为(((x !) --) <-),原有高优先级运算符的计算顺序完全不变*->1+2会被解析为* (-> (1+2)),等价于*(1+2),符合前缀运算符需求
内容的提问来源于stack exchange,提问作者Doot
相关产品推荐
相关产品推荐

