3

语法:http : //pastebin.com/ef2jt8Rg y.输出:http ://pastebin.com/AEKXrrRG

我不知道这些冲突在哪里,有人可以帮我解决这个问题吗?

4

2 回答 2

8

y.output 文件会告诉您冲突的确切位置。第一个处于状态 4,因此如果您向下查看状态 4,您会看到:

state 4

   99 compound_statement: '{' . '}'
  100                   | '{' . statement_list '}'

    IDENTIFIER      shift, and go to state 6
          :
    IDENTIFIER  [reduce using rule 1 (threat_as_ref)]
    IDENTIFIER  [reduce using rule 2 (func_call_start)]

这告诉您,在这种状态下(解析 a compound_statement,已经看到 a {),并查看下一个标记是IDENTIFIER,它可以做 3 件可能的事情 - 移动标记(这将是 a 的开头statement_list),减少threat_as_ref空生产,或减少func_call_start空生产。

方括号告诉您它已决定永远不执行这些操作——默认的“优先转换而不是减少”冲突解决意味着它将始终执行转换。

您的语法的问题是这些空规则threat_as_ref,并且func_call_start- 在移动标识符之前需要减少它们,但是为了知道它们是否有效,解析器需要在标识符之后查看标记。 func_call_start仅当这是函数调用的开始时才应减少(这取决于(IDENTIFIER 之后是否存在)。因此解析器需要更多的前瞻来处理您的语法。在您的具体情况下,您的语法是 LALR(2)(2 个标记前瞻就足够了),但不是 LALR(1),所以野牛无法处理它。

现在您可以通过摆脱那些空规则来解决它——func_call_start根本没有任何操作,并且操作 forthreat_as_ref可以移动到操作 for 中variable,但是如果您将来想要这些规则,这可能是个问题。

于 2012-06-19T18:48:29.923 回答
0

(1) 我至少看到一件事看起来很奇怪。您的作品 与的作品expression_statement相似postfix_statement,但并不完全相同。他们没有 '(' 和 ')' 标记:

expression_statement
    : ';'
    | expression ';'
    | func_call_start IDENTIFIER { ras_parse_variable_psh($2); aFree($2); } func_call_end ';'
    | func_call_start IDENTIFIER { ras_parse_variable_psh($2); aFree($2); } argument_expression_list func_call_end ';'
    ;

由于 anexpression可以是 a primary_expression,它可以是 an IDENTIFIER,并且因为func_call_startandfunc_call_end是 epsilon (null) 产生式,当出现输入时

foo;

解析器必须决定是否应用

expression_statement : expression ';'

或者

expression_statement :  func_call_start IDENTIFIER { ras_parse_variable_psh($2); aFree($2); } func_call_end ';'

(2) 另外,我不确定这一点,但我怀疑 epsilon 非终端threat_as_ref可能会给您带来一些麻烦。我没有跟踪它,但可能存在解析器必须决定某事物是 avariable_ref还是 a 的情况variable

于 2012-06-19T14:10:57.540 回答