0

我正在为一种简单的编程语言构建这个语法(已经解决了以前的歧义问题:无法弄清楚为什么 Bison 会抛出“由于冲突而导致解析器中无用的规则”)。

这是我的完整语法: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的状态,只有在使用“连接”规则的情况下,它需要在之后找到一个“OPERADOR_SUMA”令牌。但我相信一旦它看到“连接”和“表达式”都可以形成ID OPERADOR_ASIGNACION ID表达式,它就会窒息。
如果这不完全是怎么回事,我想知道那是什么问题。
而且,如果我在错误发生的地方是正确的,我真的不知道如何解决它。
请帮助:)

谢谢!

4

1 回答 1

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规则中识别你何时处理 a concatenacionvs anexpresion因为它们在语法上是相同的:

ID OPERADOR_SIGNACION ID OPERADOR_SUM ID

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

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

factor
   :   literal_string
   ;

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

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

于 2013-11-13T03:28:19.323 回答