MiniUnix/usr/doc/yacc/ssd
.SH
Appendix D: An Example of Bundling
.PP
The following program is an example of the technique of
bundling; this example is discussed in Section 7.
.LP
/* warnings:
.IP 1.
This works on Unix; the handling of functions with a
variable number of arguments is different on different systems.
.IP 2.
A number of checks for array bounds have been left out
to avoid obscuring the basic ideas, but should
be there in a practical program.
.PP
*/
.LD
%token NAME
%right \'=\'
%left \'+\' \'\-\'
%left \'*\' \'/\'
%%
lines :
= /* empty */
{
bclear( ) ;
} |
lines expr \'\en\' =
{
bprint( $2 ) ;
printf( "\en" ) ;
bclear( ) ;
} |
lines error \'\en\' =
{
bclear( ) ;
yyerrok;
} ;
expr :
expr \'+\' expr =
{
$$ = bundle( "add(", $1, ",", $3, ")" );
} |
expr \'\-\' expr =
{
$$ = bundle( "sub(", $1, ",", $3, ")" );
} |
expr \'*\' expr =
{
$$ = bundle( "mul(", $1, ",", $3, ")" );
} |
expr \'/\' expr =
{
$$ = bundle( "div(", $1, ",", $3, ")" );
} |
\'(\' expr \')\' =
{
$$ = $2;
} |
NAME \'=\' expr =
$$ = bundle( "assign(", $1, ",", $3, ")" );
} |
NAME ;
%%
#define nsize 200
char names[nsize], *nptr { names };
#define bsize 500
int bspace[bsize], *bptr { bspace };
yylex( )
{
int c;
c = getchar( );
while( c == \' \' )
c = getchar( );
if( c>=\'a\' && c<=\'z\' ) {
yylval = nptr;
for( ; c>=\'a\' && c<=\'z\'; c=getchar( ) )
*nptr++ = c;
ungetc( c );
*nptr++ = \'\e0\';
return( NAME );
}
return( c );
}
bclear( )
{
nptr = names;
bptr = bspace;
}
bundle( a1,a2,a3,a4,a5 )
{
int i, j, *p, *obp;
p = &a1;
i = nargs( );
obp = bptr;
for( j=0; j<i; ++j )
*bptr++ = *p++;
*bptr++ = 0;
return( obp );
}
bprint( p )
int *p;
{
if( p>=bspace && p< &bspace[bsize] ) /* bundle */
while( *p != 0 )
bprint( *p++ );
else printf( "%s", p );
}
.DE