Hardware sensors framework originally developed in OpenBSD and ported to
[dragonfly.git] / usr.bin / lex / parse.y
blob522449810fcaca223e9f7b59bcaa5637b3a8c94f
1 /* parse.y - parser for flex input */
3 %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
4 %token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
6 %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
7 %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
9 %{
10 /*-
11 * Copyright (c) 1990 The Regents of the University of California.
12 * All rights reserved.
14 * This code is derived from software contributed to Berkeley by
15 * Vern Paxson.
17 * The United States Government has rights in this work pursuant
18 * to contract no. DE-AC03-76SF00098 between the United States
19 * Department of Energy and the University of California.
21 * Redistribution and use in source and binary forms are permitted provided
22 * that: (1) source distributions retain this entire copyright notice and
23 * comment, and (2) distributions including binaries display the following
24 * acknowledgement: ``This product includes software developed by the
25 * University of California, Berkeley and its contributors'' in the
26 * documentation or other materials provided with the distribution and in
27 * all advertising materials mentioning features or use of this software.
28 * Neither the name of the University nor the names of its contributors may
29 * be used to endorse or promote products derived from this software without
30 * specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
36 /* $Header: /home/daffy/u0/vern/flex/RCS/parse.y,v 2.28 95/04/21 11:51:51 vern Exp $ */
37 /* $FreeBSD: src/usr.bin/lex/parse.y,v 1.3 1999/10/27 07:56:46 obrien Exp $ */
38 /* $DragonFly: src/usr.bin/lex/parse.y,v 1.3 2005/02/20 17:34:11 asmodai Exp $ */
41 /* Some versions of bison are broken in that they use alloca() but don't
42 * declare it properly. The following is the patented (just kidding!)
43 * #ifdef chud to fix the problem, courtesy of Francois Pinard.
46 #include "flexdef.h"
48 /* The remainder of the alloca() cruft has to come after including flexdef.h,
49 * so HAVE_ALLOCA_H is (possibly) defined.
51 #ifdef YYBISON
52 # ifdef __GNUC__
53 # ifndef alloca
54 # define alloca __builtin_alloca
55 # endif
56 # else
57 # if HAVE_ALLOCA_H
58 # include <alloca.h>
59 # else
60 char *alloca ();
61 # endif
62 # endif
63 #endif
65 /* Bletch, ^^^^ that was ugly! */
68 int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
69 int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
71 int *scon_stk;
72 int scon_stk_ptr;
74 static int madeany = false; /* whether we've made the '.' character class */
75 int previous_continued_action; /* whether the previous rule's action was '|' */
77 /* Expand a POSIX character class expression. */
78 #define CCL_EXPR(func) \
79 { \
80 int c; \
81 for ( c = 0; c < csize; ++c ) \
82 if ( isascii(c) && func(c) ) \
83 ccladd( currccl, c ); \
86 /* While POSIX defines isblank(), it's not ANSI C. */
87 #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
89 /* On some over-ambitious machines, such as DEC Alpha's, the default
90 * token type is "long" instead of "int"; this leads to problems with
91 * declaring yylval in flexdef.h. But so far, all the yacc's I've seen
92 * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
93 * following should ensure that the default token type is "int".
95 #define YYSTYPE int
100 goal : initlex sect1 sect1end sect2 initforrule
101 { /* add default rule */
102 int def_rule;
104 pat = cclinit();
105 cclnegate( pat );
107 def_rule = mkstate( -pat );
109 /* Remember the number of the default rule so we
110 * don't generate "can't match" warnings for it.
112 default_rule = num_rules;
114 finish_rule( def_rule, false, 0, 0 );
116 for ( i = 1; i <= lastsc; ++i )
117 scset[i] = mkbranch( scset[i], def_rule );
119 if ( spprdflt )
120 add_action(
121 "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
122 else
123 add_action( "ECHO" );
125 add_action( ";\n\tYY_BREAK\n" );
129 initlex :
130 { /* initialize for processing rules */
132 /* Create default DFA start condition. */
133 scinstal( "INITIAL", false );
137 sect1 : sect1 startconddecl namelist1
138 | sect1 options
140 | error
141 { synerr( "unknown error processing section 1" ); }
144 sect1end : SECTEND
146 check_options();
147 scon_stk = allocate_integer_array( lastsc + 1 );
148 scon_stk_ptr = 0;
152 startconddecl : SCDECL
153 { xcluflg = false; }
155 | XSCDECL
156 { xcluflg = true; }
159 namelist1 : namelist1 NAME
160 { scinstal( nmstr, xcluflg ); }
162 | NAME
163 { scinstal( nmstr, xcluflg ); }
165 | error
166 { synerr( "bad start condition list" ); }
169 options : OPTION_OP optionlist
172 optionlist : optionlist option
176 option : OPT_OUTFILE '=' NAME
178 outfilename = copy_string( nmstr );
179 did_outfilename = 1;
181 | OPT_PREFIX '=' NAME
182 { prefix = copy_string( nmstr ); }
183 | OPT_YYCLASS '=' NAME
184 { yyclass = copy_string( nmstr ); }
187 sect2 : sect2 scon initforrule flexrule '\n'
188 { scon_stk_ptr = $2; }
189 | sect2 scon '{' sect2 '}'
190 { scon_stk_ptr = $2; }
194 initforrule :
196 /* Initialize for a parse of one rule. */
197 trlcontxt = variable_trail_rule = varlength = false;
198 trailcnt = headcnt = rulelen = 0;
199 current_state_type = STATE_NORMAL;
200 previous_continued_action = continued_action;
201 in_rule = true;
203 new_rule();
207 flexrule : '^' rule
209 pat = $2;
210 finish_rule( pat, variable_trail_rule,
211 headcnt, trailcnt );
213 if ( scon_stk_ptr > 0 )
215 for ( i = 1; i <= scon_stk_ptr; ++i )
216 scbol[scon_stk[i]] =
217 mkbranch( scbol[scon_stk[i]],
218 pat );
221 else
223 /* Add to all non-exclusive start conditions,
224 * including the default (0) start condition.
227 for ( i = 1; i <= lastsc; ++i )
228 if ( ! scxclu[i] )
229 scbol[i] = mkbranch( scbol[i],
230 pat );
233 if ( ! bol_needed )
235 bol_needed = true;
237 if ( performance_report > 1 )
238 pinpoint_message(
239 "'^' operator results in sub-optimal performance" );
243 | rule
245 pat = $1;
246 finish_rule( pat, variable_trail_rule,
247 headcnt, trailcnt );
249 if ( scon_stk_ptr > 0 )
251 for ( i = 1; i <= scon_stk_ptr; ++i )
252 scset[scon_stk[i]] =
253 mkbranch( scset[scon_stk[i]],
254 pat );
257 else
259 for ( i = 1; i <= lastsc; ++i )
260 if ( ! scxclu[i] )
261 scset[i] =
262 mkbranch( scset[i],
263 pat );
267 | EOF_OP
269 if ( scon_stk_ptr > 0 )
270 build_eof_action();
272 else
274 /* This EOF applies to all start conditions
275 * which don't already have EOF actions.
277 for ( i = 1; i <= lastsc; ++i )
278 if ( ! sceof[i] )
279 scon_stk[++scon_stk_ptr] = i;
281 if ( scon_stk_ptr == 0 )
282 warn(
283 "all start conditions already have <<EOF>> rules" );
285 else
286 build_eof_action();
290 | error
291 { synerr( "unrecognized rule" ); }
294 scon_stk_ptr :
295 { $$ = scon_stk_ptr; }
298 scon : '<' scon_stk_ptr namelist2 '>'
299 { $$ = $2; }
301 | '<' '*' '>'
303 $$ = scon_stk_ptr;
305 for ( i = 1; i <= lastsc; ++i )
307 int j;
309 for ( j = 1; j <= scon_stk_ptr; ++j )
310 if ( scon_stk[j] == i )
311 break;
313 if ( j > scon_stk_ptr )
314 scon_stk[++scon_stk_ptr] = i;
319 { $$ = scon_stk_ptr; }
322 namelist2 : namelist2 ',' sconname
324 | sconname
326 | error
327 { synerr( "bad start condition list" ); }
330 sconname : NAME
332 if ( (scnum = sclookup( nmstr )) == 0 )
333 format_pinpoint_message(
334 "undeclared start condition %s",
335 nmstr );
336 else
338 for ( i = 1; i <= scon_stk_ptr; ++i )
339 if ( scon_stk[i] == scnum )
341 format_warn(
342 "<%s> specified twice",
343 scname[scnum] );
344 break;
347 if ( i > scon_stk_ptr )
348 scon_stk[++scon_stk_ptr] = scnum;
353 rule : re2 re
355 if ( transchar[lastst[$2]] != SYM_EPSILON )
356 /* Provide final transition \now/ so it
357 * will be marked as a trailing context
358 * state.
360 $2 = link_machines( $2,
361 mkstate( SYM_EPSILON ) );
363 mark_beginning_as_normal( $2 );
364 current_state_type = STATE_NORMAL;
366 if ( previous_continued_action )
368 /* We need to treat this as variable trailing
369 * context so that the backup does not happen
370 * in the action but before the action switch
371 * statement. If the backup happens in the
372 * action, then the rules "falling into" this
373 * one's action will *also* do the backup,
374 * erroneously.
376 if ( ! varlength || headcnt != 0 )
377 warn(
378 "trailing context made variable due to preceding '|' action" );
380 /* Mark as variable. */
381 varlength = true;
382 headcnt = 0;
385 if ( lex_compat || (varlength && headcnt == 0) )
386 { /* variable trailing context rule */
387 /* Mark the first part of the rule as the
388 * accepting "head" part of a trailing
389 * context rule.
391 * By the way, we didn't do this at the
392 * beginning of this production because back
393 * then current_state_type was set up for a
394 * trail rule, and add_accept() can create
395 * a new state ...
397 add_accept( $1,
398 num_rules | YY_TRAILING_HEAD_MASK );
399 variable_trail_rule = true;
402 else
403 trailcnt = rulelen;
405 $$ = link_machines( $1, $2 );
408 | re2 re '$'
409 { synerr( "trailing context used twice" ); }
411 | re '$'
413 headcnt = 0;
414 trailcnt = 1;
415 rulelen = 1;
416 varlength = false;
418 current_state_type = STATE_TRAILING_CONTEXT;
420 if ( trlcontxt )
422 synerr( "trailing context used twice" );
423 $$ = mkstate( SYM_EPSILON );
426 else if ( previous_continued_action )
428 /* See the comment in the rule for "re2 re"
429 * above.
431 warn(
432 "trailing context made variable due to preceding '|' action" );
434 varlength = true;
437 if ( lex_compat || varlength )
439 /* Again, see the comment in the rule for
440 * "re2 re" above.
442 add_accept( $1,
443 num_rules | YY_TRAILING_HEAD_MASK );
444 variable_trail_rule = true;
447 trlcontxt = true;
449 eps = mkstate( SYM_EPSILON );
450 $$ = link_machines( $1,
451 link_machines( eps, mkstate( '\n' ) ) );
454 | re
456 $$ = $1;
458 if ( trlcontxt )
460 if ( lex_compat || (varlength && headcnt == 0) )
461 /* Both head and trail are
462 * variable-length.
464 variable_trail_rule = true;
465 else
466 trailcnt = rulelen;
472 re : re '|' series
474 varlength = true;
475 $$ = mkor( $1, $3 );
478 | series
479 { $$ = $1; }
483 re2 : re '/'
485 /* This rule is written separately so the
486 * reduction will occur before the trailing
487 * series is parsed.
490 if ( trlcontxt )
491 synerr( "trailing context used twice" );
492 else
493 trlcontxt = true;
495 if ( varlength )
496 /* We hope the trailing context is
497 * fixed-length.
499 varlength = false;
500 else
501 headcnt = rulelen;
503 rulelen = 0;
505 current_state_type = STATE_TRAILING_CONTEXT;
506 $$ = $1;
510 series : series singleton
512 /* This is where concatenation of adjacent patterns
513 * gets done.
515 $$ = link_machines( $1, $2 );
518 | singleton
519 { $$ = $1; }
522 singleton : singleton '*'
524 varlength = true;
526 $$ = mkclos( $1 );
529 | singleton '+'
531 varlength = true;
532 $$ = mkposcl( $1 );
535 | singleton '?'
537 varlength = true;
538 $$ = mkopt( $1 );
541 | singleton '{' NUMBER ',' NUMBER '}'
543 varlength = true;
545 if ( $3 > $5 || $3 < 0 )
547 synerr( "bad iteration values" );
548 $$ = $1;
550 else
552 if ( $3 == 0 )
554 if ( $5 <= 0 )
556 synerr(
557 "bad iteration values" );
558 $$ = $1;
560 else
561 $$ = mkopt(
562 mkrep( $1, 1, $5 ) );
564 else
565 $$ = mkrep( $1, $3, $5 );
569 | singleton '{' NUMBER ',' '}'
571 varlength = true;
573 if ( $3 <= 0 )
575 synerr( "iteration value must be positive" );
576 $$ = $1;
579 else
580 $$ = mkrep( $1, $3, INFINITY );
583 | singleton '{' NUMBER '}'
585 /* The singleton could be something like "(foo)",
586 * in which case we have no idea what its length
587 * is, so we punt here.
589 varlength = true;
591 if ( $3 <= 0 )
593 synerr( "iteration value must be positive" );
594 $$ = $1;
597 else
598 $$ = link_machines( $1,
599 copysingl( $1, $3 - 1 ) );
602 | '.'
604 if ( ! madeany )
606 /* Create the '.' character class. */
607 anyccl = cclinit();
608 ccladd( anyccl, '\n' );
609 cclnegate( anyccl );
611 if ( useecs )
612 mkeccl( ccltbl + cclmap[anyccl],
613 ccllen[anyccl], nextecm,
614 ecgroup, csize, csize );
616 madeany = true;
619 ++rulelen;
621 $$ = mkstate( -anyccl );
624 | fullccl
626 if ( ! cclsorted )
627 /* Sort characters for fast searching. We
628 * use a shell sort since this list could
629 * be large.
631 cshell( ccltbl + cclmap[$1], ccllen[$1], true );
633 if ( useecs )
634 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
635 nextecm, ecgroup, csize, csize );
637 ++rulelen;
639 $$ = mkstate( -$1 );
642 | PREVCCL
644 ++rulelen;
646 $$ = mkstate( -$1 );
649 | '"' string '"'
650 { $$ = $2; }
652 | '(' re ')'
653 { $$ = $2; }
655 | CHAR
657 ++rulelen;
659 if ( caseins && $1 >= 'A' && $1 <= 'Z' )
660 $1 = clower( $1 );
662 $$ = mkstate( $1 );
666 fullccl : '[' ccl ']'
667 { $$ = $2; }
669 | '[' '^' ccl ']'
671 cclnegate( $3 );
672 $$ = $3;
676 ccl : ccl CHAR '-' CHAR
678 if ( caseins )
680 if ( $2 >= 'A' && $2 <= 'Z' )
681 $2 = clower( $2 );
682 if ( $4 >= 'A' && $4 <= 'Z' )
683 $4 = clower( $4 );
686 if ( $2 > $4 )
687 synerr( "negative range in character class" );
689 else
691 for ( i = $2; i <= $4; ++i )
692 ccladd( $1, i );
694 /* Keep track if this ccl is staying in
695 * alphabetical order.
697 cclsorted = cclsorted && ($2 > lastchar);
698 lastchar = $4;
701 $$ = $1;
704 | ccl CHAR
706 if ( caseins && $2 >= 'A' && $2 <= 'Z' )
707 $2 = clower( $2 );
709 ccladd( $1, $2 );
710 cclsorted = cclsorted && ($2 > lastchar);
711 lastchar = $2;
712 $$ = $1;
715 | ccl ccl_expr
717 /* Too hard to properly maintain cclsorted. */
718 cclsorted = false;
719 $$ = $1;
724 cclsorted = true;
725 lastchar = 0;
726 currccl = $$ = cclinit();
730 ccl_expr: CCE_ALNUM { CCL_EXPR(isalnum) }
731 | CCE_ALPHA { CCL_EXPR(isalpha) }
732 | CCE_BLANK { CCL_EXPR(IS_BLANK) }
733 | CCE_CNTRL { CCL_EXPR(iscntrl) }
734 | CCE_DIGIT { CCL_EXPR(isdigit) }
735 | CCE_GRAPH { CCL_EXPR(isgraph) }
736 | CCE_LOWER { CCL_EXPR(islower) }
737 | CCE_PRINT { CCL_EXPR(isprint) }
738 | CCE_PUNCT { CCL_EXPR(ispunct) }
739 | CCE_SPACE { CCL_EXPR(isspace) }
740 | CCE_UPPER {
741 if ( caseins )
742 CCL_EXPR(islower)
743 else
744 CCL_EXPR(isupper)
746 | CCE_XDIGIT { CCL_EXPR(isxdigit) }
749 string : string CHAR
751 if ( caseins && $2 >= 'A' && $2 <= 'Z' )
752 $2 = clower( $2 );
754 ++rulelen;
756 $$ = link_machines( $1, mkstate( $2 ) );
760 { $$ = mkstate( SYM_EPSILON ); }
766 /* build_eof_action - build the "<<EOF>>" action for the active start
767 * conditions
770 void build_eof_action()
772 register int i;
773 char action_text[MAXLINE];
775 for ( i = 1; i <= scon_stk_ptr; ++i )
777 if ( sceof[scon_stk[i]] )
778 format_pinpoint_message(
779 "multiple <<EOF>> rules for start condition %s",
780 scname[scon_stk[i]] );
782 else
784 sceof[scon_stk[i]] = true;
785 sprintf( action_text, "case YY_STATE_EOF(%s):\n",
786 scname[scon_stk[i]] );
787 add_action( action_text );
791 line_directive_out( (FILE *) 0, 1 );
793 /* This isn't a normal rule after all - don't count it as
794 * such, so we don't have any holes in the rule numbering
795 * (which make generating "rule can never match" warnings
796 * more difficult.
798 --num_rules;
799 ++num_eof_rules;
803 /* format_synerr - write out formatted syntax error */
805 void format_synerr( msg, arg )
806 char msg[], arg[];
808 char errmsg[MAXLINE];
810 (void) sprintf( errmsg, msg, arg );
811 synerr( errmsg );
815 /* synerr - report a syntax error */
817 void synerr( str )
818 char str[];
820 syntaxerror = true;
821 pinpoint_message( str );
825 /* format_warn - write out formatted warning */
827 void format_warn( msg, arg )
828 char msg[], arg[];
830 char warn_msg[MAXLINE];
832 (void) sprintf( warn_msg, msg, arg );
833 warn( warn_msg );
837 /* warn - report a warning, unless -w was given */
839 void warn( str )
840 char str[];
842 line_warning( str, linenum );
845 /* format_pinpoint_message - write out a message formatted with one string,
846 * pinpointing its location
849 void format_pinpoint_message( msg, arg )
850 char msg[], arg[];
852 char errmsg[MAXLINE];
854 (void) sprintf( errmsg, msg, arg );
855 pinpoint_message( errmsg );
859 /* pinpoint_message - write out a message, pinpointing its location */
861 void pinpoint_message( str )
862 char str[];
864 line_pinpoint( str, linenum );
868 /* line_warning - report a warning at a given line, unless -w was given */
870 void line_warning( str, line )
871 char str[];
872 int line;
874 char warning[MAXLINE];
876 if ( ! nowarn )
878 sprintf( warning, "warning, %s", str );
879 line_pinpoint( warning, line );
884 /* line_pinpoint - write out a message, pinpointing it at the given line */
886 void line_pinpoint( str, line )
887 char str[];
888 int line;
890 fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
894 /* yyerror - eat up an error message from the parser;
895 * currently, messages are ignore
898 void yyerror( msg )
899 char msg[];