yacc中的移位/减少错误 [英] shift/reduce error in yacc

查看:95
本文介绍了yacc中的移位/减少错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道语法的这一部分会导致错误,但是我不知道如何解决它,我什至都使用%left和right,但这没有帮助.任何人都可以帮助我找出该语法的问题吗.预先感谢您的帮助.

I know this part of my grammar cause error but I don't know how to fix it I even use %left and right but it didn't help. Can anybody please help me to find out what is the problem with this grammar. Thanks in advance for your help.

%token VARIABLE NUM
%right '='
%left '+' '-' 
%left '*' '/' 
%left '^'
%start S_PROOP

EQUATION_SEQUENCE 
    : FORMULA '=' EQUATION   
    ;
EQUATION 
    : FORMULA
    | FORMULA '=' EQUATION
    ;
FORMULA 
    : SUM EXPRESSION 
    | PRODUCT EXPRESSION 
    | EXPRESSION '+' EXPRESSION 
    | EXPRESSION '*' EXPRESSION
    | EXPRESSION '/' EXPRESSION
    | EXPRESSION '^' EXPRESSION
    | EXPRESSION '-' EXPRESSION 
    | EXPRESSION
    ;
EXPRESSION 
    : EXPRESSION EXPRESSION
    | '(' EXPRESSION ')'
    | NUM
    | VARIABLE         
    ;

推荐答案

普通样式是对非终端使用小写字母,对终端使用大写字母;不加选择地使用大写字母会使您的语法更难阅读(至少对于习惯于普通yacc/bison风格的语法而言).因此,我写这个答案时并没有太多使用大写锁定键.

基本问题是生产

expression: expression expression

显然是模棱两可的,因为它不提供任何关联性指示.在这一点上,它与

which is obviously ambiguous, since it does not provide any indication of associativity. In that, it is not different from

expression: expression '+' expression

但是可以使用优先级声明解决该冲突:

but that conflict can be resolved using a precedence declaration:

%left '+'

区别在于,第一个产品没有任何终端符号,这使得不可能使用优先级规则来消除歧义:在yacc/野牛中,优先级始终是潜在减少量和潜在转移之间的比较.潜在的减少是一些可以减少的生产;潜在的转移是一个终端符号,可能会扩大产量.由于电位平移必须是终端符号,因此优先声明中使用了该符号.默认情况下,电位降低的优先级由右侧的最后一个端子符号定义,但是可以使用%prec 标记指定其他端子.无论如何,优先级关系都包含一个终端符号,如果语法允许两个终端并列,则没有相关的终端符号.

The difference is that the first production does not have any terminal symbol, which makes it impossible to use precedence rules to disambiguate: in yacc/bison, precedence is always a comparison between a potential reduction and a potential shift. The potential reduction is some production which could be reduced; the potential shift is a terminal symbol which might be able to extend some production. Since the potential shift must be a terminal symbol, that is what is used in the precedence declaration; by default, the precedence of the potential reduction is defined by the last terminal symbol in the right-hand side but it is possible to specify a different terminal using a %prec marker. In any case, the precedence relation involves a terminal symbol, and if the grammar allows juxtaposition of two terminals, there is no relevant terminal symbol.

这很容易解决,因为您没有义务使用优先级来解决冲突.您可以避免冲突:

That's easy to work around, since you are under no obligation to use precedence to resolve conflicts. You could just avoid the conflict:

/* Left associative rule */
expr_sequence: expr | expr_sequence expr

/* Alternative: right associative rule */
expr_sequence: expr | expr expr_sequence

由于没有迹象表明您打算通过哪种方式进行并置,因此我无法推荐上述一种或多种选择,但是通常我会倾向于第一种.

Since there is no indication what you intend by the juxtaposition, I'm unable to recommend one or the other of the above alternatives, but normally I would incline towards the first one.

equation_sequence 的语法没有太大不同,尽管 equation_sequence 实际上使用了一个终端符号,因此可以通过优先声明来处理.值得注意的是, equation_sequence 按书面形式是右关联的.通常认为这对赋值运算符是正确的,( a = b = c + 3 在C之类的语言中被解析为 a =(b = c + 3)和而不是(a = b)= c + 3 ,从而使赋值成为少数几个右关联运算符之一.)但是,如果您将 = 用作相等运算符,它将可能实际上不是您想要的.

That's not terribly different from your grammar for equation_sequence, although equation_sequence actually uses a terminal symbol so it could have been handled with a precedence declaration. It's worth noting that equation_sequence, as written, is right-associative. That's usually considered correct for assignment operators, (a = b = c + 3, in a language like C, is parsed as a = (b = c + 3) and not as (a = b) = c + 3, making assignment one of the few right-associative operators.) But if you are using = as an equality operator, it might not actually be what you intended.

这篇关于yacc中的移位/减少错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