语法:http : //pastebin.com/ef2jt8Rg y.输出:http ://pastebin.com/AEKXrrRG
我不知道这些冲突在哪里,有人可以帮我解决这个问题吗?
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
,但是如果您将来想要这些规则,这可能是个问题。
(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_start
andfunc_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
。