yacc - 规则从未减少并且 shift/reduce 冲突
yacc - rules never reduced and shift/reduce conflicts
我在处理 yaac 时遇到了问题,因为我不断收到这条提示:
1 条规则从未减少。
29 shift/reduce 次冲突。
那么,有人可以帮我解决这个问题吗?
这是我正在研究的语法:
%start P
%token DEF IF THEN ELSE WHILE DO FOR
%token Punctuation_element
%token Operator
%token EQL_EQL GREATER_THAN_OR_EQUALS LESS_THAN_OR_EQUALS NOT_EQUALS
%token<sval> Identifier
%token<ival> Literal
%left '-' '+'
%left '*' '/' '%'
%right ELSE
%%
P : D ';' P
| D
;
D : DEF Identifier '(' ARGS ')' '=' E ';'
;
ARGS: Identifier ',' ARGS
| Identifier
;
E: Literal
| Identifier
| IF E OP E THEN E ELSE E
| FOR E DO E
| DO E WHILE E
| E '+' E
| E '-' E
| E '*' E
| E '/' E
| E '%' E
| Identifier '(' E ')'
| E ',' E
;
/* C: E ',' C
| E
; */
OP: EQL_EQL
| '>'
| '<'
| GREATER_THAN_OR_EQUALS
| LESS_THAN_OR_EQUALS
| NOT_EQUALS
| '%'
;
你有两个基本问题:
%
既是比较运算符 (OP
) 又是算术运算符 (E '%' E
)。这造成了歧义,bison 解决了支持算术运算符的问题,因为 bison 更喜欢 shift 而不是 reduce。该分辨率使得无法减少 OP : '%'
,这是不减少的规则。
您使 ,
成为算术运算符 (E ',' E
),但您没有为其声明优先级。这导致大量移位减少了涉及 ,
和另一个运算符的表达式的冲突。我怀疑您是否真的希望 ,
成为操作员;我认为您添加了涉及它的产生式是为了允许使用多个参数调用函数。那是行不通的。为参数列表创建一个单独的非终端,并在函数调用的生产中使用它而不是使用 E
.
(其实你有这样一个非终结符,神秘的叫C
,但是它被注释掉了,没有被使用,所以取消注释,使用它。并考虑给它起一个更有意义的名字。)
像 bison 这样的 LALR 解析器生成器通常更喜欢左递归而不是右递归。您应该考虑将您的两个列表产生式(C
和 ARGS
)更改为左递归,除非您有充分的理由不这样做。
我在处理 yaac 时遇到了问题,因为我不断收到这条提示:
1 条规则从未减少。 29 shift/reduce 次冲突。
那么,有人可以帮我解决这个问题吗?
这是我正在研究的语法:
%start P
%token DEF IF THEN ELSE WHILE DO FOR
%token Punctuation_element
%token Operator
%token EQL_EQL GREATER_THAN_OR_EQUALS LESS_THAN_OR_EQUALS NOT_EQUALS
%token<sval> Identifier
%token<ival> Literal
%left '-' '+'
%left '*' '/' '%'
%right ELSE
%%
P : D ';' P
| D
;
D : DEF Identifier '(' ARGS ')' '=' E ';'
;
ARGS: Identifier ',' ARGS
| Identifier
;
E: Literal
| Identifier
| IF E OP E THEN E ELSE E
| FOR E DO E
| DO E WHILE E
| E '+' E
| E '-' E
| E '*' E
| E '/' E
| E '%' E
| Identifier '(' E ')'
| E ',' E
;
/* C: E ',' C
| E
; */
OP: EQL_EQL
| '>'
| '<'
| GREATER_THAN_OR_EQUALS
| LESS_THAN_OR_EQUALS
| NOT_EQUALS
| '%'
;
你有两个基本问题:
%
既是比较运算符 (OP
) 又是算术运算符 (E '%' E
)。这造成了歧义,bison 解决了支持算术运算符的问题,因为 bison 更喜欢 shift 而不是 reduce。该分辨率使得无法减少OP : '%'
,这是不减少的规则。您使
,
成为算术运算符 (E ',' E
),但您没有为其声明优先级。这导致大量移位减少了涉及,
和另一个运算符的表达式的冲突。我怀疑您是否真的希望,
成为操作员;我认为您添加了涉及它的产生式是为了允许使用多个参数调用函数。那是行不通的。为参数列表创建一个单独的非终端,并在函数调用的生产中使用它而不是使用E
.(其实你有这样一个非终结符,神秘的叫
C
,但是它被注释掉了,没有被使用,所以取消注释,使用它。并考虑给它起一个更有意义的名字。)
像 bison 这样的 LALR 解析器生成器通常更喜欢左递归而不是右递归。您应该考虑将您的两个列表产生式(C
和 ARGS
)更改为左递归,除非您有充分的理由不这样做。