我如何强迫Bison转移以解决冲突?

时间:2013-11-13 00:15:26

标签: grammar bison

我正在为一种简单的编程语言构建这种语法(已经解决了以前的歧义问题: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得到一个班次/减少错误(我正在翻译它):

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)

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

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

它看到从“expresion”它可以获得一个ID令牌(expresion> termino> factor> 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 并查看“concatenacion”的规则时,它会得到:

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”令牌。 。但是我认为,一旦它看到“concatenacion”和“expresion”都可以形成 ID OPERADOR_ASIGNACION ID 表达式,它就会窒息。
如果这不是正在发生的事情,我想知道那是什么问题。
而且,如果我在错误发生的地方是正确的,我真的不知道如何解决它。
请帮忙:)

谢谢!

1 个答案:

答案 0 :(得分:2)

问题来自:

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规则中识别您何时处理{{1} } vs concatenacion因为它们在语法上是相同的:

expresion

你会看到ID OPERADOR_SIGNACION ID OPERADOR_SUM ID 的两个操作数的类型,如果它们都是字符串类型,那么你假设它是expresion,否则是concatenacion }。

您可能希望查看整个expresion规则。我认为您需要通过concatenacion规则设置字符串,因此您需要为factor添加另一种替代方法:

factor

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

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