1

我知道我的语法的这一部分会导致错误,但我不知道如何解决它我什至使用 %left 和 right 但它没有帮助。谁能帮我找出这个语法有什么问题。在此先感谢您的帮助。

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

1 回答 1

1

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

基本问题是生产

expression: expression expression

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

expression: expression '+' expression

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

%left '+'

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

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

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

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

由于并列没有表明您的意图,因此我无法推荐上述替代方案中的一个或另一个,但通常我会倾向于第一个。

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

于 2016-04-18T15:37:22.600 回答