/* parse.y - parser for flex input */
%token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP
* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Vern Paxson of Lawrence Berkeley Laboratory.
* 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, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid[] = "@(#)parse.y 5.2 (Berkeley) 6/18/90";
int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen;
int trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule;
static int madeany = false; /* whether we've made the '.' character class */
int previous_continued_action; /* whether the previous rule's action was '|' */
goal : initlex sect1 sect1end sect2 initforrule
def_rule = mkstate( -pat );
finish_rule( def_rule, false, 0, 0 );
for ( i = 1; i <= lastsc; ++i )
scset[i] = mkbranch( scset[i], def_rule );
fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )",
fputs( "ECHO", temp_action_file );
fputs( ";\n\tYY_BREAK\n", temp_action_file );
/* initialize for processing rules */
/* create default DFA start condition */
scinstal( "INITIAL", false );
sect1 : sect1 startconddecl WHITESPACE namelist1 '\n'
{ synerr( "unknown error processing section 1" ); }
/* these productions are separate from the s1object
* rule because the semantics must be done before
* we parse the remainder of an s1object
namelist1 : namelist1 WHITESPACE NAME
{ scinstal( nmstr, xcluflg ); }
{ scinstal( nmstr, xcluflg ); }
{ synerr( "bad start condition list" ); }
sect2 : sect2 initforrule flexrule '\n'
/* initialize for a parse of one rule */
trlcontxt = variable_trail_rule = varlength = false;
trailcnt = headcnt = rulelen = 0;
current_state_type = STATE_NORMAL;
previous_continued_action = continued_action;
finish_rule( pat, variable_trail_rule,
for ( i = 1; i <= actvp; ++i )
mkbranch( scbol[actvsc[i]], pat );
if ( performance_report )
"'^' operator results in sub-optimal performance" );
finish_rule( pat, variable_trail_rule,
for ( i = 1; i <= actvp; ++i )
mkbranch( scset[actvsc[i]], pat );
finish_rule( pat, variable_trail_rule,
/* add to all non-exclusive start conditions,
* including the default (0) start condition
for ( i = 1; i <= lastsc; ++i )
scbol[i] = mkbranch( scbol[i], pat );
if ( performance_report )
"'^' operator results in sub-optimal performance" );
finish_rule( pat, variable_trail_rule,
for ( i = 1; i <= lastsc; ++i )
scset[i] = mkbranch( scset[i], pat );
/* this EOF applies to all start conditions
* which don't already have EOF actions
for ( i = 1; i <= lastsc; ++i )
"warning - all start conditions already have <<EOF>> rules" );
{ synerr( "unrecognized rule" ); }
namelist2 : namelist2 ',' NAME
if ( (scnum = sclookup( nmstr )) == 0 )
"undeclared start condition %s", nmstr );
if ( (scnum = sclookup( nmstr )) == 0 )
"undeclared start condition %s", nmstr );
actvsc[actvp = 1] = scnum;
{ synerr( "bad start condition list" ); }
if ( transchar[lastst[$2]] != SYM_EPSILON )
/* provide final transition \now/ so it
* will be marked as a trailing context
$2 = link_machines( $2, mkstate( SYM_EPSILON ) );
mark_beginning_as_normal( $2 );
current_state_type = STATE_NORMAL;
if ( previous_continued_action )
/* we need to treat this as variable trailing
* context so that the backup does not happen
* in the action but before the action switch
* statement. If the backup happens in the
* action, then the rules "falling into" this
* one's action will *also* do the backup,
if ( ! varlength || headcnt != 0 )
"%s: warning - trailing context rule at line %d made variable because\n",
" of preceding '|' action\n" );
if ( varlength && headcnt == 0 )
{ /* variable trailing context rule */
/* mark the first part of the rule as the accepting
* "head" part of a trailing context rule
/* by the way, we didn't do this at the beginning
* of this production because back then
* current_state_type was set up for a trail
* rule, and add_accept() can create a new
add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK );
variable_trail_rule = true;
$$ = link_machines( $1, $2 );
{ synerr( "trailing context used twice" ); }
synerr( "trailing context used twice" );
$$ = mkstate( SYM_EPSILON );
else if ( previous_continued_action )
/* see the comment in the rule for "re2 re"
if ( ! varlength || headcnt != 0 )
"%s: warning - trailing context rule at line %d made variable because\n",
" of preceding '|' action\n" );
eps = mkstate( SYM_EPSILON );
link_machines( eps, mkstate( '\n' ) ) );
if ( varlength && headcnt == 0 )
/* both head and trail are variable-length */
variable_trail_rule = true;
/* this rule is written separately so
* the reduction will occur before the trailing
synerr( "trailing context used twice" );
/* we hope the trailing context is fixed-length */
current_state_type = STATE_TRAILING_CONTEXT;
series : series singleton
/* this is where concatenation of adjacent patterns
$$ = link_machines( $1, $2 );
singleton : singleton '*'
| singleton '{' NUMBER ',' NUMBER '}'
synerr( "bad iteration values" );
$$ = mkopt( mkrep( $1, $3, $5 ) );
$$ = mkrep( $1, $3, $5 );
| singleton '{' NUMBER ',' '}'
synerr( "iteration value must be positive" );
$$ = mkrep( $1, $3, INFINITY );
| singleton '{' NUMBER '}'
/* the singleton could be something like "(foo)",
* in which case we have no idea what its length
synerr( "iteration value must be positive" );
$$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
/* create the '.' character class */
mkeccl( ccltbl + cclmap[anyccl],
/* sort characters for fast searching. We use a
* shell sort since this list could be large.
cshell( ccltbl + cclmap[$1], ccllen[$1], true );
mkeccl( ccltbl + cclmap[$1], ccllen[$1],
nextecm, ecgroup, csize, csize );
if ( caseins && $1 >= 'A' && $1 <= 'Z' )
/* *Sigh* - to be compatible Unix lex, negated ccls
ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
cclsorted = false; /* because we added the newline */
synerr( "negative range in character class" );
if ( $2 >= 'A' && $2 <= 'Z' )
if ( $4 >= 'A' && $4 <= 'Z' )
for ( i = $2; i <= $4; ++i )
/* keep track if this ccl is staying in alphabetical
cclsorted = cclsorted && ($2 > lastchar);
if ( $2 >= 'A' && $2 <= 'Z' )
cclsorted = cclsorted && ($2 > lastchar);
if ( $2 >= 'A' && $2 <= 'Z' )
$$ = link_machines( $1, mkstate( $2 ) );
{ $$ = mkstate( SYM_EPSILON ); }
/* build_eof_action - build the "<<EOF>>" action for the active start
for ( i = 1; i <= actvp; ++i )
"multiple <<EOF>> rules for start condition %s",
fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n",
line_directive_out( temp_action_file );
/* synerr - report a syntax error */
/* format_pinpoint_message - write out a message formatted with one string,
* pinpointing its location
void format_pinpoint_message( msg, arg )
(void) sprintf( errmsg, msg, arg );
pinpoint_message( errmsg );
/* pinpoint_message - write out a message, pinpointing its location */
void pinpoint_message( str )
fprintf( stderr, "\"%s\", line %d: %s\n", infilename, linenum, str );
/* yyerror - eat up an error message from the parser;
* currently, messages are ignore