BSD 3 development
[unix-history] / usr / doc / yacc / ss2
index 7d0efc6..6500602 100644 (file)
 .SH
 .SH
-Section 2: Actions
+2: Actions
 .PP
 .PP
-To each grammar rule, the user may associate an action to be performed each time
+With each grammar rule, the user may associate actions to be performed each time
 the rule is recognized in the input process.
 the rule is recognized in the input process.
-This action may return a value, and may obtain the values returned by previous
-actions in the grammar rule.
-In addition, the lexical analyzer can return values
+These actions may return values, and may obtain the values returned by previous
+actions.
+Moreover, the lexical analyzer can return values
 for tokens, if desired.
 .PP
 for tokens, if desired.
 .PP
-When invoking Yacc, the user specifies a programming language; currently, Ratfor and C are supported.
-An action is an arbitrary statement in this language, and as such can do
+An action is an arbitrary C statement, and as such can do
 input and output, call subprograms, and alter
 input and output, call subprograms, and alter
-external vectors and variables (recall that a ``statement'' in both C and Ratfor can be compound
-and do many distinct tasks).
-An action is specified by an equal sign ``=''
-at the end of a grammar rule, followed by
+external vectors and variables.
+An action is specified by
 one or more statements, enclosed in curly braces ``{'' and ``}''.
 For example,
 .DS
 one or more statements, enclosed in curly braces ``{'' and ``}''.
 For example,
 .DS
-A: \'(\' B \')\' = { hello( 1, "abc" );  }
+A      :       \'(\'  B  \')\'
+                       {       hello( 1, "abc" );  }
 .DE
 and
 .DS
 .DE
 and
 .DS
-XXX: YYY ZZZ =
-       {
-               printf("a message\en");
-               flag = 25;
-       }
+XXX    :       YYY  ZZZ
+                       {       printf("a message\en");
+                               flag = 25;   }
 .DE
 .DE
-are grammar rules with actions in C.
-A grammar rule with an action need not end with a semicolon; in fact, it is an error to have a semicolon
-before the equal sign.
+are grammar rules with actions.
 .PP
 To facilitate easy communication between the actions and the parser, the action statements are altered
 slightly.
 The symbol ``dollar sign'' ``$'' is used as a signal to Yacc in this context.
 .PP
 To return a value, the action normally sets the
 .PP
 To facilitate easy communication between the actions and the parser, the action statements are altered
 slightly.
 The symbol ``dollar sign'' ``$'' is used as a signal to Yacc in this context.
 .PP
 To return a value, the action normally sets the
-pseudo-variable ``$$'' to some integer value.
-For example, an action which does nothing but return the value 1 is
+pseudo-variable ``$$'' to some value.
+For example, an action that does nothing but return the value 1 is
 .DS
 .DS
-= { $$ = 1; }
+       {  $$ = 1;  }
 .DE
 .PP
 To obtain the values returned by previous actions and the lexical analyzer, the
 .DE
 .PP
 To obtain the values returned by previous actions and the lexical analyzer, the
-action may use the (integer) pseudo-variables $1, $2, . . .,
+action may use the pseudo-variables $1, $2, . . .,
 which refer to the values returned by the
 components of the right side of a rule, reading from left to right.
 Thus, if the rule is
 .DS
 which refer to the values returned by the
 components of the right side of a rule, reading from left to right.
 Thus, if the rule is
 .DS
-A: B C D ;
+A      :       B  C  D   ;
 .DE
 for example, then $2 has the value returned by C, and $3 the value returned by D.
 .PP
 .DE
 for example, then $2 has the value returned by C, and $3 the value returned by D.
 .PP
-As a more concrete example, we might have the rule
+As a more concrete example, consider the rule
 .DS
 .DS
-expression: \'(\' expression \')\' ;
+expr   :       \'(\'  expr  \')\'   ;
 .DE
 .DE
-We wish the value returned by this rule to be the value of the expression in parentheses.
-Then we write
+The value returned by this rule is usually the value of the
+.I expr
+in parentheses.
+This can be indicated by
 .DS
 .DS
-expression: \'(\' expression \')\'    = { $$ = $2 ; }
+expr   :        \'(\'  expr  \')\'             {  $$ = $2 ;  }
 .DE
 .PP
 .DE
 .PP
-As a default, the value of a rule is the value of the first element in it ($1).
-This is true even if there is no explicit action given for the rule.
+By default, the value of a rule is the value of the first element in it ($1).
 Thus, grammar rules of the form
 .DS
 Thus, grammar rules of the form
 .DS
-A: B ;
+A      :       B    ;
 .DE
 .DE
-frequently need not have an explict action.
+frequently need not have an explicit action.
 .PP
 .PP
