You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决PLY中表达式语法的移进/归约冲突(含内嵌函数)

解决PLY中属性访问的移进/归约冲突问题

我用PLY开发解释器语法,实现内嵌函数调用(比如vector的pop()/join()、通用toString()、转换函数parseInt())时遇到移进/归约冲突。新增对象属性访问规则并添加('left', 'PUNTO')优先级后,仍出现以下冲突:

WARNING: shift/reduce conflict for PUNTO in state 43 resolved as shift

state 43

    (74) expresion -> acceso_atrib .
    (75) acceso_atrib -> acceso_atrib . PUNTO expresion

  ! shift/reduce conflict for PUNTO resolved as shift
    MAS             reduce using rule 74 (expresion -> acceso_atrib .)
    MENOS           reduce using rule 74 (expresion -> acceso_atrib .)
    MULTI           reduce using rule 74 (expresion -> acceso_atrib .)
    DIV             reduce using rule 74 (expresion -> acceso_atrib .)
    MOD             reduce using rule 74 (expresion -> acceso_atrib .)
    IGUAL           reduce using rule 74 (expresion -> acceso_atrib .)
    DIFERENTE       reduce using rule 74 (expresion -> acceso_atrib .)
    MENOR_QUE       reduce using rule 74 (expresion -> acceso_atrib .)
    MAYOR_QUE       reduce using rule 74 (expresion -> acceso_atrib .)
    MENOR_IGUAL     reduce using rule 74 (expresion -> acceso_atrib .)
    MAYOR_IGUAL     reduce using rule 74 (expresion -> acceso_atrib .)
    AND             reduce using rule 74 (expresion -> acceso_atrib .)
    OR              reduce using rule 74 (expresion -> acceso_atrib .)
    PUNTO_COMA      reduce using rule 74 (expresion -> acceso_atrib .)
    PAREN_CIERRE    reduce using rule 74 (expresion -> acceso_atrib .)
    COMA            reduce using rule 74 (expresion -> acceso_atrib .)
    CORCHETE_CIERRE reduce using rule 74 (expresion -> acceso_atrib .)
    DOS_PUNTOS      reduce using rule 74 (expresion -> acceso_atrib .)
    PUNTO           shift and go to state 87

  ! PUNTO           [ reduce using rule 74 (expresion -> acceso_atrib .) ]

以下是解决该冲突的具体建议:

  • 调整语法规则结构,明确层级:
    冲突根源是expresion -> acceso_atrib和acceso_atrib -> acceso_atrib PUNTO expresion的歧义——解析器遇到PUNTO时,无法判断是继续移进以构建更长的属性访问链,还是先把当前acceso_atrib归约为expresion。
    建议重构规则,将属性访问和方法调用整合为同一个规则分支,确保连续的属性访问(如a.b.c)或方法调用后接属性访问(如a.pop().b)能被优先完整解析,而非中途归约为普通表达式。示例规则:

    expresion -> acceso_atrib | aritmetica_expresion | comparacion_expresion | ...其他表达式类型...
    acceso_atrib -> IDENTIFICADOR 
                  | acceso_atrib PUNTO IDENTIFICADOR 
                  | acceso_atrib PAREN_ABIERTO argumentos PAREN_CIERRE
    

    这里把方法调用直接纳入acceso_atrib规则,因为方法本质是对象的函数属性,这样连续的属性访问操作会被优先处理。

  • 提升PUNTO的优先级:
    属性访问的优先级原本就高于算术、比较、逻辑等所有运算符,所以要把('left', 'PUNTO')放在优先级列表的最顶端,确保解析器遇到PUNTO时优先处理属性访问,而非归约前面的表达式。示例优先级配置:

    precedence = (
        ('left', 'PUNTO'),  # 最高优先级,确保属性访问优先解析
        ('left', 'OR'),
        ('left', 'AND'),
        ('nonassoc', 'IGUAL', 'DIFERENTE', 'MAYOR_QUE', 'MENOR_QUE', 'MAYOR_IGUAL', 'MENOR_IGUAL'),
        ('left', 'MAS', 'MENOS'),
        ('left', 'MULTI', 'DIV', 'MOD'),
        # 其他优先级规则...
    )
    
  • 清理冗余规则,消除歧义:
    检查是否存在其他expresion子规则能生成带PUNTO的结构,这类规则会和acceso_atrib产生冲突。确保只有acceso_atrib规则负责处理所有带.的属性访问和方法调用场景。

  • 用PLY调试工具定位具体场景:
    在创建解析器时传入debug=True参数,运行后查看状态43的完整上下文,确认冲突触发的具体输入场景(比如是否是表达式嵌套中的属性访问、连续多个方法调用等),根据实际场景针对性调整规则。

内容的提问来源于stack exchange,提问作者luisepa1420

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:53:22