1

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         
    ;
user1603454
  • 99
  • 1
  • 8

1 Answers1

1

Normal style is to use lower case for non-terminals and upper case for terminals; using upper case indiscriminately makes your grammar harder to read (at least for those of us used to normal yacc/bison style). So I've written this answer without so much recourse to the caps lock key.

The basic issue is the production

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 '+'

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.

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.

rici
  • 234,347
  • 28
  • 237
  • 341