home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
bbs
/
gnu
/
flex-2.4.6-src.lha
/
src
/
amiga
/
flex-2.4.6
/
gen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-04
|
33KB
|
1,454 lines
/* gen - actual generation (writing) of flex scanners */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Vern Paxson.
*
* The United States Government has rights in this work pursuant
* to contract no. DE-AC03-76SF00098 between the United States
* Department of Energy and the University of California.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* $Header: gen.c,v 1.2 94/01/04 14:33:12 vern Exp $ */
#include "flexdef.h"
/* declare functions that have forward references */
void gen_next_state PROTO((int));
void genecs PROTO((void));
void indent_put2s PROTO((char [], char []));
void indent_puts PROTO((char []));
static int indent_level = 0; /* each level is 8 spaces */
#define indent_up() (++indent_level)
#define indent_down() (--indent_level)
#define set_indent(indent_val) indent_level = indent_val
/* Almost everything is done in terms of arrays starting at 1, so provide
* a null entry for the zero element of all C arrays. (The exception
* to this is that the fast table representation generally uses the
* 0 elements of its arrays, too.)
*/
static char C_int_decl[] = "static const int %s[%d] =\n { 0,\n";
static char C_short_decl[] = "static const short int %s[%d] =\n { 0,\n";
static char C_long_decl[] = "static const long int %s[%d] =\n { 0,\n";
static char C_state_decl[] =
"static const yy_state_type %s[%d] =\n { 0,\n";
/* Indent to the current level. */
void do_indent()
{
register int i = indent_level * 8;
while ( i >= 8 )
{
putchar( '\t' );
i -= 8;
}
while ( i > 0 )
{
putchar( ' ' );
--i;
}
}
/* Generate the code to keep backing-up information. */
void gen_backing_up()
{
if ( reject || num_backing_up == 0 )
return;
if ( fullspd )
indent_puts( "if ( yy_current_state[-1].yy_nxt )" );
else
indent_puts( "if ( yy_accept[yy_current_state] )" );
indent_up();
indent_puts( "{" );
indent_puts( "yy_last_accepting_state = yy_current_state;" );
indent_puts( "yy_last_accepting_cpos = yy_cp;" );
indent_puts( "}" );
indent_down();
}
/* Generate the code to perform the backing up. */
void gen_bu_action()
{
if ( reject || num_backing_up == 0 )
return;
set_indent( 3 );
indent_puts( "case 0: /* must back up */" );
indent_puts( "/* undo the effects of YY_DO_BEFORE_ACTION */" );
indent_puts( "*yy_cp = yy_hold_char;" );
if ( fullspd || fulltbl )
indent_puts( "yy_cp = yy_last_accepting_cpos + 1;" );
else
/* Backing-up info for compressed tables is taken \after/
* yy_cp has been incremented for the next state.
*/
indent_puts( "yy_cp = yy_last_accepting_cpos;" );
indent_puts( "yy_current_state = yy_last_accepting_state;" );
indent_puts( "goto yy_find_action;" );
putchar( '\n' );
set_indent( 0 );
}
/* genctbl - generates full speed compressed transition table */
void genctbl()
{
register int i;
int end_of_buffer_action = num_rules + 1;
/* Table of verify for transition and offset to next state. */
printf( "static const struct yy_trans_info yy_transition[%d] =\n",
tblend + numecs + 1 );
printf( " {\n" );
/* We want the transition to be represented as the offset to the
* next state, not the actual state number, which is what it currently
* is. The offset is base[nxt[i]] - (base of current state)]. That's
* just the difference between the starting points of the two involved
* states (to - from).
*
* First, though, we need to find some way to put in our end-of-buffer
* flags and states. We do this by making a state with absolutely no
* transitions. We put it at the end of the table.
*/
/* We need to have room in nxt/chk for two more slots: One for the
* action and one for the end-of-buffer transition. We now *assume*
* that we're guaranteed the only character we'll try to index this
* nxt/chk pair with is EOB, i.e., 0, so we don't have to make sure
* there's room for jam entries for other characters.
*/
while ( tblend + 2 >= current_max_xpairs )
expand_nxt_chk();
while ( lastdfa + 1 >= current_max_dfas )
increase_max_dfas();
base[lastdfa + 1] = tblend + 2;
nxt[tblend + 1] = end_of_buffer_action;
chk[tblend + 1] = numecs + 1;
chk[tblend + 2] = 1; /* anything but EOB */
/* So that "make test" won't show arb. differences. */
nxt[tblend + 2] = 0;
/* Make sure every state has an end-of-buffer transition and an
* action #.
*/
for ( i = 0; i <= lastdfa; ++i )
{
int anum = dfaacc[i].dfaacc_state;
int offset = base[i];
chk[offset] = EOB_POSITION;
chk[offset - 1] = ACTION_POSITION;
nxt[offset - 1] = anum; /* action number */
}
for ( i = 0; i <= tblend; ++i )
{
if ( chk[i] == EOB_POSITION )
transition_struct_out( 0, base[lastdfa + 1] - i );
else if ( chk[i] == ACTION_POSITION )
transition_struct_out( 0, nxt[i] );
else if ( chk[i] > numecs || chk[i] == 0 )
transition_struct_out( 0, 0 ); /* unused slot */
else /* verify, transition */
transition_struct_out( chk[i],
base[nxt[i]] - (i - chk[i]) );
}
/* Here's the final, end-of-buffer state. */
transition_struct_out( chk[tblend + 1], nxt[tblend + 1] );
transition_struct_out( chk[tblend + 2], nxt[tblend + 2] );
printf( " };\n" );
printf( "\n" );
/* Table of pointers to start states. */
printf(
"static const struct yy_trans_info *yy_start_state_list[%d] =\n",
lastsc * 2 + 1 );
printf( " {\n" ); /* } so vi doesn't get confused */
for ( i = 0; i <= lastsc * 2; ++i )
printf( " &yy_transition[%d],\n", base[i] );
dataend();
if ( useecs )
genecs();
}
/* Generate equivalence-class tables. */
void genecs()
{
Char clower();
register int i, j;
int numrows;
printf( C_int_decl, "yy_ec", csize );
for ( i = 1; i < csize; ++i )
{
if ( caseins && (i >= 'A') && (i <= 'Z') )
ecgroup[i] = ecgroup[clower( i )];
ecgroup[i] = ABS( ecgroup[i] );
mkdata( ecgroup[i] );
}
dataend();
if ( trace )
{
fputs( "\n\nEquivalence Classes:\n\n", stderr );
numrows = csize / 8;
for ( j = 0; j < numrows; ++j )
{
for ( i = j; i < csize; i = i + numrows )
{
fprintf( stderr, "%4s = %-2d",
readable_form( i ), ecgroup[i] );
putc( ' ', stderr );
}
putc( '\n', stderr );
}
}
}
/* Generate the code to find the action number. */
void gen_find_action()
{
if ( fullspd )
indent_puts( "yy_act = yy_current_state[-1].yy_nxt;" );
else if ( fulltbl )
indent_puts( "yy_act = yy_accept[yy_current_state];" );
else if ( reject )
{
indent_puts( "yy_current_state = *--yy_state_ptr;" );
indent_puts( "yy_lp = yy_accept[yy_current_state];" );
puts(
"find_rule: /* we branch to this label when backing up */" );
indent_puts(
"for ( ; ; ) /* until we find what rule we matched */" );
indent_up();
indent_puts( "{" );
indent_puts(
"if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )" );
indent_up();
indent_puts( "{" );
indent_puts( "yy_act = yy_acclist[yy_lp];" );
if ( variable_trailing_context_rules )
{
indent_puts( "if ( yy_act & YY_TRAILING_HEAD_MASK ||" );
indent_puts( " yy_looking_for_trail_begin )" );
indent_up();
indent_puts( "{" );
indent_puts(
"if ( yy_act == yy_looking_for_trail_begin )" );
in