首页 > 其他分享 >Bison遇到冲突的默认行为&用户自定义优先级

Bison遇到冲突的默认行为&用户自定义优先级

时间:2024-10-14 14:12:24浏览次数:1  
标签:优先级 自定义 规约 expr 运算符 Bison 冲突

Bison遇到冲突的默认行为&用户自定义优先级

在使用 Bison 进行语法分析时,如果在语法规则中存在冲突,Bison 会根据默认的优先级结合性规则进行决策,选择某个特定的行为来解决冲突。Bison 中常见的冲突主要包括两类:

  1. 移入-规约冲突(shift-reduce conflict)
  2. 规约-规约冲突(reduce-reduce conflict)

Bison 对这些冲突的处理有一定的优先策略。以下是详细解释:

详细解释

1. 移入-规约冲突(shift-reduce conflict)

移入-规约冲突 是最常见的冲突之一。它发生在某个时刻,语法分析器既可以选择移入(读取更多输入符号),也可以选择规约(使用当前符号规约为某个非终结符)。例如:

stmt: expr ';'
    | expr '+' expr ';'
    ;

在这种情况下,当看到 expr 后,有可能既可以选择规约stmt,也可以选择移入以继续处理 + 符号并形成 expr '+' expr 的结构。这就导致了移入-规约冲突。

Bison 的优先行为:

  • 默认行为:Bison 会优先选择移入(shift),而不是规约(reduce)。Bison 默认认为继续读取输入符号可能会得到更多信息,避免过早规约导致后续无法正确处理输入。

    这个策略通常会产生正确的行为,尤其是在像表达式解析这种场景下,移入操作能够捕获更多的输入,并正确地生成更大的表达式。

结合性和优先级的影响:

  • Bison 允许通过指定运算符的优先级和结合性来控制移入和规约的冲突。通过使用 %left%right%nonassoc 关键字声明运算符的优先级和结合性,可以帮助解析器解决冲突。

    示例:

    %left '+' '-'
    %left '*' '/'
    
    expr: expr '+' expr
        | expr '*' expr
        | '(' expr ')'
        | NUM
        ;
    

    在这个例子中,*/ 的优先级高于 +-,因此如果有 expr + expr * expr,Bison 会先移入 *,然后规约 expr * expr,再规约 +

2. 规约-规约冲突(reduce-reduce conflict)

规约-规约冲突 发生在解析器可以根据多条规则规约当前的符号。也就是说,两个或多个规则都可以适用于当前的输入,但 Bison 无法确定使用哪个规则来规约。

示例:

stmt: expr ';'
    | var_decl ';'
    ;

var_decl: TYPE ID
    ;

expr: ID
    ;

在这种情况下,如果解析器看到 ID 后,不确定是否要将其规约为 expr 还是 var_decl,则会产生规约-规约冲突。

Bison 的优先行为:

  • 默认行为:对于规约-规约冲突,Bison 会根据文法的书写顺序来选择使用最早声明的规则进行规约。也就是说,如果两个规约规则产生冲突,Bison 将选择在定义中出现顺序靠前的那个规则。

3. 运算符优先级和结合性

Bison 提供了一种机制,通过定义运算符的优先级和结合性来解决移入-规约冲突。这通常用于消除表达式解析中的冲突问题。

  • 优先级(precedence):优先级用于决定两个运算符的顺序问题。如果有两条规则冲突,Bison 会根据优先级来决定是先移入还是先规约。高优先级的运算符会优先执行。

  • 结合性(associativity):结合性用于处理多个同级运算符的顺序问题。结合性可以是:

    • 左结合(left-associative):从左往右结合,比如 a - b - c 应该解析为 (a - b) - c
    • 右结合(right-associative):从右往左结合,比如 a = b = c 应该解析为 a = (b = c)
    • 非结合(non-associative):如果两个同级运算符不能连用,则称为非结合。

定义优先级和结合性示例:

%left '+' '-'
%left '*' '/'
%right '^'    // 右结合的运算符
%nonassoc '<' '>'  // 非结合的运算符

通过这种方式,Bison 会根据优先级和结合性来确定如何处理移入-规约冲突,从而生成正确的解析结果。

总结

Bison 在处理语法规则冲突时,采用以下默认的优先行为:

  1. 移入-规约冲突:Bison 默认会选择移入操作(shift),而不是规约。如果定义了运算符的优先级和结合性,Bison 会根据这些信息决定是移入还是规约。
  2. 规约-规约冲突:Bison 会选择最早定义的规则进行规约。
  3. 优先级和结合性:可以通过 %left%right%nonassoc 定义运算符的优先级和结合性,进一步控制冲突的处理方式。
  4. 自定义优先级:通过%left%right等语法定义的优先级,写在越后面,优先级越高。

