Article View: comp.sources.mac
Article #61Flex for the Mac (part 4 of 7)
From: Earle R. Horton
Date: Fri, 01 Jul 1988 05:00
Date: Fri, 01 Jul 1988 05:00
2121 lines
48686 bytes
48686 bytes
[Flex for the Mac - part 4 of 7]
---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# flex/misc.c
# flex/nfa.c
# flex/parse.y
# flex/scan.l
# This archive created: Wed Jun 29 07:03:20 1988
# By: Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'misc.c'" '(10335 characters)'
if test -f 'misc.c'
then
echo shar: will not over-write existing file "'misc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc.c'
X/* misc - miscellaneous flex routines */
X
X/*
X * Copyright (c) 1987, the University of California
X *
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X *
X * This program may be redistributed. Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include <ctype.h>
X#include "flexdef.h"
X
Xchar *malloc(), *realloc();
X
X
X/* action_out - write the actions from the temporary file to lex.yy.c
X *
X * synopsis
X * action_out();
X *
X * Copies the action file up to %% (or end-of-file) to lex.yy.c
X */
X
Xaction_out()
X
X {
X char buf[MAXLINE];
X
X while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
X if ( buf[0] == '%' && buf[1] == '%' )
X break;
X else
X fputs( buf, stdout );
X }
X
X
X/* allocate_array - allocate memory for an integer array of the given size */
X
Xchar *allocate_array( size, element_size )
Xint size, element_size;
X
X {
X register char *mem = malloc( (unsigned) (element_size * size) );
X
X if ( mem == NULL )
X flexfatal( "memory allocation failed in allocate_array()" );
X
X return ( mem );
X }
X
X
X/* bubble - bubble sort an integer array in increasing order
X *
X * synopsis
X * int v[n], n;
X * bubble( v, n );
X *
X * description
X * sorts the first n elements of array v and replaces them in
X * increasing order.
X *
X * passed
X * v - the array to be sorted
X * n - the number of elements of 'v' to be sorted */
X
Xbubble( v, n )
Xint v[], n;
X
X {
X register int i, j, k;
X
X for ( i = n; i > 1; --i )
X for ( j = 1; j < i; ++j )
X if ( v[j] > v[j + 1] ) /* compare */
X {
X k = v[j]; /* exchange */
X v[j] = v[j + 1];
X v[j + 1] = k;
X }
X }
X
X
X/* clower - replace upper-case letter to lower-case
X *
X * synopsis:
X * char clower(), c;
X * c = clower( c );
X */
X
Xchar clower( c )
Xregister char c;
X
X {
X return ( isupper(c) ? tolower(c) : c );
X }
X
X
X/* copy_string - returns a dynamically allocated copy of a string
X *
X * synopsis
X * char *str, *copy, *copy_string();
X * copy = copy_string( str );
X */
X
Xchar *copy_string( str )
Xregister char *str;
X
X {
X register char *c;
X char *copy;
X
X /* find length */
X for ( c = str; *c; ++c )
X ;
X
X copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
X
X if ( copy == NULL )
X flexfatal( "dynamic memory failure in copy_string()" );
X
X for ( c = copy; (*c++ = *str++); )
X ;
X
X return ( copy );
X }
X
X
X/* cshell - shell sort a character array in increasing order
X *
X * synopsis
X *
X * char v[n];
X * int n;
X * cshell( v, n );
X *
X * description
X * does a shell sort of the first n elements of array v.
X *
X * passed
X * v - array to be sorted
X * n - number of elements of v to be sorted
X */
Xcshell( v, n )
Xchar v[];
Xint n;
X
X {
X int gap, i, j, jg;
X char k;
X
X for ( gap = n / 2; gap > 0; gap = gap / 2 )
X for ( i = gap; i < n; ++i )
X for ( j = i - gap; j >= 0; j = j - gap )
X {
X jg = j + gap;
X
X if ( v[j] <= v[jg] )
X break;
X
X k = v[j];
X v[j] = v[jg];
X v[jg] = k;
X }
X }
X
X
X/* dataend - finish up a block of data declarations
X *
X * synopsis
X * dataend();
X */
Xdataend()
X
X {
X if ( datapos > 0 )
X dataflush();
X
X /* add terminator for initialization */
X puts( " } ;\n" );
X
X dataline = 0;
X }
X
X
X
X/* dataflush - flush generated data statements
X *
X * synopsis
X * dataflush();
X */
Xdataflush()
X
X {
X putchar( '\n' );
X
X if ( ++dataline >= NUMDATALINES )
X {
X /* put out a blank line so that the table is grouped into
X * large blocks that enable the user to find elements easily
X */
X putchar( '\n' );
X dataline = 0;
X }
X
X /* reset the number of characters written on the current line */
X datapos = 0;
X }
X
X/* gettime - return current time
X *
X * synopsis
X * char *gettime(), *time_str;
X * time_str = gettime();
X */
X#ifdef MPW
Xpascal void IUTIMESTRING(dateTime, wantSeconds, result)
X long dateTime;
X short wantSeconds;
X char *result;
X extern;
Xchar *p2cstr();
Xchar *gettime()
X
X {
X char *copy_string();
X long curtime;
X char strbuf[256];
X GetDateTime(&curtime);
X IUTIMESTRING(curtime,true,strbuf);
X p2cstr(strbuf);
X return (copy_string(strbuf));
X}
X
X#else
X/* include sys/types.h to use time_t and make lint happy */
X
X#include <sys/types.h>
X
Xchar *gettime()
X
X {
X time_t t, time();
X char *result, *ctime(), *copy_string();
X
X t = time( (long *) 0 );
X
X result = copy_string( ctime( &t ) );
X
X /* get rid of trailing newline */
X result[24] = '\0';
X
X return ( result );
X }
X#endif
X
X/* lerrif - report an error message formatted with one integer argument
X *
X * synopsis
X * char msg[];
X * int arg;
X * lerrif( msg, arg );
X */
X
Xlerrif( msg, arg )
Xchar msg[];
Xint arg;
X
X {
X char errmsg[MAXLINE];
X (void) sprintf( errmsg, msg, arg );
X flexerror( errmsg );
X }
X
X
X/* lerrsf - report an error message formatted with one string argument
X *
X * synopsis
X * char msg[], arg[];
X * lerrsf( msg, arg );
X */
X
Xlerrsf( msg, arg )
Xchar msg[], arg[];
X
X {
X char errmsg[MAXLINE];
X
X (void) sprintf( errmsg, msg, arg );
X flexerror( errmsg );
X }
X
X
X/* flexerror - report an error message and terminate
X *
X * synopsis
X * char msg[];
X * flexerror( msg );
X */
X
Xflexerror( msg )
Xchar msg[];
X
X {
X fprintf( stderr, "flex: %s\n", msg );
X flexend( 1 );
X }
X
X
X/* flexfatal - report a fatal error message and terminate
X *
X * synopsis
X * char msg[];
X * flexfatal( msg );
X */
X
Xflexfatal( msg )
Xchar msg[];
X
X {
X fprintf( stderr, "flex: fatal internal error %s\n", msg );
X flexend( 1 );
X }
X
X
X/* line_directive_out - spit out a "# line" statement */
X
Xline_directive_out( output_file_name )
XFILE *output_file_name;
X
X {
X if ( infilename && gen_line_dirs )
X fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
X }
X
X
X/* mk2data - generate a data statement for a two-dimensional array
X *
X * synopsis
X * int value;
X * mk2data( value );
X *
X * generates a data statement initializing the current 2-D array to "value"
X */
Xmk2data( value )
Xint value;
X
X {
X if ( datapos >= NUMDATAITEMS )
X {
X putchar( ',' );
X dataflush();
X }
X
X if ( datapos == 0 )
X /* indent */
X fputs( " ", stdout );
X
X else
X putchar( ',' );
X
X ++datapos;
X
X printf( "%5d", value );
X }
X
X
X/* mkdata - generate a data statement
X *
X * synopsis
X * int value;
X * mkdata( value );
X *
X * generates a data statement initializing the current array element to
X * "value"
X */
Xmkdata( value )
Xint value;
X
X {
X if ( datapos >= NUMDATAITEMS )
X {
X putchar( ',' );
X dataflush();
X }
X
X if ( datapos == 0 )
X /* indent */
X fputs( " ", stdout );
X
X else
X putchar( ',' );
X
X ++datapos;
X
X printf( "%5d", value );
X }
X
X
X/* myctoi - return the integer represented by a string of digits
X *
X * synopsis
X * char array[];
X * int val, myctoi();
X * val = myctoi( array );
X *
X */
X
Xint myctoi( array )
Xchar array[];
X
X {
X int val = 0;
X
X (void) sscanf( array, "%d", &val );
X
X return ( val );
X }
X
X
X/* myesc - return character corresponding to escape sequence
X *
X * synopsis
X * char array[], c, myesc();
X * c = myesc( array );
X *
X */
X
Xchar myesc( array )
Xchar array[];
X
X {
X switch ( array[1] )
X {
X case 'n': return ( '\n' );
X case 't': return ( '\t' );
X case 'f': return ( '\f' );
X case 'r': return ( '\r' );
X case 'b': return ( '\b' );
X
X case '0':
X if ( isdigit(array[2]) )
X { /* \0<octal> */
X char c, esc_char;
X register int sptr = 2;
X
X while ( isdigit(array[sptr]) )
X /* don't increment inside loop control because the
X * macro will expand it to two increments! (Not a
X * problem with the C version of the macro)
X */
X ++sptr;
X
X c = array[sptr];
X array[sptr] = '\0';
X
X esc_char = otoi( array + 2 );
X array[sptr] = c;
X
X if ( esc_char == '\0' )
X {
X synerr( "escape sequence for null not allowed" );
X return ( 1 );
X }
X
X return ( esc_char );
X }
X
X else
X {
X synerr( "escape sequence for null not allowed" );
X return ( 1 );
X }
X
X#ifdef NOTDEF
X case '^':
X {
X register char next_char = array[2];
X
X if ( next_char == '?' )
X return ( 0x7f );
X
X else if ( next_char >= 'A' && next_char <= 'Z' )
X return ( next_char - 'A' + 1 );
X
X else if ( next_char >= 'a' && next_char <= 'z' )
X return ( next_char - 'z' + 1 );
X
X synerr( "illegal \\^ escape sequence" );
X
X return ( 1 );
X }
X#endif
X }
X
X return ( array[1] );
X }
X
X
X/* otoi - convert an octal digit string to an integer value
X *
X * synopsis:
X * int val, otoi();
X * char str[];
X * val = otoi( str );
X */
X
Xint otoi( str )
Xchar str[];
X
X {
X#ifdef FTLSOURCE
X fortran int gctoi()
X int dummy = 1;
X
X return ( gctoi( str, dummy, 8 ) );
X#else
X int result;
X
X (void) sscanf( str, "%o", &result );
X
X return ( result );
X#endif
X }
X
X
X
X
X/* reallocate_array - increase the size of a dynamic array */
X
Xchar *reallocate_array( array, size, element_size )
Xchar *array;
Xint size, element_size;
X
X {
X register char *new_array = realloc( array,
X (unsigned) (size * element_size ));
X
X if ( new_array == NULL )
X flexfatal( "attempt to increase array size failed" );
X
X return ( new_array );
X }
X
X
X/* skelout - write out one section of the skeleton file
X *
X * synopsis
X * skelout();
X *
X * DESCRIPTION
X * Copies from skelfile to stdout until a line beginning with "%%" or
X * EOF is found.
X */
Xskelout()
X
X {
X char buf[MAXLINE];
X
X while ( fgets( buf, MAXLINE, skelfile ) != NULL )
X if ( buf[0] == '%' && buf[1] == '%' )
X break;
X else
X fputs( buf, stdout );
X }
X
X
X/* transition_struct_out - output a yy_trans_info structure
X *
X * synopsis
X * int element_v, element_n;
X * transition_struct_out( element_v, element_n );
X *
X * outputs the yy_trans_info structure with the two elements, element_v and
X * element_n. Formats the output with spaces and carriage returns.
X */
X
Xtransition_struct_out( element_v, element_n )
Xint element_v, element_n;
X
X {
X printf( "%7d, %5d,", element_v, element_n );
X
X datapos += TRANS_STRUCT_PRINT_LENGTH;
X
X if ( datapos >= 75 )
X {
X printf( "\n" );
X
X if ( ++dataline % 10 == 0 )
X printf( "\n" );
X
X datapos = 0;
X }
X }
SHAR_EOF
if test 10335 -ne "`wc -c < 'misc.c'`"
then
echo shar: error transmitting "'misc.c'" '(should have been 10335 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nfa.c'" '(13633 characters)'
if test -f 'nfa.c'
then
echo shar: will not over-write existing file "'nfa.c'"
else
sed 's/^X//' << \SHAR_EOF > 'nfa.c'
X/* nfa - NFA construction routines */
X
X/*
X * Copyright (c) 1987, the University of California
X *
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X *
X * This program may be redistributed. Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* add_accept - add an accepting state to a machine
X *
X * synopsis
X *
X * add_accept( mach, headcnt, trailcnt );
X *
X * the global ACCNUM is incremented and the new value becomes mach's
X * accepting number. if headcnt or trailcnt is non-zero then the machine
X * recognizes a pattern with trailing context. headcnt is the number of
X * characters in the matched part of the pattern, or zero if the matched
X * part has variable length. trailcnt is the number of trailing context
X * characters in the pattern, or zero if the trailing context has variable
X * length.
X */
X
Xadd_accept( mach, headcnt, trailcnt )
Xint mach, headcnt, trailcnt;
X
X {
X int astate;
X
X fprintf( temp_action_file, "case %d:\n", ++accnum );
X
X if ( headcnt > 0 || trailcnt > 0 )
X { /* do trailing context magic to not match the trailing characters */
X fprintf( temp_action_file,
X "YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */\n" );
X
X if ( headcnt > 0 )
X {
X int head_offset = headcnt - 1;
X
X if ( fullspd || fulltbl )
X /* with the fast skeleton, yy_c_buf_p points to the *next*
X * character to scan, rather than the one that was last
X * scanned
X */
X ++head_offset;
X
X if ( head_offset > 0 )
X fprintf( temp_action_file, "yy_c_buf_p = yy_b_buf_p + %d;\n",
X head_offset );
X
X else
X fprintf( temp_action_file, "yy_c_buf_p = yy_b_buf_p;\n" );
X }
X
X else
X fprintf( temp_action_file, "yy_c_buf_p -= %d;\n", trailcnt );
X
X fprintf( temp_action_file, "YY_DO_BEFORE_ACTION; /* set up yytext again */\n" );
X }
X
X line_directive_out( temp_action_file );
X
X /* hang the accepting number off an epsilon state. if it is associated
X * with a state that has a non-epsilon out-transition, then the state
X * will accept BEFORE it makes that transition, i.e., one character
X * too soon
X */
X
X if ( transchar[finalst[mach]] == SYM_EPSILON )
X accptnum[finalst[mach]] = accnum;
X
X else
X {
X astate = mkstate( SYM_EPSILON );
X accptnum[astate] = accnum;
X mach = link_machines( mach, astate );
X }
X }
X
X
X/* copysingl - make a given number of copies of a singleton machine
X *
X * synopsis
X *
X * newsng = copysingl( singl, num );
X *
X * newsng - a new singleton composed of num copies of singl
X * singl - a singleton machine
X * num - the number of copies of singl to be present in newsng
X */
X
Xint copysingl( singl, num )
Xint singl, num;
X
X {
X int copy, i;
X
X copy = mkstate( SYM_EPSILON );
X
X for ( i = 1; i <= num; ++i )
X copy = link_machines( copy, dupmachine( singl ) );
X
X return ( copy );
X }
X
X
X/* dumpnfa - debugging routine to write out an nfa
X *
X * synopsis
X * int state1;
X * dumpnfa( state1 );
X */
X
Xdumpnfa( state1 )
Xint state1;
X
X {
X int sym, tsp1, tsp2, anum, ns;
X
X fprintf( stderr, "\n\n********** beginning dump of nfa with start state %d\n",
X state1 );
X
X /* we probably should loop starting at firstst[state1] and going to
X * lastst[state1], but they're not maintained properly when we "or"
X * all of the rules together. So we use our knowledge that the machine
X * starts at state 1 and ends at lastnfa.
X */
X
X /* for ( ns = firstst[state1]; ns <= lastst[state1]; ++ns ) */
X for ( ns = 1; ns <= lastnfa; ++ns )
X {
X fprintf( stderr, "state # %4d\t", ns );
X
X sym = transchar[ns];
X tsp1 = trans1[ns];
X tsp2 = trans2[ns];
X anum = accptnum[ns];
X
X fprintf( stderr, "%3d: %4d, %4d", sym, tsp1, tsp2 );
X
X if ( anum != NIL )
X fprintf( stderr, " [%d]", anum );
X
X fprintf( stderr, "\n" );
X }
X
X fprintf( stderr, "********** end of dump\n" );
X }
X
X
X/* dupmachine - make a duplicate of a given machine
X *
X * synopsis
X *
X * copy = dupmachine( mach );
X *
X * copy - holds duplicate of mach
X * mach - machine to be duplicated
X *
X * note that the copy of mach is NOT an exact duplicate; rather, all the
X * transition states values are adjusted so that the copy is self-contained,
X * as the original should have been.
X *
X * also note that the original MUST be contiguous, with its low and high
X * states accessible by the arrays firstst and lastst
X */
X
Xint dupmachine( mach )
Xint mach;
X
X {
X int i, state, init, last = lastst[mach], state_offset;
X
X for ( i = firstst[mach]; i <= last; ++i )
X {
X state = mkstate( transchar[i] );
X
X if ( trans1[i] != NO_TRANSITION )
X {
X mkxtion( finalst[state], trans1[i] + state - i );
X
X if ( transchar[i] == SYM_EPSILON && trans2[i] != NO_TRANSITION )
X mkxtion( finalst[state], trans2[i] + state - i );
X }
X
X accptnum[state] = accptnum[i];
X }
X
X state_offset = state - i + 1;
X
X init = mach + state_offset;
X firstst[init] = firstst[mach] + state_offset;
X finalst[init] = finalst[mach] + state_offset;
X lastst[init] = lastst[mach] + state_offset;
X
X return ( init );
X }
X
X
X/* link_machines - connect two machines together
X *
X * synopsis
X *
X * new = link_machines( first, last );
X *
X * new - a machine constructed by connecting first to last
X * first - the machine whose successor is to be last
X * last - the machine whose predecessor is to be first
X *
X * note: this routine concatenates the machine first with the machine
X * last to produce a machine new which will pattern-match first first
X * and then last, and will fail if either of the sub-patterns fails.
X * FIRST is set to new by the operation. last is unmolested.
X */
X
Xint link_machines( first, last )
Xint first, last;
X
X {
X if ( first == NIL )
X return ( last );
X
X else if ( last == NIL )
X return ( first );
X
X else
X {
X mkxtion( finalst[first], last );
X finalst[first] = finalst[last];
X lastst[first] = max( lastst[first], lastst[last] );
X firstst[first] = min( firstst[first], firstst[last] );
X
X return ( first );
X }
X }
X
X
X/* mkbranch - make a machine that branches to two machines
X *
X * synopsis
X *
X * branch = mkbranch( first, second );
X *
X * branch - a machine which matches either first's pattern or second's
X * first, second - machines whose patterns are to be or'ed (the | operator)
X *
X * note that first and second are NEITHER destroyed by the operation. Also,
X * the resulting machine CANNOT be used with any other "mk" operation except
X * more mkbranch's. Compare with mkor()
X */
X
Xint mkbranch( first, second )
Xint first, second;
X
X {
X int eps;
X
X if ( first == NO_TRANSITION )
X return ( second );
X
X else if ( second == NO_TRANSITION )
X return ( first );
X
X eps = mkstate( SYM_EPSILON );
X
X mkxtion( eps, first );
X mkxtion( eps, second );
X
X return ( eps );
X }
X
X
X/* mkclos - convert a machine into a closure
X *
X * synopsis
X * new = mkclos( state );
X *
X * new - a new state which matches the closure of "state"
X */
X
Xint mkclos( state )
Xint state;
X
X {
X return ( mkopt( mkposcl( state ) ) );
X }
X
X
X/* mkopt - make a machine optional
X *
X * synopsis
X *
X * new = mkopt( mach );
X *
X * new - a machine which optionally matches whatever mach matched
X * mach - the machine to make optional
X *
X * notes:
X * 1. mach must be the last machine created
X * 2. mach is destroyed by the call
X */
X
Xint mkopt( mach )
Xint mach;
X
X {
X int eps;
X
X if ( ! SUPER_FREE_EPSILON(finalst[mach]) )
X {
X eps = mkstate( SYM_EPSILON );
X mach = link_machines( mach, eps );
X }
X
X /* can't skimp on the following if FREE_EPSILON(mach) is true because
X * some state interior to "mach" might point back to the beginning
X * for a closure
X */
X eps = mkstate( SYM_EPSILON );
X mach = link_machines( eps, mach );
X
X mkxtion( mach, finalst[mach] );
X
X return ( mach );
X }
X
X
X/* mkor - make a machine that matches either one of two machines
X *
X * synopsis
X *
X * new = mkor( first, second );
X *
X * new - a machine which matches either first's pattern or second's
X * first, second - machines whose patterns are to be or'ed (the | operator)
X *
X * note that first and second are both destroyed by the operation
X * the code is rather convoluted because an attempt is made to minimize
X * the number of epsilon states needed
X */
X
Xint mkor( first, second )
Xint first, second;
X
X {
X int eps, orend;
X
X if ( first == NIL )
X return ( second );
X
X else if ( second == NIL )
X return ( first );
X
X else
X {
X /* see comment in mkopt() about why we can't use the first state
X * of "first" or "second" if they satisfy "FREE_EPSILON"
X */
X eps = mkstate( SYM_EPSILON );
X
X first = link_machines( eps, first );
X
X mkxtion( first, second );
X
X if ( SUPER_FREE_EPSILON(finalst[first]) &&
X accptnum[finalst[first]] == NIL )
X {
X orend = finalst[first];
X mkxtion( finalst[second], orend );
X }
X
X else if ( SUPER_FREE_EPSILON(finalst[second]) &&
X accptnum[finalst[second]] == NIL )
X {
X orend = finalst[second];
X mkxtion( finalst[first], orend );
X }
X
X else
X {
X eps = mkstate( SYM_EPSILON );
X
X first = link_machines( first, eps );
X orend = finalst[first];
X
X mkxtion( finalst[second], orend );
X }
X }
X
X finalst[first] = orend;
X return ( first );
X }
X
X
X/* mkposcl - convert a machine into a positive closure
X *
X * synopsis
X * new = mkposcl( state );
X *
X * new - a machine matching the positive closure of "state"
X */
X
Xint mkposcl( state )
Xint state;
X
X {
X int eps;
X
X if ( SUPER_FREE_EPSILON(finalst[state]) )
X {
X mkxtion( finalst[state], state );
X return ( state );
X }
X
X else
X {
X eps = mkstate( SYM_EPSILON );
X mkxtion( eps, state );
X return ( link_machines( state, eps ) );
X }
X }
X
X
X/* mkrep - make a replicated machine
X *
X * synopsis
X * new = mkrep( mach, lb, ub );
X *
X * new - a machine that matches whatever "mach" matched from "lb"
X * number of times to "ub" number of times
X *
X * note
X * if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach"
X */
X
Xint mkrep( mach, lb, ub )
Xint mach, lb, ub;
X
X {
X int base, tail, copy, i;
X
X base = copysingl( mach, lb - 1 );
X
X if ( ub == INFINITY )
X {
X copy = dupmachine( mach );
X mach = link_machines( mach, link_machines( base, mkclos( copy ) ) );
X }
X
X else
X {
X tail = mkstate( SYM_EPSILON );
X
X for ( i = lb; i < ub; ++i )
X {
X copy = dupmachine( mach );
X tail = mkopt( link_machines( copy, tail ) );
X }
X
X mach = link_machines( mach, link_machines( base, tail ) );
X }
X
X return ( mach );
X }
X
X
X/* mkstate - create a state with a transition on a given symbol
X *
X * synopsis
X *
X * state = mkstate( sym );
X *
X * state - a new state matching sym
X * sym - the symbol the new state is to have an out-transition on
X *
X * note that this routine makes new states in ascending order through the
X * state array (and increments LASTNFA accordingly). The routine DUPMACHINE
X * relies on machines being made in ascending order and that they are
X * CONTIGUOUS. Change it and you will have to rewrite DUPMACHINE (kludge
X * that it admittedly is)
X */
X
Xint mkstate( sym )
Xint sym;
X
X {
X if ( ++lastnfa >= current_mns )
X {
X if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS )
X lerrif( "input rules are too complicated (>= %d NFA states)",
X current_mns );
X
X ++num_reallocs;
X
X transchar = reallocate_integer_array( transchar, current_mns );
X trans1 = reallocate_integer_array( trans1, current_mns );
X trans2 = reallocate_integer_array( trans2, current_mns );
X accptnum = reallocate_integer_array( accptnum, current_mns );
X firstst = reallocate_integer_array( firstst, current_mns );
X finalst = reallocate_integer_array( finalst, current_mns );
X lastst = reallocate_integer_array( lastst, current_mns );
X }
X
X transchar[lastnfa] = sym;
X trans1[lastnfa] = NO_TRANSITION;
X trans2[lastnfa] = NO_TRANSITION;
X accptnum[lastnfa] = NIL;
X firstst[lastnfa] = lastnfa;
X finalst[lastnfa] = lastnfa;
X lastst[lastnfa] = lastnfa;
X
X /* fix up equivalence classes base on this transition. Note that any
X * character which has its own transition gets its own equivalence class.
X * Thus only characters which are only in character classes have a chance
X * at being in the same equivalence class. E.g. "a|b" puts 'a' and 'b'
X * into two different equivalence classes. "[ab]" puts them in the same
X * equivalence class (barring other differences elsewhere in the input).
X */
X
X if ( sym < 0 )
X {
X /* we don't have to update the equivalence classes since that was
X * already done when the ccl was created for the first time
X */
X }
X
X else if ( sym == SYM_EPSILON )
X ++numeps;
X
X else
X {
X if ( useecs )
X mkechar( sym, nextecm, ecgroup );
X }
X
X return ( lastnfa );
X }
X
X
X/* mkxtion - make a transition from one state to another
X *
X * synopsis
X *
X * mkxtion( statefrom, stateto );
X *
X * statefrom - the state from which the transition is to be made
X * stateto - the state to which the transition is to be made
X */
X
Xmkxtion( statefrom, stateto )
Xint statefrom, stateto;
X
X {
X if ( trans1[statefrom] == NO_TRANSITION )
X trans1[statefrom] = stateto;
X
X else if ( (transchar[statefrom] != SYM_EPSILON) ||
X (trans2[statefrom] != NO_TRANSITION) )
X flexfatal( "found too many transitions in mkxtion()" );
X
X else
X { /* second out-transition for an epsilon state */
X ++eps2;
X trans2[statefrom] = stateto;
X }
X }
SHAR_EOF
if test 13633 -ne "`wc -c < 'nfa.c'`"
then
echo shar: error transmitting "'nfa.c'" '(should have been 13633 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'parse.y'" '(8970 characters)'
if test -f 'parse.y'
then
echo shar: will not over-write existing file "'parse.y'"
else
sed 's/^X//' << \SHAR_EOF > 'parse.y'
X/* parse.y - parser for flex input */
X
X/*
X * Copyright (c) 1987, the University of California
X *
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X *
X * This program may be redistributed. Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL
X
X%{
X#include "flexdef.h"
X
Xint pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen;
Xint trlcontxt, xcluflg, cclsorted, varlength;
Xchar clower();
X
Xstatic int madeany = false; /* whether we've made the '.' character class */
X
X%}
X
X%%
Xgoal : initlex sect1 sect1end sect2
X ;
X
Xinitlex :
X {
X /* initialize for processing rules */
X
X /* create default DFA start condition */
X scinstal( "INITIAL", false );
X }
X ;
X
Xsect1 : sect1 startconddecl WHITESPACE namelist1 '\n'
X |
X | error '\n'
X { synerr( "unknown error processing section 1" ); }
X ;
X
Xsect1end : SECTEND
X ;
X
Xstartconddecl : SCDECL
X {
X /* these productions are separate from the s1object
X * rule because the semantics must be done before
X * we parse the remainder of an s1object
X */
X
X xcluflg = false;
X }
X
X | XSCDECL
X { xcluflg = true; }
X ;
X
Xnamelist1 : namelist1 WHITESPACE NAME
X { scinstal( nmstr, xcluflg ); }
X
X | NAME
X { scinstal( nmstr, xcluflg ); }
X
X | error
X { synerr( "bad start condition list" ); }
X ;
X
Xsect2 : sect2 initforrule flexrule '\n'
X |
X ;
X
Xinitforrule :
X {
X /* initialize for a parse of one rule */
X trlcontxt = varlength = false;
X trailcnt = headcnt = rulelen = 0;
X }
X ;
X
Xflexrule : scon '^' re eol
X {
X pat = link_machines( $3, $4 );
X add_accept( pat, headcnt, trailcnt );
X
X for ( i = 1; i <= actvp; ++i )
X scbol[actvsc[i]] = mkbranch( scbol[actvsc[i]], pat );
X }
X
X | scon re eol
X {
X pat = link_machines( $2, $3 );
X add_accept( pat, headcnt, trailcnt );
X
X for ( i = 1; i <= actvp; ++i )
X scset[actvsc[i]] = mkbranch( scset[actvsc[i]], pat );
X }
X
X | '^' re eol
X {
X pat = link_machines( $2, $3 );
X add_accept( pat, headcnt, trailcnt );
X
X /* add to all non-exclusive start conditions,
X * including the default (0) start condition
X */
X
X for ( i = 1; i <= lastsc; ++i )
X if ( ! scxclu[i] )
X scbol[i] = mkbranch( scbol[i], pat );
X }
X
X | re eol
X {
X pat = link_machines( $1, $2 );
X add_accept( pat, headcnt, trailcnt );
X
X for ( i = 1; i <= lastsc; ++i )
X if ( ! scxclu[i] )
X scset[i] = mkbranch( scset[i], pat );
X }
X
X | error
X { synerr( "unrecognized rule" ); }
X ;
X
Xscon : '<' namelist2 '>'
X ;
X
Xnamelist2 : namelist2 ',' NAME
X {
X if ( (scnum = sclookup( nmstr )) == 0 )
X synerr( "undeclared start condition" );
X
X else
X actvsc[++actvp] = scnum;
X }
X
X | NAME
X {
X if ( (scnum = sclookup( nmstr )) == 0 )
X synerr( "undeclared start condition" );
X else
X actvsc[actvp = 1] = scnum;
X }
X
X | error
X { synerr( "bad start condition list" ); }
X ;
X
Xeol : '$'
X {
X if ( trlcontxt )
X {
X synerr( "trailing context used twice" );
X $$ = mkstate( SYM_EPSILON );
X }
X else
X {
X trlcontxt = true;
X
X if ( ! varlength )
X headcnt = rulelen;
X
X ++rulelen;
X trailcnt = 1;
X
X eps = mkstate( SYM_EPSILON );
X $$ = link_machines( eps, mkstate( '\n' ) );
X }
X }
X
X |
X {
X $$ = mkstate( SYM_EPSILON );
X
X if ( trlcontxt )
X {
X if ( varlength && headcnt == 0 )
X /* both head and trail are variable-length */
X synerr( "illegal trailing context" );
X
X else
X trailcnt = rulelen;
X }
X }
X ;
X
Xre : re '|' series
X {
X varlength = true;
X
X $$ = mkor( $1, $3 );
X }
X
X | re2 series
X { $$ = link_machines( $1, $2 ); }
X
X | series
X { $$ = $1; }
X ;
X
X
Xre2 : re '/'
X {
X /* this rule is separate from the others for "re" so
X * that the reduction will occur before the trailing
X * series is parsed
X */
X
X if ( trlcontxt )
X synerr( "trailing context used twice" );
X else
X trlcontxt = true;
X
X if ( varlength )
X /* the trailing context had better be fixed-length */
X varlength = false;
X else
X headcnt = rulelen;
X
X rulelen = 0;
X $$ = $1;
X }
X ;
X
Xseries : series singleton
X {
X /* this is where concatenation of adjacent patterns
X * gets done
X */
X $$ = link_machines( $1, $2 );
X }
X
X | singleton
X { $$ = $1; }
X ;
X
Xsingleton : singleton '*'
X {
X varlength = true;
X
X $$ = mkclos( $1 );
X }
X
X | singleton '+'
X {
X varlength = true;
X
X $$ = mkposcl( $1 );
X }
X
X | singleton '?'
X {
X varlength = true;
X
X $$ = mkopt( $1 );
X }
X
X | singleton '{' NUMBER ',' NUMBER '}'
X {
X varlength = true;
X
X if ( $3 > $5 || $3 <= 0 )
X {
X synerr( "bad iteration values" );
X $$ = $1;
X }
X else
X $$ = mkrep( $1, $3, $5 );
X }
X
X | singleton '{' NUMBER ',' '}'
X {
X varlength = true;
X
X if ( $3 <= 0 )
X {
X synerr( "iteration value must be positive" );
X $$ = $1;
X }
X
X else
X $$ = mkrep( $1, $3, INFINITY );
X }
X
X | singleton '{' NUMBER '}'
X {
X /* the singleton could be something like "(foo)",
X * in which case we have no idea what its length
X * is, so we punt here.
X */
X varlength = true;
X
X if ( $3 <= 0 )
X {
X synerr( "iteration value must be positive" );
X $$ = $1;
X }
X
X else
X $$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
X }
X
X | '.'
X {
X if ( ! madeany )
X {
X /* create the '.' character class */
X anyccl = cclinit();
X ccladd( anyccl, '\n' );
X cclnegate( anyccl );
X
X if ( useecs )
X mkeccl( ccltbl + cclmap[anyccl],
X ccllen[anyccl], nextecm,
X ecgroup, CSIZE );
X
X madeany = true;
X }
X
X ++rulelen;
X
X $$ = mkstate( -anyccl );
X }
X
X | fullccl
X {
X if ( ! cclsorted )
X /* sort characters for fast searching. We use a
X * shell sort since this list could be large.
X */
X cshell( ccltbl + cclmap[$1], ccllen[$1] );
X
X if ( useecs )
X mkeccl( ccltbl + cclmap[$1], ccllen[$1],
X nextecm, ecgroup, CSIZE );
X
X ++rulelen;
X
X $$ = mkstate( -$1 );
X }
X
X | PREVCCL
X {
X ++rulelen;
X
X $$ = mkstate( -$1 );
X }
X
X | '"' string '"'
X { $$ = $2; }
X
X | '(' re ')'
X { $$ = $2; }
X
X | CHAR
X {
X ++rulelen;
X
X if ( $1 == '\0' )
X synerr( "null in rule" );
X
X if ( caseins && $1 >= 'A' && $1 <= 'Z' )
X $1 = clower( $1 );
X
X $$ = mkstate( $1 );
X }
X ;
X
Xfullccl : '[' ccl ']'
X { $$ = $2; }
X
X | '[' '^' ccl ']'
X {
X /* *Sigh* - to be compatible Unix lex, negated ccls
X * match newlines
X */
X#ifdef NOTDEF
X ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
X cclsorted = false; /* because we added the newline */
X#endif
X cclnegate( $3 );
X $$ = $3;
X }
X ;
X
Xccl : ccl CHAR '-' CHAR
X {
X if ( $2 > $4 )
X synerr( "negative range in character class" );
X
X else
X {
X if ( caseins )
X {
X if ( $2 >= 'A' && $2 <= 'Z' )
X $2 = clower( $2 );
X if ( $4 >= 'A' && $4 <= 'Z' )
X $4 = clower( $4 );
X }
X
X for ( i = $2; i <= $4; ++i )
X ccladd( $1, i );
X
X /* keep track if this ccl is staying in alphabetical
X * order
X */
X cclsorted = cclsorted && ($2 > lastchar);
X lastchar = $4;
X }
X
X $$ = $1;
X }
X
X | ccl CHAR
X {
X if ( caseins )
X if ( $2 >= 'A' && $2 <= 'Z' )
X $2 = clower( $2 );
X
X ccladd( $1, $2 );
X cclsorted = cclsorted && ($2 > lastchar);
X lastchar = $2;
X $$ = $1;
X }
X
X |
X {
X cclsorted = true;
X lastchar = 0;
X $$ = cclinit();
X }
X ;
X
Xstring : string CHAR
X {
X if ( caseins )
X if ( $2 >= 'A' && $2 <= 'Z' )
X $2 = clower( $2 );
X
X ++rulelen;
X
X $$ = link_machines( $1, mkstate( $2 ) );
X }
X
X |
X { $$ = mkstate( SYM_EPSILON ); }
X ;
X
X%%
X
X/* synerr - report a syntax error
X *
X * synopsis
X * char str[];
X * synerr( str );
X */
X
Xsynerr( str )
Xchar str[];
X
X {
X syntaxerror = true;
X#ifdef MPW
X fprintf( stderr, "File %s ;Line %d # Syntax error: %s\n",infilename,linenum, str );
X#else
X fprintf( stderr, "Syntax error at line %d: %s\n", linenum, str );
X#endif
X }
X
X
X/* yyerror - eat up an error message from the parser
X *
X * synopsis
X * char msg[];
X * yyerror( msg );
X */
X
Xyyerror( msg )
Xchar msg[];
X
X {
X }
SHAR_EOF
if test 8970 -ne "`wc -c < 'parse.y'`"
then
echo shar: error transmitting "'parse.y'" '(should have been 8970 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'scan.l'" '(9222 characters)'
if test -f 'scan.l'
then
echo shar: will not over-write existing file "'scan.l'"
else
sed 's/^X//' << \SHAR_EOF > 'scan.l'
X/* scan.l - scanner for flex input */
X
X/*
X * Copyright (c) 1987, the University of California
X *
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X *
X * This program may be redistributed. Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X%{
X#include "flexdef.h"
X#include "parse.h"
X
X#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
X#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
X
X#undef YY_DECL
X#define YY_DECL \
X int flexscan()
X
X#define RETURNCHAR \
X yylval = yytext[0] & BYTEMASK; \
X return ( CHAR );
X
X#define RETURNNAME \
X (void) strcpy( nmstr, yytext ); \
X return ( NAME );
X
X#define PUT_BACK_STRING(str, start) \
X for ( i = strlen( str ) - 1; i >= start; --i ) \
X unput(str[i])
X%}
X
X%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
X%x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
X%x ACTION_STRING PERCENT_BRACE_ACTION
X
XWS [ \t]+
X
XOPTWS [ \t]*
X
XNAME [a-z_][a-z_0-9]*
X
XSCNAME {NAME}
X
XESCSEQ \\([^^\n]|"^".|0[0-9]{1,3})
X
X%%
X static int bracelevel, didadef;
X int i, cclval;
X char nmdef[MAXLINE], myesc();
X
X^{WS}.*\n ++linenum; ECHO; /* indented code */
X^#.*\n ++linenum; ECHO; /* treat as a comment */
X^"/*" ECHO; BEGIN(C_COMMENT);
X^"%s"(tart)? return ( SCDECL );
X^"%x" return ( XSCDECL );
X^"%{".*\n ++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
X{WS} return ( WHITESPACE );
X
X^"%%".* {
X sectnum = 2;
X line_directive_out( stdout );
X BEGIN(SECT2PROLOG);
X return ( SECTEND );
X }
X
X^"%"[^sx{%].*\n {
X fprintf( stderr,
X "old-style lex command at line %d ignored:\n\t%s",
X linenum, yytext );
X ++linenum;
X }
X
X^{NAME} {
X (void) strcpy( nmstr, yytext );
X didadef = false;
X BEGIN(PICKUPDEF);
X }
X
X{SCNAME} RETURNNAME;
X^{OPTWS}\n ++linenum; /* allows blank lines in section 1 */
X\n ++linenum; return ( '\n' );
X. synerr( "illegal character" ); BEGIN(RECOVER);
X
X
X<C_COMMENT>"*/" ECHO; BEGIN(0);
X<C_COMMENT>"*/".*\n ++linenum; ECHO; BEGIN(0);
X<C_COMMENT>[^*\n]+ ECHO;
X<C_COMMENT>"*" ECHO;
X<C_COMMENT>\n ++linenum; ECHO;
X
X<CODEBLOCK>^"%}".*\n ++linenum; BEGIN(0);
X<CODEBLOCK>.*\n ++linenum; ECHO;
X
X<PICKUPDEF>{WS} /* separates name and definition */
X
X<PICKUPDEF>[^ \t\n].* {
X (void) strcpy( nmdef, yytext );
X
X for ( i = strlen( nmdef ) - 1;
X i >= 0 &&
X nmdef[i] == ' ' || nmdef[i] == '\t';
X --i )
X ;
X
X nmdef[i + 1] = '\0';
X
X ndinstal( nmstr, nmdef );
X didadef = true;
X }
X
X<PICKUPDEF>\n {
X if ( ! didadef )
X synerr( "incomplete name definition" );
X BEGIN(0);
X ++linenum;
X }
X
X<RECOVER>.*\n ++linenum; BEGIN(0); RETURNNAME;
X
X
X<SECT2PROLOG>.*\n/[^ \t\n] {
X ++linenum;
X ACTION_ECHO;
X MARK_END_OF_PROLOG;
X BEGIN(SECT2);
X }
X
X<SECT2PROLOG>.*\n ++linenum; ACTION_ECHO;
X
X<SECT2>^{OPTWS}\n ++linenum; /* allow blank lines in section 2 */
X
X /* this horrible mess of a rule matches indented lines which
X * do not contain "/*". We need to make the distinction because
X * otherwise this rule will be taken instead of the rule which
X * matches the beginning of comments like this one
X */
X<SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n {
X synerr( "indented code found outside of action" );
X ++linenum;
X }
X
X<SECT2>"<" BEGIN(SC); return ( '<' );
X<SECT2>^"^" return ( '^' );
X<SECT2>\" BEGIN(QUOTE); return ( '"' );
X<SECT2>"{"/[0-9] BEGIN(NUM); return ( '{' );
X<SECT2>"{"[^0-9\n][^}\n]* BEGIN(BRACEERROR);
X<SECT2>"$"/[ \t\n] return ( '$' );
X
X<SECT2>{WS}"%{" {
X bracelevel = 1;
X BEGIN(PERCENT_BRACE_ACTION);
X return ( '\n' );
X }
X<SECT2>{WS}"|".*\n ++linenum; return ( '\n' );
X
X<SECT2>^{OPTWS}"/*" ACTION_ECHO; BEGIN(C_COMMENT_2);
X
X<SECT2>{WS} { /* needs to be separate from following rule due to
X * bug with trailing context
X */
X bracelevel = 0;
X BEGIN(ACTION);
X return ( '\n' );
X }
X
X<SECT2>{OPTWS}/\n {
X bracelevel = 0;
X BEGIN(ACTION);
X return ( '\n' );
X }
X
X<SECT2>^{OPTWS}\n ++linenum; return ( '\n' );
X
X<SECT2>^"%%".* {
X /* guarantee that the SECT3 rule will have something
X * to match
X */
X yyless(1);
X sectnum = 3;
X BEGIN(SECT3);
X return ( EOF ); /* to stop the parser */
X }
X
X<SECT2>"["([^\\\]\n]|{ESCSEQ})+"]" {
X (void) strcpy( nmstr, yytext );
X
X /* check to see if we've already encountered this ccl */
X if ( (cclval = ccllookup( nmstr )) )
X {
X yylval = cclval;
X ++cclreuse;
X return ( PREVCCL );
X }
X else
X {
X /* we fudge a bit. We know that this ccl will
X * soon be numbered as lastccl + 1 by cclinit
X */
X cclinstal( nmstr, lastccl + 1 );
X
X /* push back everything but the leading bracket
X * so the ccl can be rescanned
X */
X PUT_BACK_STRING(nmstr, 1);
X
X BEGIN(FIRSTCCL);
X return ( '[' );
X }
X }
X
X<SECT2>"{"{NAME}"}" {
X register char *nmdefptr;
X char *ndlookup();
X
X (void) strcpy( nmstr, yytext );
X nmstr[yyleng - 1] = '\0'; /* chop trailing brace */
X
X /* lookup from "nmstr + 1" to chop leading brace */
X if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
X synerr( "undefined {name}" );
X
X else
X { /* push back name surrounded by ()'s */
X unput(')');
X PUT_BACK_STRING(nmdefptr, 0);
X unput('(');
X }
X }
X
X<SECT2>[/|*+?.()] return ( yytext[0] );
X<SECT2>. RETURNCHAR;
X<SECT2>\n ++linenum; return ( '\n' );
X
X
X<SC>"," return ( ',' );
X<SC>">" BEGIN(SECT2); return ( '>' );
X<SC>">"/"^" BEGIN(CARETISBOL); return ( '>' );
X<SC>{SCNAME} RETURNNAME;
X<SC>. synerr( "bad start condition name" );
X
X<CARETISBOL>"^" BEGIN(SECT2); return ( '^' );
X
X
X<QUOTE>[^"\n] RETURNCHAR;
X<QUOTE>\" BEGIN(SECT2); return ( '"' );
X
X<QUOTE>\n {
X synerr( "missing quote" );
X BEGIN(SECT2);
X ++linenum;
X return ( '"' );
X }
X
X
X<FIRSTCCL>"^"/[^-\n] BEGIN(CCL); return ( '^' );
X<FIRSTCCL>"^"/- return ( '^' );
X<FIRSTCCL>- BEGIN(CCL); yylval = '-'; return ( CHAR );
X<FIRSTCCL>. BEGIN(CCL); RETURNCHAR;
X
X<CCL>-/[^\]\n] return ( '-' );
X<CCL>[^\]\n] RETURNCHAR;
X<CCL>"]" BEGIN(SECT2); return ( ']' );
X
X
X<NUM>[0-9]+ {
X yylval = myctoi( yytext );
X return ( NUMBER );
X }
X
X<NUM>"," return ( ',' );
X<NUM>"}" BEGIN(SECT2); return ( '}' );
X
X<NUM>. {
X synerr( "bad character inside {}'s" );
X BEGIN(SECT2);
X return ( '}' );
X }
X
X<NUM>\n {
X synerr( "missing }" );
X BEGIN(SECT2);
X ++linenum;
X return ( '}' );
X }
X
X
X<BRACEERROR>"}" synerr( "bad name in {}'s" ); BEGIN(SECT2);
X<BRACEERROR>\n synerr( "missing }" ); ++linenum; BEGIN(SECT2);
X
X
X<PERCENT_BRACE_ACTION>{OPTWS}"%}".* bracelevel = 0;
X<PERCENT_BRACE_ACTION>.* ACTION_ECHO;
X<PERCENT_BRACE_ACTION>\n {
X ++linenum;
X ACTION_ECHO;
X if ( bracelevel == 0 )
X {
X fputs( "\tYY_BREAK\n", temp_action_file );
X BEGIN(SECT2);
X }
X }
X
X<ACTION>"{" ACTION_ECHO; ++bracelevel;
X<ACTION>"}" ACTION_ECHO; --bracelevel;
X<ACTION>[^{}"'/\n]+ ACTION_ECHO;
X<ACTION>"/*" ACTION_ECHO; BEGIN(ACTION_COMMENT);
X<ACTION>"'"([^'\\\n]|\\.)*"'" ACTION_ECHO; /* character constant */
X<ACTION>\" ACTION_ECHO; BEGIN(ACTION_STRING);
X<ACTION>\n {
X ++linenum;
X ACTION_ECHO;
X if ( bracelevel == 0 )
X {
X fputs( "\tYY_BREAK\n", temp_action_file );
X BEGIN(SECT2);
X }
X }
X<ACTION>. ACTION_ECHO;
X
X<ACTION_COMMENT>"*/" ACTION_ECHO; BEGIN(ACTION);
X<ACTION_COMMENT>[^*\n]+ ACTION_ECHO;
X<ACTION_COMMENT>"*" ACTION_ECHO;
X<ACTION_COMMENT>\n ++linenum; ACTION_ECHO;
X<ACTION_COMMENT>. ACTION_ECHO;
X
X<C_COMMENT_2>"*/" ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>"*/".*\n ++linenum; ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>[^*\n]+ ACTION_ECHO;
X<C_COMMENT_2>"*" ACTION_ECHO;
X<C_COMMENT_2>\n ++linenum; ACTION_ECHO;
X
X<ACTION_STRING>[^"\\\n]+ ACTION_ECHO;
X<ACTION_STRING>\\. ACTION_ECHO;
X<ACTION_STRING>\n ++linenum; ACTION_ECHO;
X<ACTION_STRING>\" ACTION_ECHO; BEGIN(ACTION);
X<ACTION_STRING>. ACTION_ECHO;
X
X
X<SECT2,QUOTE,CCL>{ESCSEQ} {
X yylval = myesc( yytext ) & BYTEMASK;
X return ( CHAR );
X }
X
X<FIRSTCCL>{ESCSEQ} {
X yylval = myesc( yytext ) & BYTEMASK;
X BEGIN(CCL);
X return ( CHAR );
X }
X
X
X<SECT3>.|\n {
X register int numchars;
X
X /* black magic - we know the names of a flex scanner's
X * internal variables. We cap the input buffer with
X * an end-of-string and dump it to the output.
X */
X YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
X
X#ifdef FLEX_FAST_SKEL
X fputs( yy_c_buf_p + 1, stdout );
X#else
X yy_ch_buf[yy_e_buf_p + 1] = '\0';
X
X /* ignore the first character; it's the second '%'
X * put back by the yyless(1) above
X */
X fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
X#endif
X
X /* if we don't do this, the data written by write()
X * can get overwritten when stdout is finally flushed
X */
X (void) fflush( stdout );
X
X while ( (numchars = read( fileno(yyin), yy_ch_buf,
X YY_BUF_MAX )) > 0 )
X (void) write( fileno(stdout), yy_ch_buf, numchars );
X
X if ( numchars < 0 )
X flexerror( "fatal read error in section 3" );
X
X return ( EOF );
X }
X%%
SHAR_EOF
if test 9222 -ne "`wc -c < 'scan.l'`"
then
echo shar: error transmitting "'scan.l'" '(should have been 9222 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--- end of part 4 ---
Technical Details
Message-ID:
<9386@dhw68k.cts.com>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!husc6!bloom-beacon!bu-cs!purdue!decwrl!hplabs!felix!dhw68k!macintoshReferences:
<9364@dhw68k.cts.com> <9368@dhw68k.cts.com> <9382@dhw68k.cts.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!husc6!bloom-beacon!bu-cs!purdue!decwrl!hplabs!felix!dhw68k!macintosh From: earleh@eleazar.dartmouth.edu (Earle R. Horton) Newsgroups: comp.sources.mac Subject: Flex for the Mac (part 4 of 7) Message-ID: <9386@dhw68k.cts.com> Date: 1 Jul 88 05:00:34 GMT References: <9364@dhw68k.cts.com> <9368@dhw68k.cts.com> <9382@dhw68k.cts.com> Sender: macintosh@dhw68k.cts.com Organization: Dartmouth College, Hanover, NH Lines: 2121 Approved: bytebug@dhw68k.cts.com (Roger L. Long)