-Notice that, although the values of actions are integers, these integers may in fact
-contain pointers (in C) or indices into an array (in Ratfor); in this way,
-actions can return and reference more complex data structures.
-.PP
-Sometimes, we wish to get control before a rule is fully parsed, as well as at the
-end of the rule.
-There is no explicit mechanism in Yacc to allow this; the same effect can be obtained, however,
-by introducing a new symbol which matches the empty string, and inserting an action for this symbol.
-For example, we might have a rule describing an ``if'' statement:
+In the examples above, all the actions came at the end of their rules.
+Sometimes, it is desirable to get control before a rule is fully parsed.
+Yacc permits an action to be written in the middle of a rule as well
+as at the end.
+This rule is assumed to return a value, accessible
+through the usual \$ mechanism by the actions to
+the right of it.
+In turn, it may access the values
+returned by the symbols to its left.
+Thus, in the rule
 .DS
 .DS
-statement: IF \'(\' expr \')\' THEN statement
+A      :       B
+                       {  $$ = 1;  }
+               C
+                       {   x = $2;   y = $3;  }
+       ;
 .DE
 .DE
-Suppose that we wish to get control after seeing the right parenthesis
-in order to output some code.
-We might accomplish this by the rules:
-.DS
-statement:  IF \'(\' expr \')\' actn THEN statement 
-       = { call action1 }
-
-actn:   /* matches the empty string */
-       = { call action2 }
-.DE
-.PP
-Thus, the new nonterminal symbol actn matches no input, but serves only to call action2 after the
-right parenthesis is seen.
+the effect is to set
+.I x
+to 1, and
+.I y
+to the value returned by C.
 .PP
 .PP
-Frequently, it is more natural in such cases to break the rule into
-parts where the action is needed.
-Thus, the above example might also have been written
+Actions that do not terminate a rule are actually
+handled by Yacc by manufacturing a new nonterminal
+symbol name, and a new rule matching this
+name to the empty string.
+The interior action is the action triggered off by recognizing
+this added rule.
+Yacc actually treats the above example as if
+it had been written:
 .DS
 .DS
-statement:  ifpart THEN statement
-       = { call action1 }
+$ACT   :       /* empty */
+                       {  $$ = 1;  }
+       ;
 
 
-ifpart:      IF \'(\' expr \')\'
-       = { call action2 }
+A      :       B  $ACT  C
+                       {   x = $2;   y = $3;  }
+       ;
 .DE
 .PP
 In many applications, output is not done directly by the actions;
 rather, a data structure, such as a parse tree, is constructed in memory,
 and transformations are applied to it before output is generated.
 Parse trees are particularly easy to
 .DE
 .PP
 In many applications, output is not done directly by the actions;
 rather, a data structure, such as a parse tree, is constructed in memory,
 and transformations are applied to it before output is generated.
 Parse trees are particularly easy to
-construct, given routines which build and maintain the tree
+construct, given routines to build and maintain the tree
 structure desired.
 structure desired.
-For example, suppose we have a C function
-``node'', written so that the call
+For example, suppose there is a C function
+.I node ,
+written so that the call
 .DS
 node( L, n1, n2 )
 .DE
 .DS
 node( L, n1, n2 )
 .DE
-creates a node with label L, and descendants n1 and n2, and returns a pointer
-to the newly created node.
-Then we can cause a parse tree to be built by supplying actions such as:
+creates a node with label L, and descendants n1 and n2, and returns the index of
+the newly created node.
+Then parse tree can be built by supplying actions such as:
 .DS
 .DS
-expr: expr \'+\' expr 
-       = { $$ = node( \'+\', $1, $3 ); }
+expr   :       expr  \'+\'  expr  
+                       {  $$ = node( \'+\', $1, $3 );  }
 .DE
 .DE
-in our specification.
+in the specification.
 .PP
 The user may define other variables to be used by the actions.
 .PP
 The user may define other variables to be used by the actions.
-Declarations and definitions can appear in two places in the
-Yacc specification: in the declarations section, and at the head of the rules sections, before the
-first grammar rule.
-In each case, the declarations and definitions are enclosed in the marks ``%{'' and ``%}''.
-Declarations and definitions placed in the declarations section have global scope, 
-and are thus known to the action statements and the lexical analyzer.
-Declarations and definitions placed at the head of the rules section have scope local to
-the action statements.
-Thus, in the above example, we might have included
-.DS
-%{ int variable 0; %}
-.DE
-in the declarations section, or, perhaps,
+Declarations and definitions can appear in
+the declarations section,
+enclosed in the marks ``%{'' and ``%}''.
+These declarations and definitions have global scope, 
+so they are known to the action statements and the lexical analyzer.
+For example,
 .DS
 .DS
-%{ static int variable; %}
+%{   int variable = 0;   %}
 .DE
 .DE
-at the head of the rules section.
-If we were writing Ratfor actions, we might want to include some
-COMMON statements at the beginning of the rules section, to allow for
-easy communication between the actions and other routines.
-For both C and Ratfor, Yacc has used only external names beginning in ``yy'';
+could be placed in the declarations section,
+making
+.I variable
+accessible to all of the actions.
+The Yacc parser uses only names beginning in ``yy'';
 the user should avoid such names.
 the user should avoid such names.
+.PP
+In these examples, all the values are integers: a discussion of
+values of other types will be found in Section 10.