yacc actions

With each grammar rule, you can specify actions to be performed each time the parser recognizes the rule in the input stream. An action is a C language statement that does input and output, calls subprograms, and alters external vectors and variables.

Actions return values and obtain the values returned by previous actions. The lexical analyzer can also return values for tokens.

Specify an action in the grammar file with one or more statements enclosed in {} (braces). The following examples are grammar rules with actions:
A  :  '('B')'
   {
     hello(1, "abc" );
   }
AND
XXX  :  YYY  ZZZ
     {
     printf("a message\n");
     flag = 25;
     }

Passing Values between Actions

To get values generated by other actions, an action can use the yacc parameter keywords that begin with a dollar sign ($1, $2, ... ). These keywords refer to the values returned by the components of the right side of a rule, reading from left to right. For example, if the rule is:
A  :  B  C  D  ;

then $1 has the value returned by the rule that recognized B, $2 has the value returned by the rule that recognized C, and $3 the value returned by the rule that recognized D.

To return a value, the action sets the pseudo-variable $$ to some value. For example, the following action returns a value of 1:
{ $$ = 1;}
By default, the value of a rule is the value of the first element in it ($1). Therefore, you do not need to provide an action for rules that have the following form:
A : B ;

The following additional yacc parameter keywords beginning with a $ (dollar sign) allow for type-checking:

  • $<Tag>$
  • $<Tag>Number

$<Tag>Number imposes on the reference the type of the union member referenced by <Tag>. This adds .tag to the reference so that the union member identified by Tag is accessed. This construct is equivalent to specifying $$.Tag or $1.Tag. You can use this construct when you use actions in the middle of rules where the return type cannot be specified through a %type declaration. If a %type has been declared for a nonterminal name, do not use the <Tag> construct; the union reference will be done automatically.

Putting actions in the middle of rules

To get control of the parsing process before a rule is completed, write an action in the middle of a rule. If this rule returns a value through the $ keywords, actions that follow this rule can use that value. This rule can also use values returned by actions that precede it. Therefore, the following rule sets x to 1 and y to the value returned by C. The value of rule A is the value returned by B, following the default rule.
A  :  B
        {
           $$ =1;
        }
        C
   {
        x = $2;
        y = $3;
   }
   ;
Internally, the yacc command creates a new nonterminal symbol name for the action that occurs in the middle. It also creates a new rule matching this name to the empty string. Therefore, the yacc command treats the preceding program as if it were written in the following form:
$ACT  :  /* empty */
      {
         $$ = 1;
      }
      ;
A     :  B  $ACT  C
      {
         x = $2;
         y = $3;
      }
      ;

where $ACT is an empty action.