Под покровом yacc действительно поддерживает действия только в конце производства. Поэтому, когда вы чередуете действие { PL_parser->expect = XSTATE; }
в середине производства, yacc (или любой другой потомок, которого вы используете) вытаскивает действие и прикрепляет его в конце пустого правила как таковое:
grammar: GRAMPROG $$1 remember stmtmseq
{
newPROG(block_end($3, $4));
$$ = 0;
}
$$1:
{
PL_parser->expect = XSTATE;
}
(Если ваш вариант yacc поддерживает сброс многословной грамматики, и вы делаете это, вы увидите множество правил $$ 1, $$ 2 и т. Д. Для действий.)
В этом случае чередованное действие фактически не назначает ничего для $$
, но если бы оно имело, правило grammar
могло бы получить доступ к значению как $2
.