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
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 term
s 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 ')'