I’m programming a simple calculator in Bison & Flex , using C/C++ (The logic is done in Bison , and the C/C++ part is responsible for the data structures , e.g. STL and more) .
I have the following problem :
In my calculator the dollar sign $ means i++ and ++i (both prefix and postfix) , e.g. :
int y = 3;
-> $y = 4
-> y$ = 4
When the user hits : int_expression1 && int_expression2 , if int_expression1 is evaluated to 0 (i.e. false) , then I don’t wan’t bison to evaluate int_expression2 !
For example :
int a = 0 ;
int x = 2 ;
and the user hits : int z = a&&x$ …
So , the variable a is evaluated to 0 , hence , I don’t want to evaluate x , however it still grows by 1 … here is the code of the bison/c++ :
%union
{
int int_value;
double double_value;
char* string_value;
}
%type <int_value> int_expr
%type <double_value> double_expr
%type <double_value> cmp_expr
int_expr:
| int_expr '&&' int_expr { /* And operation between two integers */
if ($1 == 0)
$$ = 0;
else // calc
$$ = $1 && $3;
}
How can I tell bison to not evaluate the second expression , if the first one was already evaluated to false (i.e. 0) ?
Converting extensive commentary into an answer:
It’s your code that does the evaluation, not Bison; put the ‘blame’ where it belongs.
You need to detect that you’re dealing with an
&&rule before the RHS is evaluated. The chances are that you need to insert some code after the&&and before the secondint_exprthat suspends evaluation if the firstint_exprevaluates to 0. You’ll also need to modify all the other evaluation code to check for and obey a ‘do not evaluate’ flag.Alternatively, you have the Bison do the parsing and create a program that you execute when the parse is complete, rather than evaluating as you parse. That is a much bigger set of changes.
You have to write your code so that it does not evaluate when it is not supposed to evaluate. The Bison syntax is:
‘Code 1’ will check on
$1and arrange to stop evaluating (set a global variable or something similar). ‘Code 2’ will conditionally evaluate$4(4 because ‘code 1’ is now $3). All evaluation code must obey the dictates of ‘code 1’ — it must not evaluate if ‘code 1’ says ‘do not evaluate’. Or you can do what I suggested and aselle suggested; parse and evaluate separately.I second aselle’s suggestion about The UNIX Programming Environment. There’s a whole chapter in there about developing a calculator (they call it
hocfor higher-order calculator) which is worth reading. Be aware, though, that the book was published in 1984, and pre-dates the C standard by a good margin. There are no prototypes in the C code, and (by modern standards) it takes a few liberties. I do havehoc6(the last version ofhocthey describe; also versions 1-3) in modern C — contact me if you want it (see my profile).You can stop evaluating in the middle of a rule, but you have to code your expression evaluation code block to take the possibility into account. And when I said ‘stop evaluating’, I meant ‘stop doing the calculations’, not ‘stop the parser in its tracks’. The parsing must continue; your code that calculates values must only evaluate when evaluation is required, not when no evaluation is required. This might be an (ugh!) global flag, or you may have some other mechanism.
It’s probably best to convert your parser into a code generator and execute the code after you’ve parsed it. This sort of complication is why that is a good strategy.
Now it is an answer.