10.6 Embedded Actions

There are times when you want to perform an action before you get to the end of the right-hand side of a production.

You can do that by creating a nonterminal that has only one production, an erasing production, and attaching the action to the end of that production.

For example, you can set variables that indicate context, or you can perform initializations.

expr : TOK_FOO  initForFoo
       expr  TOK_ENDFOO
         {
            printf("Foo %d\n", $4);
            insideFoo = 0;
         }

…
     ;

initForFoo : /* empty *.
               {
                 insideFoo = 1;
               }
           ;

That kind of thing is sufficiently common that Bison has a convenient way to do it. Just write an action in place of a token or nonterminal. So you can write

expr : TOK_FOO 
         {
           insideFoo = 1;
         }
       expr TOK_ENDFOO
         {
            printf("Foo %d\n", $4);
            insideFoo = 0;
         }
…
     ;

Bison replaces the extra action by a new nonterminal and creates an erasing production for it. Consequently, the extra action counts as one of the things on the right-hand side of the production.

So TOK_ENDFOO is still $4. $2 refers to the second thing, which is the automatically create nonterminal.