通过这些机制,Bison 能够有效地解析复杂的文法,并解决解析过程中可能出现的冲突。

标签:优先级,自定义,规约,expr,运算符,Bison,冲突
From: https://www.cnblogs.com/smartljy/p/18464008

相关文章

  • 【vue+printJs】前端打印, 自定义字体大小, 自定义样式, 封装共享样式
    效果示例思维导图目录1,基本使用1,依赖下载2,页面导入3,修改字体大小(可行但不推荐)2,自定义样式,字体大小1,修改字体大小(推荐)2,自定义样式3,封装共享样式3,去除页面页脚内容4,测试案例demo,直接cv可用5,print-js的其他参数说明1,基本使用1,依......
  • C语言——自定义类型
    目录一、结构体        1、结构体的定义与声明        2、结构体变量的定义和初始化        3、结构体的自引用         4、结构体的内存对齐         5、为什么要结构体的内存对齐                1、性能......
  • [java/spring/web] 深入理解:Spring @ExceptionHandler => 自定义应用异常处理器(Appli
    1概述:Spring@ExceptionHandler∈spring-web作用ExceptionHandler是Spring框架(spring-web模块)提供的一个注解,用于处理应用程序中的异常。当应用程序中发生异常时,ExceptionHandler将优先地拦截异常并处理它,然后将处理结果返回到前端。该注解可用于类级别和方法级别,以......
  • 在 LaTeX 中,默认的 `enumerate` 环境会输出 “1. 2. 3.“ 这样的编号。如果你想将编号
    在LaTeX中,默认的enumerate环境会输出“1.2.3.”这样的编号。如果你想将编号格式改为(1)(2)(3)这种样式,你可以通过enumerate包进行自定义。在导言区导入enumerate包:\usepackage{enumerate}在enumerate环境中使用\renewcommand来自定义编号格式为带括号的样式......
  • 如何在cnblogs的发文中使用自定义地址作为发文链接
    要知道在cnblogs中发表内容后其默认的链接地址都是一串数字的形式,比如本篇的默认地址:https://www.cnblogs.com/xyz/p/18461898但是为了让发表的内容更有个性化,于是我们可以指定发文内容的链接地址,也就是自定义发文内容的链接地址,具体方法为在发表时指定slug地址,具体如下:如果......
  • Qt自定义一个圆角对话框
    如何得到一个圆角对话框?步骤:1、继承自QDiaglog2、去掉系统自带的边框3、设置背景透明,不设置4个角会有多余的部分出现颜色4、对话框内部添加1个QWidget,给这个widget设置圆角,并添加到布局中让他充满对话框5、后续对话框的所有内容都添加在这个widget里面举例:#ifndefRO......
  • 实验项目3 自定义路由转换器
    实验目的了解Django处理HTTP请求的流程。掌握路由转换器的用法。掌握如何定义和使用自定义路由转换器。实验内容操作1 创建Django项目chapter02(先进入之前创建的虚拟环境(python3.7、有Django))操作2 在项目chapter02中创建应用app01(应用需要激活应用并分配根路由、创建子......
  • Spring Boot 集成 RabbitMQ 自定义 MessageConverter
    1.SpringBoot集成RabbitMQ自定义消息转换器1.1.版本说明1.2.概述1.3.Spring配置1.4.定义常量1.5.配置交换机和队列1.6.配置ObjectMapper1.7.配置MessageConverter1.8.测试1.SpringBoot集成RabbitMQ自定义消息转换器1.1.版本说明构件版......
  • 自定义 http header 名称中带下划线时,可能会被 nginx 忽略删除
    在设计自定义header时,会发现如user_id这样的header无法被后端读取到想来中间有一层nginx搜了一下果然是它的影响,具体情况就不记录了,可以看参考链接。简单记录是因为下划线可能会导致一些兼容性问题,所以nginx默认不允许header名称带下划线,但也允许手动开启。解决方......
  • 了解如何实现自定义View
    在Android开发中,自定义View是实现独特UI组件的重要手段。通过自定义View,开发者可以创建出满足特定需求、具有独特外观和行为的UI元素。以下将详细介绍如何实现自定义View,包括基础步骤、关键要点以及最佳实践。一、自定义View的基础步骤1.继承View或其子类首先,你需要创建一......