语法:http://pastebin.com/ef2jt8Rg y.output:http://pastebin.com/AEKXrrRG
我不知道那些冲突在哪里,有人可以帮我解决这个问题吗?
答案 0 :(得分:7)
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)]
这告诉你,在这种状态下(解析compound_statement
,看到{
),并查看下一个令牌是IDENTIFIER
,它可能有3种可能do - 移动令牌(这将是statement_list
的开头),减少threat_as_ref
空制作,或减少func_call_start
空制作。
括号告诉您它已经决定永远不会执行这些操作 - 默认的“更喜欢转换减少”冲突解决方案意味着它将始终进行转换。
你的语法问题是这些空的规则threat_as_ref
和func_call_start
- 在转移IDENTIFIER之前需要减少它们,但是为了知道它们是否有效,解析器需要在识别之后看到令牌。只有当这是函数调用的开始时才会减少func_call_start
(这取决于IDENTIFIER之后是(
。)因此解析器需要更多的前瞻来处理你的gramar。在你的特定情况下,你的语法是LALR(2)(2个令牌前瞻就足够了),但不是LALR(1),所以野牛不能处理它。
现在你可以通过删除那些空的规则来修复它 - func_call_start
根本没有任何操作,threat_as_ref
的操作可以移动到variable
的操作中,但如果您希望将来这些规则可能存在问题。
答案 1 :(得分: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 ';'
;
由于expression
可以是primary_expression
,可以是IDENTIFIER
,因为func_call_start
和func_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
可能会给你带来一些麻烦。我没有追踪它,但可能有一种情况,解析器必须决定某些东西是variable_ref
还是variable
。