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

Bison跨规则解决移进/归约冲突:如何标记优先级?

解决Bison中规则优先级冲突:让expression IS type优先解析完整类型

当规则展开内容存在重叠时,比如定义expression IS type规则(其中type递归展开为type DOT identifier),同时expression规则中也包含expression DOT identifier,Bison会报告冲突。我们需要让expression IS后的所有DOT都归约为type——例如a is b.c.d要解析为(a is b.c.d),而非(a is b).c.d。

冲突的最简语法

%require "3.0"
%defines

%define api.pure full
%define parse.trace

%token DOT '.'
%token IS "is"

%left DOT
%left IS

%%

example
    : expression
    ;
    
expression
    : expression DOT identifier
    | expression IS type
    | identifier
    ;
    
type
    : fqtypename
    ;

fqtypename
    : identifier
    | fqtypename DOT identifier
    ;

identifier: 
    "blah"
    ;

%%

错误信息

State 10

5 type: fqtypename •
7 fqtypename: fqtypename • DOT identifier

DOT  shift, and go to state 12

DOT       [reduce using rule 5 (type)]
$default  reduce using rule 5 (type)

解决方案

方法1:拆分表达式规则,明确优先级

通过单独拆分IS相关的表达式规则,让Bison先完整解析type部分(包括所有嵌套的DOT),再归约为expression,避免和普通成员访问规则冲突:

%require "3.0"
%defines

%define api.pure full
%define parse.trace

%token DOT '.'
%token IS "is"

// 调整优先级:IS优先级低于DOT,确保type内部的DOT先处理
%left IS
%left DOT

%%

example
    : expression
    ;
    
expression
    : expression DOT identifier       // 普通成员访问表达式
    | is_expression                   // 单独定义IS表达式
    | identifier
    ;

// 明确IS表达式的结构,确保type先完成递归解析
is_expression
    : identifier IS type
    | expression DOT identifier IS type
    ;
    
type
    : fqtypename
    ;

fqtypename
    : identifier
    | fqtypename DOT identifier       // type内部的DOT递归,优先于expression的DOT
    ;

identifier: 
    "blah"
    ;

%%

方法2:使用%prec绑定更高优先级

给fqtypename的递归规则绑定更高优先级的标记,让Bison在遇到DOT时优先选择移进构建完整的type,而非归约type后处理expression DOT:

%require "3.0"
%defines

%define api.pure full
%define parse.trace

%token DOT '.'
%token IS "is"

// 定义优先级层级:DOT_HIGH > DOT > IS
%left IS
%left DOT
%left DOT_HIGH

%%

example
    : expression
    ;
    
expression
    : expression DOT identifier
    | expression IS type
    | identifier
    ;
    
type
    : fqtypename
    ;

fqtypename
    : identifier
    | fqtypename DOT identifier %prec DOT_HIGH  // 绑定更高优先级
    ;

identifier: 
    "blah"
    ;

%%

两种方法的核心都是让Bison明确:IS关键字后的DOT属于type的递归解析,优先级高于普通的expression DOT成员访问,从而避免归约冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 23:06:23