Это естественно. Вы анализируете оператор print, поэтому выполняется cout. То, что вы хотите сделать, это создать какой-то байт-код, где вы храните инструкцию печати. Эту инструкцию печати можно затем объединить с выражением if для формирования инструкции if-Statement.
Вдобавок ко всему, я не могу вспомнить точные утверждения в Bison (вам нужно заглянуть в документацию), но вы, как правило, хотите определить тип для вашего стека значений, обычно объединение структур что-то вроде этого (хотя для него есть команда bison, которая сделает его типом для стека значений).
union {
int type;
struct {
int type; // must always be first, this is a union
union stmt *stmt; // conditional stmt to execute
union expr *expr; // expression to evaluate
} if_stmt;
struct {
int type;
} print_stmt;
} stmt;
Что позволит вам вставить правило в вашу грамматику, что-то вроде этого
stmt: IF '(' expr ')' stmt { $$.type = IF_STMT; $$.if_stmt.expr = copy ($3); $$.if_stmt.stmt = copy ($5); }
и т. Д. (Там может быть ошибка «один за другим», не помню, если $ s начинается с 0 или 1). Вам нужно будет самостоятельно реализовать функцию copy
для управления распределением памяти, bison предоставит только стек для значений. В конце концов у вас будет дерево (которое, как я считаю, обычно называется синтаксическим деревом), которое вы можете запустить для узлов с типом IF_STMT, evalute if_stmt.expr и, если оно вернет true, вычислить if_stmt.stmt, и т. д.
Затем, когда вы закончите синтаксический анализ вашего языка, вы можете «выполнить» свой байт-код, когда вы нажмете оператор if, оцените выражение, если оно истинно (а это не так), выполните оператор, как описано выше и затем, когда вы нажимаете на инструкцию print (что не произойдет, поскольку выражение ложно), вы печатаете свое «привет», и у вас есть результат, который вы ищете (то есть, ничего не печатается).
Это в значительной степени то, как вам нужно это делать. Вы не можете (легко) выполнить условное выполнение при разборе с бизоном.