Annotation of src/usr.bin/lex/parse.y, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: parse.y,v 1.7 2002/05/31 22:49:29 deraadt Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /* parse.y - parser for flex input */
4:
5: %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
6: %token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
7:
8: %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
9: %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
10:
11: %{
12: /*-
13: * Copyright (c) 1990 The Regents of the University of California.
14: * All rights reserved.
15: *
16: * This code is derived from software contributed to Berkeley by
17: * Vern Paxson.
18: *
19: * The United States Government has rights in this work pursuant
20: * to contract no. DE-AC03-76SF00098 between the United States
21: * Department of Energy and the University of California.
22: *
1.4 deraadt 23: * Redistribution and use in source and binary forms, with or without
1.8 ! millert 24: * modification, are permitted provided that the following conditions
! 25: * are met:
! 26: *
! 27: * 1. Redistributions of source code must retain the above copyright
! 28: * notice, this list of conditions and the following disclaimer.
! 29: * 2. Redistributions in binary form must reproduce the above copyright
! 30: * notice, this list of conditions and the following disclaimer in the
! 31: * documentation and/or other materials provided with the distribution.
! 32: *
! 33: * Neither the name of the University nor the names of its contributors
! 34: * may be used to endorse or promote products derived from this software
! 35: * without specific prior written permission.
! 36: *
! 37: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
! 38: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
! 39: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 40: * PURPOSE.
1.1 deraadt 41: */
42:
1.8 ! millert 43: /* $Header: /cvs/src/usr.bin/lex/parse.y,v 1.7 2002/05/31 22:49:29 deraadt Exp $ */
1.1 deraadt 44:
45:
46: /* Some versions of bison are broken in that they use alloca() but don't
47: * declare it properly. The following is the patented (just kidding!)
48: * #ifdef chud to fix the problem, courtesy of Francois Pinard.
49: */
50: #ifdef YYBISON
51: /* AIX requires this to be the first thing in the file. What a piece. */
52: # ifdef _AIX
53: #pragma alloca
54: # endif
55: #endif
56:
57: #include "flexdef.h"
58:
59: /* The remainder of the alloca() cruft has to come after including flexdef.h,
60: * so HAVE_ALLOCA_H is (possibly) defined.
61: */
62: #ifdef YYBISON
63: # ifdef __GNUC__
64: # ifndef alloca
65: # define alloca __builtin_alloca
66: # endif
67: # else
68: # if HAVE_ALLOCA_H
69: # include <alloca.h>
70: # else
71: # ifdef __hpux
72: void *alloca ();
73: # else
74: # ifdef __TURBOC__
75: # include <malloc.h>
76: # else
77: char *alloca ();
78: # endif
79: # endif
80: # endif
81: # endif
82: #endif
83:
84: /* Bletch, ^^^^ that was ugly! */
85:
86:
87: int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
88: int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
89:
90: int *scon_stk;
91: int scon_stk_ptr;
92:
93: static int madeany = false; /* whether we've made the '.' character class */
94: int previous_continued_action; /* whether the previous rule's action was '|' */
95:
96: /* Expand a POSIX character class expression. */
97: #define CCL_EXPR(func) \
98: { \
99: int c; \
100: for ( c = 0; c < csize; ++c ) \
101: if ( isascii(c) && func(c) ) \
102: ccladd( currccl, c ); \
103: }
104:
105: /* While POSIX defines isblank(), it's not ANSI C. */
106: #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
107:
108: /* On some over-ambitious machines, such as DEC Alpha's, the default
109: * token type is "long" instead of "int"; this leads to problems with
110: * declaring yylval in flexdef.h. But so far, all the yacc's I've seen
111: * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
112: * following should ensure that the default token type is "int".
113: */
114: #define YYSTYPE int
115:
116: %}
117:
118: %%
119: goal : initlex sect1 sect1end sect2 initforrule
120: { /* add default rule */
121: int def_rule;
122:
123: pat = cclinit();
124: cclnegate( pat );
125:
126: def_rule = mkstate( -pat );
127:
128: /* Remember the number of the default rule so we
129: * don't generate "can't match" warnings for it.
130: */
131: default_rule = num_rules;
132:
133: finish_rule( def_rule, false, 0, 0 );
134:
135: for ( i = 1; i <= lastsc; ++i )
136: scset[i] = mkbranch( scset[i], def_rule );
137:
138: if ( spprdflt )
139: add_action(
140: "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
141: else
142: add_action( "ECHO" );
143:
144: add_action( ";\n\tYY_BREAK\n" );
145: }
146: ;
147:
148: initlex :
149: { /* initialize for processing rules */
150:
151: /* Create default DFA start condition. */
152: scinstal( "INITIAL", false );
153: }
154: ;
155:
156: sect1 : sect1 startconddecl namelist1
157: | sect1 options
158: |
159: | error
160: { synerr( "unknown error processing section 1" ); }
161: ;
162:
163: sect1end : SECTEND
164: {
165: check_options();
166: scon_stk = allocate_integer_array( lastsc + 1 );
167: scon_stk_ptr = 0;
168: }
169: ;
170:
171: startconddecl : SCDECL
172: { xcluflg = false; }
173:
174: | XSCDECL
175: { xcluflg = true; }
176: ;
177:
178: namelist1 : namelist1 NAME
179: { scinstal( nmstr, xcluflg ); }
180:
181: | NAME
182: { scinstal( nmstr, xcluflg ); }
183:
184: | error
185: { synerr( "bad start condition list" ); }
186: ;
187:
188: options : OPTION_OP optionlist
189: ;
190:
191: optionlist : optionlist option
192: |
193: ;
194:
195: option : OPT_OUTFILE '=' NAME
196: {
197: outfilename = copy_string( nmstr );
198: did_outfilename = 1;
199: }
200: | OPT_PREFIX '=' NAME
201: { prefix = copy_string( nmstr ); }
202: | OPT_YYCLASS '=' NAME
203: { yyclass = copy_string( nmstr ); }
204: ;
205:
206: sect2 : sect2 scon initforrule flexrule '\n'
207: { scon_stk_ptr = $2; }
208: | sect2 scon '{' sect2 '}'
209: { scon_stk_ptr = $2; }
210: |
211: ;
212:
213: initforrule :
214: {
215: /* Initialize for a parse of one rule. */
216: trlcontxt = variable_trail_rule = varlength = false;
217: trailcnt = headcnt = rulelen = 0;
218: current_state_type = STATE_NORMAL;
219: previous_continued_action = continued_action;
220: in_rule = true;
221:
222: new_rule();
223: }
224: ;
225:
226: flexrule : '^' rule
227: {
228: pat = $2;
229: finish_rule( pat, variable_trail_rule,
230: headcnt, trailcnt );
231:
232: if ( scon_stk_ptr > 0 )
233: {
234: for ( i = 1; i <= scon_stk_ptr; ++i )
235: scbol[scon_stk[i]] =
236: mkbranch( scbol[scon_stk[i]],
237: pat );
238: }
239:
240: else
241: {
242: /* Add to all non-exclusive start conditions,
243: * including the default (0) start condition.
244: */
245:
246: for ( i = 1; i <= lastsc; ++i )
247: if ( ! scxclu[i] )
248: scbol[i] = mkbranch( scbol[i],
249: pat );
250: }
251:
252: if ( ! bol_needed )
253: {
254: bol_needed = true;
255:
256: if ( performance_report > 1 )
257: pinpoint_message(
258: "'^' operator results in sub-optimal performance" );
259: }
260: }
261:
262: | rule
263: {
264: pat = $1;
265: finish_rule( pat, variable_trail_rule,
266: headcnt, trailcnt );
267:
268: if ( scon_stk_ptr > 0 )
269: {
270: for ( i = 1; i <= scon_stk_ptr; ++i )
271: scset[scon_stk[i]] =
272: mkbranch( scset[scon_stk[i]],
273: pat );
274: }
275:
276: else
277: {
278: for ( i = 1; i <= lastsc; ++i )
279: if ( ! scxclu[i] )
280: scset[i] =
281: mkbranch( scset[i],
282: pat );
283: }
284: }
285:
286: | EOF_OP
287: {
288: if ( scon_stk_ptr > 0 )
289: build_eof_action();
290:
291: else
292: {
293: /* This EOF applies to all start conditions
294: * which don't already have EOF actions.
295: */
296: for ( i = 1; i <= lastsc; ++i )
297: if ( ! sceof[i] )
298: scon_stk[++scon_stk_ptr] = i;
299:
300: if ( scon_stk_ptr == 0 )
301: warn(
302: "all start conditions already have <<EOF>> rules" );
303:
304: else
305: build_eof_action();
306: }
307: }
308:
309: | error
310: { synerr( "unrecognized rule" ); }
311: ;
312:
313: scon_stk_ptr :
314: { $$ = scon_stk_ptr; }
315: ;
316:
317: scon : '<' scon_stk_ptr namelist2 '>'
318: { $$ = $2; }
319:
320: | '<' '*' '>'
321: {
322: $$ = scon_stk_ptr;
323:
324: for ( i = 1; i <= lastsc; ++i )
325: {
326: int j;
327:
328: for ( j = 1; j <= scon_stk_ptr; ++j )
329: if ( scon_stk[j] == i )
330: break;
331:
332: if ( j > scon_stk_ptr )
333: scon_stk[++scon_stk_ptr] = i;
334: }
335: }
336:
337: |
338: { $$ = scon_stk_ptr; }
339: ;
340:
341: namelist2 : namelist2 ',' sconname
342:
343: | sconname
344:
345: | error
346: { synerr( "bad start condition list" ); }
347: ;
348:
349: sconname : NAME
350: {
351: if ( (scnum = sclookup( nmstr )) == 0 )
352: format_pinpoint_message(
353: "undeclared start condition %s",
354: nmstr );
355: else
356: {
357: for ( i = 1; i <= scon_stk_ptr; ++i )
358: if ( scon_stk[i] == scnum )
359: {
360: format_warn(
361: "<%s> specified twice",
362: scname[scnum] );
363: break;
364: }
365:
366: if ( i > scon_stk_ptr )
367: scon_stk[++scon_stk_ptr] = scnum;
368: }
369: }
370: ;
371:
372: rule : re2 re
373: {
374: if ( transchar[lastst[$2]] != SYM_EPSILON )
375: /* Provide final transition \now/ so it
376: * will be marked as a trailing context
377: * state.
378: */
379: $2 = link_machines( $2,
380: mkstate( SYM_EPSILON ) );
381:
382: mark_beginning_as_normal( $2 );
383: current_state_type = STATE_NORMAL;
384:
385: if ( previous_continued_action )
386: {
387: /* We need to treat this as variable trailing
388: * context so that the backup does not happen
389: * in the action but before the action switch
390: * statement. If the backup happens in the
391: * action, then the rules "falling into" this
392: * one's action will *also* do the backup,
393: * erroneously.
394: */
395: if ( ! varlength || headcnt != 0 )
396: warn(
397: "trailing context made variable due to preceding '|' action" );
398:
399: /* Mark as variable. */
400: varlength = true;
401: headcnt = 0;
402: }
403:
404: if ( lex_compat || (varlength && headcnt == 0) )
405: { /* variable trailing context rule */
406: /* Mark the first part of the rule as the
407: * accepting "head" part of a trailing
408: * context rule.
409: *
410: * By the way, we didn't do this at the
411: * beginning of this production because back
412: * then current_state_type was set up for a
413: * trail rule, and add_accept() can create
414: * a new state ...
415: */
416: add_accept( $1,
417: num_rules | YY_TRAILING_HEAD_MASK );
418: variable_trail_rule = true;
419: }
420:
421: else
422: trailcnt = rulelen;
423:
424: $$ = link_machines( $1, $2 );
425: }
426:
427: | re2 re '$'
428: { synerr( "trailing context used twice" ); }
429:
430: | re '$'
431: {
432: headcnt = 0;
433: trailcnt = 1;
434: rulelen = 1;
435: varlength = false;
436:
437: current_state_type = STATE_TRAILING_CONTEXT;
438:
439: if ( trlcontxt )
440: {
441: synerr( "trailing context used twice" );
442: $$ = mkstate( SYM_EPSILON );
443: }
444:
445: else if ( previous_continued_action )
446: {
447: /* See the comment in the rule for "re2 re"
448: * above.
449: */
450: warn(
451: "trailing context made variable due to preceding '|' action" );
452:
453: varlength = true;
454: }
455:
456: if ( lex_compat || varlength )
457: {
458: /* Again, see the comment in the rule for
459: * "re2 re" above.
460: */
461: add_accept( $1,
462: num_rules | YY_TRAILING_HEAD_MASK );
463: variable_trail_rule = true;
464: }
465:
466: trlcontxt = true;
467:
468: eps = mkstate( SYM_EPSILON );
469: $$ = link_machines( $1,
470: link_machines( eps, mkstate( '\n' ) ) );
471: }
472:
473: | re
474: {
475: $$ = $1;
476:
477: if ( trlcontxt )
478: {
479: if ( lex_compat || (varlength && headcnt == 0) )
480: /* Both head and trail are
481: * variable-length.
482: */
483: variable_trail_rule = true;
484: else
485: trailcnt = rulelen;
486: }
487: }
488: ;
489:
490:
491: re : re '|' series
492: {
493: varlength = true;
494: $$ = mkor( $1, $3 );
495: }
496:
497: | series
498: { $$ = $1; }
499: ;
500:
501:
502: re2 : re '/'
503: {
504: /* This rule is written separately so the
505: * reduction will occur before the trailing
506: * series is parsed.
507: */
508:
509: if ( trlcontxt )
510: synerr( "trailing context used twice" );
511: else
512: trlcontxt = true;
513:
514: if ( varlength )
515: /* We hope the trailing context is
516: * fixed-length.
517: */
518: varlength = false;
519: else
520: headcnt = rulelen;
521:
522: rulelen = 0;
523:
524: current_state_type = STATE_TRAILING_CONTEXT;
525: $$ = $1;
526: }
527: ;
528:
529: series : series singleton
530: {
531: /* This is where concatenation of adjacent patterns
532: * gets done.
533: */
534: $$ = link_machines( $1, $2 );
535: }
536:
537: | singleton
538: { $$ = $1; }
539: ;
540:
541: singleton : singleton '*'
542: {
543: varlength = true;
544:
545: $$ = mkclos( $1 );
546: }
547:
548: | singleton '+'
549: {
550: varlength = true;
551: $$ = mkposcl( $1 );
552: }
553:
554: | singleton '?'
555: {
556: varlength = true;
557: $$ = mkopt( $1 );
558: }
559:
560: | singleton '{' NUMBER ',' NUMBER '}'
561: {
562: varlength = true;
563:
564: if ( $3 > $5 || $3 < 0 )
565: {
566: synerr( "bad iteration values" );
567: $$ = $1;
568: }
569: else
570: {
571: if ( $3 == 0 )
572: {
573: if ( $5 <= 0 )
574: {
575: synerr(
576: "bad iteration values" );
577: $$ = $1;
578: }
579: else
580: $$ = mkopt(
581: mkrep( $1, 1, $5 ) );
582: }
583: else
584: $$ = mkrep( $1, $3, $5 );
585: }
586: }
587:
588: | singleton '{' NUMBER ',' '}'
589: {
590: varlength = true;
591:
592: if ( $3 <= 0 )
593: {
594: synerr( "iteration value must be positive" );
595: $$ = $1;
596: }
597:
598: else
599: $$ = mkrep( $1, $3, INFINITY );
600: }
601:
602: | singleton '{' NUMBER '}'
603: {
604: /* The singleton could be something like "(foo)",
605: * in which case we have no idea what its length
606: * is, so we punt here.
607: */
608: varlength = true;
609:
610: if ( $3 <= 0 )
611: {
612: synerr( "iteration value must be positive" );
613: $$ = $1;
614: }
615:
616: else
617: $$ = link_machines( $1,
618: copysingl( $1, $3 - 1 ) );
619: }
620:
621: | '.'
622: {
623: if ( ! madeany )
624: {
625: /* Create the '.' character class. */
626: anyccl = cclinit();
627: ccladd( anyccl, '\n' );
628: cclnegate( anyccl );
629:
630: if ( useecs )
631: mkeccl( ccltbl + cclmap[anyccl],
632: ccllen[anyccl], nextecm,
633: ecgroup, csize, csize );
634:
635: madeany = true;
636: }
637:
638: ++rulelen;
639:
640: $$ = mkstate( -anyccl );
641: }
642:
643: | fullccl
644: {
645: if ( ! cclsorted )
646: /* Sort characters for fast searching. We
647: * use a shell sort since this list could
648: * be large.
649: */
650: cshell( ccltbl + cclmap[$1], ccllen[$1], true );
651:
652: if ( useecs )
653: mkeccl( ccltbl + cclmap[$1], ccllen[$1],
654: nextecm, ecgroup, csize, csize );
655:
656: ++rulelen;
657:
658: $$ = mkstate( -$1 );
659: }
660:
661: | PREVCCL
662: {
663: ++rulelen;
664:
665: $$ = mkstate( -$1 );
666: }
667:
668: | '"' string '"'
669: { $$ = $2; }
670:
671: | '(' re ')'
672: { $$ = $2; }
673:
674: | CHAR
675: {
676: ++rulelen;
677:
678: if ( caseins && $1 >= 'A' && $1 <= 'Z' )
679: $1 = clower( $1 );
680:
681: $$ = mkstate( $1 );
682: }
683: ;
684:
685: fullccl : '[' ccl ']'
686: { $$ = $2; }
687:
688: | '[' '^' ccl ']'
689: {
690: cclnegate( $3 );
691: $$ = $3;
692: }
693: ;
694:
695: ccl : ccl CHAR '-' CHAR
696: {
697: if ( caseins )
698: {
699: if ( $2 >= 'A' && $2 <= 'Z' )
700: $2 = clower( $2 );
701: if ( $4 >= 'A' && $4 <= 'Z' )
702: $4 = clower( $4 );
703: }
704:
705: if ( $2 > $4 )
706: synerr( "negative range in character class" );
707:
708: else
709: {
710: for ( i = $2; i <= $4; ++i )
711: ccladd( $1, i );
712:
713: /* Keep track if this ccl is staying in
714: * alphabetical order.
715: */
716: cclsorted = cclsorted && ($2 > lastchar);
717: lastchar = $4;
718: }
719:
720: $$ = $1;
721: }
722:
723: | ccl CHAR
724: {
725: if ( caseins && $2 >= 'A' && $2 <= 'Z' )
726: $2 = clower( $2 );
727:
728: ccladd( $1, $2 );
729: cclsorted = cclsorted && ($2 > lastchar);
730: lastchar = $2;
731: $$ = $1;
732: }
733:
734: | ccl ccl_expr
735: {
736: /* Too hard to properly maintain cclsorted. */
737: cclsorted = false;
738: $$ = $1;
739: }
740:
741: |
742: {
743: cclsorted = true;
744: lastchar = 0;
745: currccl = $$ = cclinit();
746: }
747: ;
748:
749: ccl_expr: CCE_ALNUM { CCL_EXPR(isalnum) }
750: | CCE_ALPHA { CCL_EXPR(isalpha) }
751: | CCE_BLANK { CCL_EXPR(IS_BLANK) }
752: | CCE_CNTRL { CCL_EXPR(iscntrl) }
753: | CCE_DIGIT { CCL_EXPR(isdigit) }
754: | CCE_GRAPH { CCL_EXPR(isgraph) }
755: | CCE_LOWER { CCL_EXPR(islower) }
756: | CCE_PRINT { CCL_EXPR(isprint) }
757: | CCE_PUNCT { CCL_EXPR(ispunct) }
758: | CCE_SPACE { CCL_EXPR(isspace) }
759: | CCE_UPPER {
760: if ( caseins )
761: CCL_EXPR(islower)
762: else
763: CCL_EXPR(isupper)
764: }
765: | CCE_XDIGIT { CCL_EXPR(isxdigit) }
766: ;
767:
768: string : string CHAR
769: {
770: if ( caseins && $2 >= 'A' && $2 <= 'Z' )
771: $2 = clower( $2 );
772:
773: ++rulelen;
774:
775: $$ = link_machines( $1, mkstate( $2 ) );
776: }
777:
778: |
779: { $$ = mkstate( SYM_EPSILON ); }
780: ;
781:
782: %%
783:
784:
785: /* build_eof_action - build the "<<EOF>>" action for the active start
786: * conditions
787: */
788:
789: void build_eof_action()
790: {
791: register int i;
792: char action_text[MAXLINE];
793:
794: for ( i = 1; i <= scon_stk_ptr; ++i )
795: {
796: if ( sceof[scon_stk[i]] )
797: format_pinpoint_message(
798: "multiple <<EOF>> rules for start condition %s",
799: scname[scon_stk[i]] );
800:
801: else
802: {
803: sceof[scon_stk[i]] = true;
1.7 deraadt 804: snprintf( action_text, sizeof action_text,
805: "case YY_STATE_EOF(%s):\n",
1.1 deraadt 806: scname[scon_stk[i]] );
807: add_action( action_text );
808: }
809: }
810:
811: line_directive_out( (FILE *) 0, 1 );
812:
813: /* This isn't a normal rule after all - don't count it as
814: * such, so we don't have any holes in the rule numbering
815: * (which make generating "rule can never match" warnings
816: * more difficult.
817: */
818: --num_rules;
819: ++num_eof_rules;
820: }
821:
822:
823: /* format_synerr - write out formatted syntax error */
824:
825: void format_synerr( msg, arg )
826: char msg[], arg[];
827: {
828: char errmsg[MAXLINE];
829:
1.7 deraadt 830: (void) snprintf( errmsg, sizeof errmsg, msg, arg );
1.1 deraadt 831: synerr( errmsg );
832: }
833:
834:
835: /* synerr - report a syntax error */
836:
837: void synerr( str )
838: char str[];
839: {
840: syntaxerror = true;
841: pinpoint_message( str );
842: }
843:
844:
845: /* format_warn - write out formatted warning */
846:
847: void format_warn( msg, arg )
848: char msg[], arg[];
849: {
850: char warn_msg[MAXLINE];
851:
1.7 deraadt 852: (void) snprintf( warn_msg, sizeof warn_msg, msg, arg );
1.1 deraadt 853: warn( warn_msg );
854: }
855:
856:
857: /* warn - report a warning, unless -w was given */
858:
859: void warn( str )
860: char str[];
861: {
862: line_warning( str, linenum );
863: }
864:
865: /* format_pinpoint_message - write out a message formatted with one string,
866: * pinpointing its location
867: */
868:
869: void format_pinpoint_message( msg, arg )
870: char msg[], arg[];
871: {
872: char errmsg[MAXLINE];
873:
1.7 deraadt 874: (void) snprintf( errmsg, sizeof errmsg, msg, arg );
1.1 deraadt 875: pinpoint_message( errmsg );
876: }
877:
878:
879: /* pinpoint_message - write out a message, pinpointing its location */
880:
881: void pinpoint_message( str )
882: char str[];
883: {
884: line_pinpoint( str, linenum );
885: }
886:
887:
888: /* line_warning - report a warning at a given line, unless -w was given */
889:
890: void line_warning( str, line )
891: char str[];
892: int line;
893: {
894: char warning[MAXLINE];
895:
896: if ( ! nowarn )
897: {
1.7 deraadt 898: snprintf( warning, sizeof warning, "warning, %s", str );
1.1 deraadt 899: line_pinpoint( warning, line );
900: }
901: }
902:
903:
904: /* line_pinpoint - write out a message, pinpointing it at the given line */
905:
906: void line_pinpoint( str, line )
907: char str[];
908: int line;
909: {
910: fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
911: }
912:
913:
914: /* yyerror - eat up an error message from the parser;
915: * currently, messages are ignore
916: */
917:
918: void yyerror( msg )
919: char msg[];
920: {
921: }