在yacc

时间:2016-04-17 21:12:00

标签: grammar yacc shift-reduce-conflict

我知道这部分语法错误但我不知道如何修复它我甚至使用%左右但它没有帮助。任何人都可以帮我找出这个语法有什么问题。 在此先感谢您的帮助。

%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         
    ;

1 个答案:

答案 0 :(得分:0)

正常的风格是对于非终端使用小写,对终端使用大写;不加选择地使用大写字母会使你的语法难以阅读(至少对于我们这些习惯于常规yacc / bison风格的人来说)。所以我没有那么多地使用大写锁定键来写这个答案。

基本问题是制作

expression: expression expression

这显然是模棱两可的,因为它没有提供任何关联性的指示。在那,它与

没有什么不同
expression: expression '+' expression

但可以使用优先声明来解决冲突:

%left '+'

不同之处在于第一个产品没有任何终端符号,这使得无法使用优先规则来消除歧义:在yacc / bison中,优先级始终是潜在减少和潜在变化之间的比较。潜在的减少是一些可以减少的产量;潜在的转变是终极符号,可能能够扩展一些生产。由于潜在的移位必须是终端符号,因此优先级声明中使用的是;默认情况下,潜在减少的优先级由右侧的最后一个终端符号定义,但可以使用%prec标记指定不同的终端。在任何情况下,优先关系都涉及终端符号,如果语法允许并置两个终端,则没有相关的终端符号。

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

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

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

由于没有任何迹象表明您希望通过并置,我无法推荐上述其中一种或另一种,但通常我会倾向于第一种。

这与equation_sequence的语法没有太大的不同,尽管equation_sequence实际上使用了终端符号,因此可以使用优先声明进行处理。值得注意的是equation_sequence,正如所写的,是正确联想的。对于赋值运算符而言,这通常被认为是正确的,(a = b = c + 3,在像C这样的语言中,被解析为a = (b = c + 3)而不是(a = b) = c + 3,这使得任务成为少数几个权利之一 - 关联运算符。)但是如果你使用=作为相等运算符,它可能实际上并不是你想要的。