首页 文章

使用空格分隔表达式列表解决bison语法中的冲突if / then / else

提问于
浏览
0

我有以下yacc / bison / happy语法:

%token 
  if              TokenIf
  then            TokenThen
  else            TokenElse
  true            TokenTrue
  false           TokenFalse

%left APP
%right IF

%%

Hungry
  : NoHungry
  | Hungry NoHungry %prec APP
  | if Hungry then Hungry else Hungry %prec IF

NoHungry
  : true
  | false

bison -v 告诉我在以下情况下有两个冲突:

State 12

    2 Hungry: Hungry . NoHungry
    3       | if Hungry then Hungry else Hungry .

    true   shift, and go to state 2
    false  shift, and go to state 3

    true      [reduce using rule 3 (Hungry)]
    false     [reduce using rule 3 (Hungry)]
    $default  reduce using rule 3 (Hungry)

    NoHungry  go to state 8

我尝试通过 %prec 给出明确的优先声明来解决冲突,但无济于事 . 鉴于野牛解决了所谓的冲突(例如转移而不是减少),这并不是那么糟糕,但我想知道如何在不改变公认语言的情况下摆脱冲突 .

1 回答

  • 1

    从野牛报告中可以看出,冲突与终端 truefalse 有冲突,这些终端未在优先关系中列出 . 因此,优先规则不适用于这些冲突 .

    回想一下,在 生产环境 和终端之间定义了优先关系 . 它不涉及两个终端或两个产品(因此不能用于解决减少 - 减少冲突) . 可以减少的 生产环境 优先级与先行终端之间的比较确定是否会发生减少或转移 . 为方便起见,制作由终端名称表示,通常是制作中唯一的终端;这对应于一个常见的用例,但有时令人困惑 . 特别是, %prec 声明仅用于为规则提供在优先声明中使用的名称,并且最好以这种方式而不是"explicit"声明来考虑它 .

    简而言之,通过在优先关系中明确添加适当的终端,可以解决问题中简化语法的冲突:

    %precedence "if"
    %precedence "true" "false"
    
    %%
    
    Hungry
      : NoHungry
      | Hungry NoHungry
      | "if" Hungry "then" Hungry "else" Hungry %prec "if"
    
    NoHungry
      : "true"
      | "false"
    

    摘自 -v 输出:

    State 12
    
        2 Hungry: Hungry . NoHungry
        3       | "if" Hungry "then" Hungry "else" Hungry .
    
        "true"   shift, and go to state 2
        "false"  shift, and go to state 3
    
        $default  reduce using rule 3 (Hungry)
    
        NoHungry  go to state 8
    

    通过使用 -r solved 而不是 -v ,您可以更明确地看到分辨率:

    Conflict between rule 3 and token "true" resolved as shift ("if" < "true").
        Conflict between rule 3 and token "false" resolved as shift ("if" < "false").
    

    我本可以使用 "else" 作为 if 生产环境 的名称,如果没有 %prec 声明,它将是默认值,但 "if" 似乎更直观 .

    %precedence 声明(最近的野牛版本中提供)并不意味着左右相关性;在这种情况下,关联性不适用,因为不存在冲突涉及具有相同优先级的 生产环境 和终端的情况 . 如果Happy没有实现它,可以使用 %left%right 出于同样的原因(关联性无关紧要)但我认为 %precedence 更好地记录了这种情况 .

    由于这无疑是一个简化的例子,值得注意的是更完整的语法需要一些语法分析 . 特别是,优先级大于 "if" 的终端列表必须包含 FIRST(NoHungry) 中的所有终端,并且bison不提供执行该计算的自动工具,尽管您通常可以从shift-reduce冲突报告中提取列表 . (甚至可能是 "if" 是集合的一部分,在这种情况下,关联性很重要 . )

相关问题