【问题标题】:How can I force Bison to shift to resolve a conflict?我怎样才能迫使 Bison 转变以解决冲突?
【发布时间】:2013-11-13 00:15:26
【问题描述】:

我正在为一种简单的编程语言构建这个语法(已经解决了以前的歧义问题:Can't figure out why Bison is throwing "Rules useless in parser due to conflicts")。

这是我的完整语法:http://pastebin.com/yBHLSP0z
这是 Bison 的输出文件:http://pastebin.com/eAma3gWy
(抱歉,它们是西班牙语,但我认为它们非常不言自明)

问题是,在状态 107 处我仍然遇到一个 shift/reduce 错误(我正在翻译它):

state 107

31 factor: ID .
48 concatenacion: ID . OPERADOR_SUMA ID
49              | ID . OPERADOR_SUMA literal_string

OPERADOR_SUMA  shift and go to state 140
OPERADOR_SUMA  [reduce using rule 31 (factor)]
$default       reduce using rule 31 (factor)


现在,从状态 70 调用状态 107:

estado 70

   45 asignacion: ID OPERADOR_ASIGNACION . concatenacion
   46           | ID OPERADOR_ASIGNACION . expresion
   47           | ID OPERADOR_ASIGNACION . literal_string

    OPERADOR_RESTA   desplazar e ir al estado 55
    PARENTESIS_ABRE  desplazar e ir al estado 56
    COMILLA          desplazar e ir al estado 67
    ID               desplazar e ir al estado 107

    expresion       ir al estado 108
    termino         ir al estado 61
    factor          ir al estado 62
    concatenacion   ir al estado 109
    literal_string  ir al estado 110
    literal_real    ir al estado 63
    literal_entero  ir al estado 64
    signo           ir al estado 65

我认为正在发生的事情(如果我错了,请纠正我)是当它找到这样的“asignacion”规则时:

asignacion: ID OPERADOR_ASIGNACION concatenacion | ID OPERADOR_ASIGNACION expresion

它看到从“表达式”可以得到一个ID令牌(表达式>终端>因子> ID),制作一个ID OPERADOR_ASIGNACION ID

expresion:  
        expresion OPERADOR_SUMA termino
        | expresion OPERADOR_RESTA termino
        | termino
        ;


termino:
        termino OPERADOR_MULTIPLICACION factor
        | termino OPERADOR_DIVISION factor
        | factor
        ;


factor:     
        ID
        | literal_entero
        | literal_real
        | PARENTESIS_ABRE expresion PARENTESIS_CIERRA
        ;

现在,当它到达 ID OPERADOR_ASIGNACION 连接并查看“连接”的规则时,它会得到:

concatenacion:
        ID OPERADOR_SUMA ID 
        | ID OPERADOR_SUMA literal_string 
        | literal_string OPERADOR_SUMA ID 
        | literal_string OPERADOR_SUMA literal_string
        ;

其中两个以“ID”开头。因此,如果选择了这两个规则中的任何一个,它就会进入一个可以获取ID OPERADOR_ASIGNACION ID的状态,只有使用“concatenacion”规则,它需要在之后找到一个“OPERADOR_SUMA”令牌.但我相信一旦它看到“连接”和“表达式”都可以形成 ID OPERADOR_ASIGNACION ID 表达式,它就会窒息。
如果这不完全是怎么回事,我想知道那是什么问题。
而且,如果我在错误发生的位置是正确的,我真的不知道如何解决它。
请帮忙:)

谢谢!

【问题讨论】:

    标签: grammar bison


    【解决方案1】:

    问题出在:

    asignacion
        :   ID OPERADOR_ASIGNACION concatenacion
        |   ID OPERADOR_ASIGNACION expresion
        ;
    

    以及选择的替代方案:

    expresion
        :   expresion OPERADOR_SUMA termino
        ;
    
    termino
        :   factor
        ;
    
    factor
        :   ID
        ;
    
    concatenacion
        :   ID OPERADOR_SUMA ID
        ;
    

    这意味着当你的解析器遇到:

    x = y + z
    

    它无法判断它是在处理asignacion 的第一个备选方案还是第二个备选方案。

    这是最简单的部分。怎么修?最简单的修复(如果它有效,我还没有测试过)是删除我展示的concatenacion 规则,并在expresion 规则中,识别您何时处理concatenacionexpresion因为它们在语法上是相同的:

    ID OPERADOR_SIGNACION ID OPERADOR_SUM ID
    

    您会查看expresion 的两个操作数的类型,如果它们都是字符串类型,那么您会假设它是concatenacion,否则是expresion

    不过,您可能想查看整个concatenacion 规则。我认为你需要让字符串通过factor 规则,所以你需要添加另一个替代factor

    factor
       :   literal_string
       ;
    

    不过,这意味着您必须在其他规则中拒绝文字字符串,因此需要进行更多的语义检查。另一种方法是引入+ 以外的单独运算符来表示“字符串连接”。 SQL 使用||;一些语言使用了,;您可以完全使用另一个令牌,例如 @。一旦你脱离+,就有很多选择。你甚至可以只使用'两个相邻的字符串表达式意味着连接操作',它们之间没有运算符吗?

    如果这些都不起作用,请回复我。

    【讨论】:

    • 谢谢!你真是个天才!我真的看不出那里的歧义!我刚刚更改了连接运算符,它神奇地起作用了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多