Search code examples
parsingcompiler-errorscompiler-constructionbison

rules for unary operators in bison


I am trying to write bison expression for arithmetic operations, and for unary operators. the rules for unary operator should be

--6 is not accepted, but -(-6) accepted

4--5 and 4+-5 are not accepted, but 4-(-5) accepted

4*-5 and 4/-5 are not accepted, but 4*(-5) accepted

3- is not accepted

-3*4 is accepted

the rules are

line
    : assign '\n'            {      
                    long temp=eval($1); 
                LIST_EXPR[count-1].value=temp;
                LIST_EXPR[count-1].flag=1;
                printf("   %ld\n", LIST_EXPR[count-1].value);
            }
    ;

assign
: VAR '=' expr           { $$ = make_binop(EQUAL, BINOP_EXPR, make_var($1), $3); add_to_list_expr($3,count); count++;}
| expr          {add_to_list_expr($1,count); count++;}
;

expr
: expr '+' term          { $$ = make_binop(PLUS,BINOP_EXPR, $1, $3);}
| expr '-' term          { $$ = make_binop(MINUS,BINOP_EXPR, $1, $3);}
| term
;

term
: term '*' factor        { $$ = make_binop(TIME,BINOP_EXPR, $1, $3);}
| term '/' factor        { $$ = make_binop(DIV,BINOP_EXPR, $1, $3); }
| term '%' factor        { $$ = make_binop(MOD,BINOP_EXPR, $1, $3); }
| factor
| pre
;

pre: 
  '-' factor         {$$=make_binop(UMINUS,BINOP_EXPR, $2, NULL);}
| '+' factor         {$$=make_binop(UPLUS,BINOP_EXPR, $2, NULL);}
;

factor
: '(' expr ')'           { $$ = $2; }
| CONST          { $$ = make_const($1); }
| VAR                    { $$ = make_var($1); }
| '#' factor         {$$=make_binop(LINE_REF,BINOP_EXPR, $2, NULL);}
;

the problem is when the unary come in the right side it is accepted, for example 3--4 it is accepted, while it should not be accepted. this problem occur just with + and - operation.

Does anyone know how to solve it


Solution

  • Your grammar has:

    expr: expr '-' term
    term: pre
    pre : '-' factor
    

    So 3--4 must be accepted; -4 is reduced to pre and then term, and then 3--4 has become expr - term, which reduces to expr.

    Similarly -3*4 will reduce -3 to pre and then term, after which it can be used to reduce -3*4 to term, by using term: term '*' factor.

    It is unclear to me why you want 3--4 to be invalid, while you are willing to accept -3-4 as well as -3*4. 3--4 is not, imho, any more or less confusing than those other two, and it does not create any ambiguities.

    But if that's what you want, you could achieve it by distinguishing the terms which can be unary expressions, and those that cannot (untested):

    expr : expr '+' rterm
         | expr '-' rterm
         | term
    rterm: term '*' factor
         | term '/' factor
         | term '%' factor
         | factor
    term : rterm | pre
    pre  : '-' factor | '+' factor
    factor: VAR | CONST | '#' factor | '(' expr ')'