2 /* parse.y - parser for flex input */
4 %token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP
8 * Copyright (c) 1990 The Regents of the University of California.
11 * This code is derived from software contributed to Berkeley by
14 * The United States Government has rights in this work pursuant
15 * to contract no. DE-AC03-76SF00098 between the United States
16 * Department of Energy and the University of California.
18 * Redistribution and use in source and binary forms are permitted provided
19 * that: (1) source distributions retain this entire copyright notice and
20 * comment, and (2) distributions including binaries display the following
21 * acknowledgement: ``This product includes software developed by the
22 * University of California, Berkeley and its contributors'' in the
23 * documentation or other materials provided with the distribution and in
24 * all advertising materials mentioning features or use of this software.
25 * Neither the name of the University nor the names of its contributors may
26 * be used to endorse or promote products derived from this software without
27 * specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
35 "@(#) $Id: parse.y,v 1.2 1994/06/24 10:57:18 ceriel Exp $ (LBL)";
40 int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen;
41 int trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule;
44 static int madeany = false; /* whether we've made the '.' character class */
45 int previous_continued_action; /* whether the previous rule's action was '|' */
50 goal : initlex sect1 sect1end sect2 initforrule
51 { /* add default rule */
57 def_rule = mkstate( -pat );
59 finish_rule( def_rule, false, 0, 0 );
61 for ( i = 1; i <= lastsc; ++i )
62 scset[i] = mkbranch( scset[i], def_rule );
65 fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )",
68 fputs( "ECHO", temp_action_file );
70 fputs( ";\n\tYY_BREAK\n", temp_action_file );
76 /* initialize for processing rules */
78 /* create default DFA start condition */
79 scinstal( "INITIAL", false );
83 sect1 : sect1 startconddecl WHITESPACE namelist1 '\n'
86 { synerr( "unknown error processing section 1" ); }
92 startconddecl : SCDECL
94 /* these productions are separate from the s1object
95 * rule because the semantics must be done before
96 * we parse the remainder of an s1object
106 namelist1 : namelist1 WHITESPACE NAME
107 { scinstal( nmstr, xcluflg ); }
110 { scinstal( nmstr, xcluflg ); }
113 { synerr( "bad start condition list" ); }
116 sect2 : sect2 initforrule flexrule '\n'
122 /* initialize for a parse of one rule */
123 trlcontxt = variable_trail_rule = varlength = false;
124 trailcnt = headcnt = rulelen = 0;
125 current_state_type = STATE_NORMAL;
126 previous_continued_action = continued_action;
131 flexrule : scon '^' rule
134 finish_rule( pat, variable_trail_rule,
137 for ( i = 1; i <= actvp; ++i )
139 mkbranch( scbol[actvsc[i]], pat );
145 if ( performance_report )
147 "'^' operator results in sub-optimal performance" );
154 finish_rule( pat, variable_trail_rule,
157 for ( i = 1; i <= actvp; ++i )
159 mkbranch( scset[actvsc[i]], pat );
165 finish_rule( pat, variable_trail_rule,
168 /* add to all non-exclusive start conditions,
169 * including the default (0) start condition
172 for ( i = 1; i <= lastsc; ++i )
174 scbol[i] = mkbranch( scbol[i], pat );
180 if ( performance_report )
182 "'^' operator results in sub-optimal performance" );
189 finish_rule( pat, variable_trail_rule,
192 for ( i = 1; i <= lastsc; ++i )
194 scset[i] = mkbranch( scset[i], pat );
198 { build_eof_action(); }
202 /* this EOF applies to all start conditions
203 * which don't already have EOF actions
207 for ( i = 1; i <= lastsc; ++i )
213 "warning - all start conditions already have <<EOF>> rules" );
220 { synerr( "unrecognized rule" ); }
223 scon : '<' namelist2 '>'
226 namelist2 : namelist2 ',' NAME
228 if ( (scnum = sclookup( nmstr )) == 0 )
229 format_pinpoint_message(
230 "undeclared start condition %s", nmstr );
233 actvsc[++actvp] = scnum;
238 if ( (scnum = sclookup( nmstr )) == 0 )
239 format_pinpoint_message(
240 "undeclared start condition %s", nmstr );
242 actvsc[actvp = 1] = scnum;
246 { synerr( "bad start condition list" ); }
251 if ( transchar[lastst[$2]] != SYM_EPSILON )
252 /* provide final transition \now/ so it
253 * will be marked as a trailing context
256 $2 = link_machines( $2, mkstate( SYM_EPSILON ) );
258 mark_beginning_as_normal( $2 );
259 current_state_type = STATE_NORMAL;
261 if ( previous_continued_action )
263 /* we need to treat this as variable trailing
264 * context so that the backup does not happen
265 * in the action but before the action switch
266 * statement. If the backup happens in the
267 * action, then the rules "falling into" this
268 * one's action will *also* do the backup,
271 if ( ! varlength || headcnt != 0 )
274 "%s: warning - trailing context rule at line %d made variable because\n",
275 program_name, linenum );
277 " of preceding '|' action\n" );
280 /* mark as variable */
285 if ( varlength && headcnt == 0 )
286 { /* variable trailing context rule */
287 /* mark the first part of the rule as the accepting
288 * "head" part of a trailing context rule
290 /* by the way, we didn't do this at the beginning
291 * of this production because back then
292 * current_state_type was set up for a trail
293 * rule, and add_accept() can create a new
296 add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK );
297 variable_trail_rule = true;
303 $$ = link_machines( $1, $2 );
307 { synerr( "trailing context used twice" ); }
313 synerr( "trailing context used twice" );
314 $$ = mkstate( SYM_EPSILON );
317 else if ( previous_continued_action )
319 /* see the comment in the rule for "re2 re"
322 if ( ! varlength || headcnt != 0 )
325 "%s: warning - trailing context rule at line %d made variable because\n",
326 program_name, linenum );
328 " of preceding '|' action\n" );
331 /* mark as variable */
344 eps = mkstate( SYM_EPSILON );
345 $$ = link_machines( $1,
346 link_machines( eps, mkstate( '\n' ) ) );
355 if ( varlength && headcnt == 0 )
356 /* both head and trail are variable-length */
357 variable_trail_rule = true;
378 /* this rule is written separately so
379 * the reduction will occur before the trailing
384 synerr( "trailing context used twice" );
389 /* we hope the trailing context is fixed-length */
396 current_state_type = STATE_TRAILING_CONTEXT;
401 series : series singleton
403 /* this is where concatenation of adjacent patterns
406 $$ = link_machines( $1, $2 );
413 singleton : singleton '*'
434 | singleton '{' NUMBER ',' NUMBER '}'
438 if ( $3 > $5 || $3 < 0 )
440 synerr( "bad iteration values" );
446 $$ = mkopt( mkrep( $1, $3, $5 ) );
448 $$ = mkrep( $1, $3, $5 );
452 | singleton '{' NUMBER ',' '}'
458 synerr( "iteration value must be positive" );
463 $$ = mkrep( $1, $3, INFINITY );
466 | singleton '{' NUMBER '}'
468 /* the singleton could be something like "(foo)",
469 * in which case we have no idea what its length
470 * is, so we punt here.
476 synerr( "iteration value must be positive" );
481 $$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
488 /* create the '.' character class */
490 ccladd( anyccl, '\n' );
494 mkeccl( ccltbl + cclmap[anyccl],
495 ccllen[anyccl], nextecm,
496 ecgroup, csize, csize );
503 $$ = mkstate( -anyccl );
509 /* sort characters for fast searching. We use a
510 * shell sort since this list could be large.
512 cshell( ccltbl + cclmap[$1], ccllen[$1], true );
515 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
516 nextecm, ecgroup, csize, csize );
540 if ( caseins && $1 >= 'A' && $1 <= 'Z' )
547 fullccl : '[' ccl ']'
552 /* *Sigh* - to be compatible Unix lex, negated ccls
556 ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
557 cclsorted = false; /* because we added the newline */
564 ccl : ccl CHAR '-' CHAR
567 synerr( "negative range in character class" );
573 if ( $2 >= 'A' && $2 <= 'Z' )
575 if ( $4 >= 'A' && $4 <= 'Z' )
579 for ( i = $2; i <= $4; ++i )
582 /* keep track if this ccl is staying in alphabetical
585 cclsorted = cclsorted && ($2 > lastchar);
595 if ( $2 >= 'A' && $2 <= 'Z' )
599 cclsorted = cclsorted && ($2 > lastchar);
615 if ( $2 >= 'A' && $2 <= 'Z' )
620 $$ = link_machines( $1, mkstate( $2 ) );
624 { $$ = mkstate( SYM_EPSILON ); }
630 /* build_eof_action - build the "<<EOF>>" action for the active start
634 void build_eof_action()
639 for ( i = 1; i <= actvp; ++i )
641 if ( sceof[actvsc[i]] )
642 format_pinpoint_message(
643 "multiple <<EOF>> rules for start condition %s",
648 sceof[actvsc[i]] = true;
649 fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n",
654 line_directive_out( temp_action_file );
658 /* synerr - report a syntax error */
665 pinpoint_message( str );
669 /* format_pinpoint_message - write out a message formatted with one string,
670 * pinpointing its location
673 void format_pinpoint_message( msg, arg )
677 char errmsg[MAXLINE];
679 (void) sprintf( errmsg, msg, arg );
680 pinpoint_message( errmsg );
684 /* pinpoint_message - write out a message, pinpointing its location */
686 void pinpoint_message( str )
690 fprintf( stderr, "\"%s\", line %d: %s\n", infilename, linenum, str );
694 /* yyerror - eat up an error message from the parser;
695 * currently, messages are ignore