xref: /freebsd/contrib/flex/src/parse.y (revision 7e38239042df09edbbdc443ccb4825f9155c6bb7)
1*7e382390SJung-uk Kim /* parse.y - parser for flex input */
2*7e382390SJung-uk Kim 
3*7e382390SJung-uk Kim %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
4*7e382390SJung-uk Kim %token TOK_OPTION TOK_OUTFILE TOK_PREFIX TOK_YYCLASS TOK_HEADER_FILE TOK_EXTRA_TYPE
5*7e382390SJung-uk Kim %token TOK_TABLES_FILE
6*7e382390SJung-uk Kim 
7*7e382390SJung-uk Kim %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
8*7e382390SJung-uk Kim %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
9*7e382390SJung-uk Kim 
10*7e382390SJung-uk Kim %token CCE_NEG_ALNUM CCE_NEG_ALPHA CCE_NEG_BLANK CCE_NEG_CNTRL CCE_NEG_DIGIT CCE_NEG_GRAPH
11*7e382390SJung-uk Kim %token CCE_NEG_LOWER CCE_NEG_PRINT CCE_NEG_PUNCT CCE_NEG_SPACE CCE_NEG_UPPER CCE_NEG_XDIGIT
12*7e382390SJung-uk Kim 
13*7e382390SJung-uk Kim %left CCL_OP_DIFF CCL_OP_UNION
14*7e382390SJung-uk Kim 
15*7e382390SJung-uk Kim /*
16*7e382390SJung-uk Kim  *POSIX and AT&T lex place the
17*7e382390SJung-uk Kim  * precedence of the repeat operator, {}, below that of concatenation.
18*7e382390SJung-uk Kim  * Thus, ab{3} is ababab.  Most other POSIX utilities use an Extended
19*7e382390SJung-uk Kim  * Regular Expression (ERE) precedence that has the repeat operator
20*7e382390SJung-uk Kim  * higher than concatenation.  This causes ab{3} to yield abbb.
21*7e382390SJung-uk Kim  *
22*7e382390SJung-uk Kim  * In order to support the POSIX and AT&T precedence and the flex
23*7e382390SJung-uk Kim  * precedence we define two token sets for the begin and end tokens of
24*7e382390SJung-uk Kim  * the repeat operator, '{' and '}'.  The lexical scanner chooses
25*7e382390SJung-uk Kim  * which tokens to return based on whether posix_compat or lex_compat
26*7e382390SJung-uk Kim  * are specified. Specifying either posix_compat or lex_compat will
27*7e382390SJung-uk Kim  * cause flex to parse scanner files as per the AT&T and
28*7e382390SJung-uk Kim  * POSIX-mandated behavior.
29*7e382390SJung-uk Kim  */
30*7e382390SJung-uk Kim 
31*7e382390SJung-uk Kim %token BEGIN_REPEAT_POSIX END_REPEAT_POSIX BEGIN_REPEAT_FLEX END_REPEAT_FLEX
32*7e382390SJung-uk Kim 
33*7e382390SJung-uk Kim 
34*7e382390SJung-uk Kim %{
35*7e382390SJung-uk Kim /*  Copyright (c) 1990 The Regents of the University of California. */
36*7e382390SJung-uk Kim /*  All rights reserved. */
37*7e382390SJung-uk Kim 
38*7e382390SJung-uk Kim /*  This code is derived from software contributed to Berkeley by */
39*7e382390SJung-uk Kim /*  Vern Paxson. */
40*7e382390SJung-uk Kim 
41*7e382390SJung-uk Kim /*  The United States Government has rights in this work pursuant */
42*7e382390SJung-uk Kim /*  to contract no. DE-AC03-76SF00098 between the United States */
43*7e382390SJung-uk Kim /*  Department of Energy and the University of California. */
44*7e382390SJung-uk Kim 
45*7e382390SJung-uk Kim /*  This file is part of flex. */
46*7e382390SJung-uk Kim 
47*7e382390SJung-uk Kim /*  Redistribution and use in source and binary forms, with or without */
48*7e382390SJung-uk Kim /*  modification, are permitted provided that the following conditions */
49*7e382390SJung-uk Kim /*  are met: */
50*7e382390SJung-uk Kim 
51*7e382390SJung-uk Kim /*  1. Redistributions of source code must retain the above copyright */
52*7e382390SJung-uk Kim /*     notice, this list of conditions and the following disclaimer. */
53*7e382390SJung-uk Kim /*  2. Redistributions in binary form must reproduce the above copyright */
54*7e382390SJung-uk Kim /*     notice, this list of conditions and the following disclaimer in the */
55*7e382390SJung-uk Kim /*     documentation and/or other materials provided with the distribution. */
56*7e382390SJung-uk Kim 
57*7e382390SJung-uk Kim /*  Neither the name of the University nor the names of its contributors */
58*7e382390SJung-uk Kim /*  may be used to endorse or promote products derived from this software */
59*7e382390SJung-uk Kim /*  without specific prior written permission. */
60*7e382390SJung-uk Kim 
61*7e382390SJung-uk Kim /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
62*7e382390SJung-uk Kim /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
63*7e382390SJung-uk Kim /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
64*7e382390SJung-uk Kim /*  PURPOSE. */
65*7e382390SJung-uk Kim 
66*7e382390SJung-uk Kim #include "flexdef.h"
67*7e382390SJung-uk Kim #include "tables.h"
68*7e382390SJung-uk Kim 
69*7e382390SJung-uk Kim int pat, scnum, eps, headcnt, trailcnt, lastchar, i, rulelen;
70*7e382390SJung-uk Kim int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
71*7e382390SJung-uk Kim 
72*7e382390SJung-uk Kim int *scon_stk;
73*7e382390SJung-uk Kim int scon_stk_ptr;
74*7e382390SJung-uk Kim 
75*7e382390SJung-uk Kim static int madeany = false;  /* whether we've made the '.' character class */
76*7e382390SJung-uk Kim static int ccldot, cclany;
77*7e382390SJung-uk Kim int previous_continued_action;	/* whether the previous rule's action was '|' */
78*7e382390SJung-uk Kim 
79*7e382390SJung-uk Kim #define format_warn3(fmt, a1, a2) \
80*7e382390SJung-uk Kim 	do{ \
81*7e382390SJung-uk Kim         char fw3_msg[MAXLINE];\
82*7e382390SJung-uk Kim         snprintf( fw3_msg, MAXLINE,(fmt), (a1), (a2) );\
83*7e382390SJung-uk Kim         lwarn( fw3_msg );\
84*7e382390SJung-uk Kim 	}while(0)
85*7e382390SJung-uk Kim 
86*7e382390SJung-uk Kim /* Expand a POSIX character class expression. */
87*7e382390SJung-uk Kim #define CCL_EXPR(func) \
88*7e382390SJung-uk Kim 	do{ \
89*7e382390SJung-uk Kim 	int c; \
90*7e382390SJung-uk Kim 	for ( c = 0; c < csize; ++c ) \
91*7e382390SJung-uk Kim 		if ( isascii(c) && func(c) ) \
92*7e382390SJung-uk Kim 			ccladd( currccl, c ); \
93*7e382390SJung-uk Kim 	}while(0)
94*7e382390SJung-uk Kim 
95*7e382390SJung-uk Kim /* negated class */
96*7e382390SJung-uk Kim #define CCL_NEG_EXPR(func) \
97*7e382390SJung-uk Kim 	do{ \
98*7e382390SJung-uk Kim 	int c; \
99*7e382390SJung-uk Kim 	for ( c = 0; c < csize; ++c ) \
100*7e382390SJung-uk Kim 		if ( !func(c) ) \
101*7e382390SJung-uk Kim 			ccladd( currccl, c ); \
102*7e382390SJung-uk Kim 	}while(0)
103*7e382390SJung-uk Kim 
104*7e382390SJung-uk Kim /* While POSIX defines isblank(), it's not ANSI C. */
105*7e382390SJung-uk Kim #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
106*7e382390SJung-uk Kim 
107*7e382390SJung-uk Kim /* On some over-ambitious machines, such as DEC Alpha's, the default
108*7e382390SJung-uk Kim  * token type is "long" instead of "int"; this leads to problems with
109*7e382390SJung-uk Kim  * declaring yylval in flexdef.h.  But so far, all the yacc's I've seen
110*7e382390SJung-uk Kim  * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
111*7e382390SJung-uk Kim  * following should ensure that the default token type is "int".
112*7e382390SJung-uk Kim  */
113*7e382390SJung-uk Kim #define YYSTYPE int
114*7e382390SJung-uk Kim 
115*7e382390SJung-uk Kim %}
116*7e382390SJung-uk Kim 
117*7e382390SJung-uk Kim %%
118*7e382390SJung-uk Kim goal		:  initlex sect1 sect1end sect2 initforrule
119*7e382390SJung-uk Kim 			{ /* add default rule */
120*7e382390SJung-uk Kim 			int def_rule;
121*7e382390SJung-uk Kim 
122*7e382390SJung-uk Kim 			pat = cclinit();
123*7e382390SJung-uk Kim 			cclnegate( pat );
124*7e382390SJung-uk Kim 
125*7e382390SJung-uk Kim 			def_rule = mkstate( -pat );
126*7e382390SJung-uk Kim 
127*7e382390SJung-uk Kim 			/* Remember the number of the default rule so we
128*7e382390SJung-uk Kim 			 * don't generate "can't match" warnings for it.
129*7e382390SJung-uk Kim 			 */
130*7e382390SJung-uk Kim 			default_rule = num_rules;
131*7e382390SJung-uk Kim 
132*7e382390SJung-uk Kim 			finish_rule( def_rule, false, 0, 0, 0);
133*7e382390SJung-uk Kim 
134*7e382390SJung-uk Kim 			for ( i = 1; i <= lastsc; ++i )
135*7e382390SJung-uk Kim 				scset[i] = mkbranch( scset[i], def_rule );
136*7e382390SJung-uk Kim 
137*7e382390SJung-uk Kim 			if ( spprdflt )
138*7e382390SJung-uk Kim 				add_action(
139*7e382390SJung-uk Kim 				"YY_FATAL_ERROR( \"flex scanner jammed\" )" );
140*7e382390SJung-uk Kim 			else
141*7e382390SJung-uk Kim 				add_action( "ECHO" );
142*7e382390SJung-uk Kim 
143*7e382390SJung-uk Kim 			add_action( ";\n\tYY_BREAK]]\n" );
144*7e382390SJung-uk Kim 			}
145*7e382390SJung-uk Kim 		;
146*7e382390SJung-uk Kim 
147*7e382390SJung-uk Kim initlex		:
148*7e382390SJung-uk Kim 			{ /* initialize for processing rules */
149*7e382390SJung-uk Kim 
150*7e382390SJung-uk Kim 			/* Create default DFA start condition. */
151*7e382390SJung-uk Kim 			scinstal( "INITIAL", false );
152*7e382390SJung-uk Kim 			}
153*7e382390SJung-uk Kim 		;
154*7e382390SJung-uk Kim 
155*7e382390SJung-uk Kim sect1		:  sect1 startconddecl namelist1
156*7e382390SJung-uk Kim 		|  sect1 options
157*7e382390SJung-uk Kim 		|
158*7e382390SJung-uk Kim 		|  error
159*7e382390SJung-uk Kim 			{ synerr( _("unknown error processing section 1") ); }
160*7e382390SJung-uk Kim 		;
161*7e382390SJung-uk Kim 
162*7e382390SJung-uk Kim sect1end	:  SECTEND
163*7e382390SJung-uk Kim 			{
164*7e382390SJung-uk Kim 			check_options();
165*7e382390SJung-uk Kim 			scon_stk = allocate_integer_array( lastsc + 1 );
166*7e382390SJung-uk Kim 			scon_stk_ptr = 0;
167*7e382390SJung-uk Kim 			}
168*7e382390SJung-uk Kim 		;
169*7e382390SJung-uk Kim 
170*7e382390SJung-uk Kim startconddecl	:  SCDECL
171*7e382390SJung-uk Kim 			{ xcluflg = false; }
172*7e382390SJung-uk Kim 
173*7e382390SJung-uk Kim 		|  XSCDECL
174*7e382390SJung-uk Kim 			{ xcluflg = true; }
175*7e382390SJung-uk Kim 		;
176*7e382390SJung-uk Kim 
177*7e382390SJung-uk Kim namelist1	:  namelist1 NAME
178*7e382390SJung-uk Kim 			{ scinstal( nmstr, xcluflg ); }
179*7e382390SJung-uk Kim 
180*7e382390SJung-uk Kim 		|  NAME
181*7e382390SJung-uk Kim 			{ scinstal( nmstr, xcluflg ); }
182*7e382390SJung-uk Kim 
183*7e382390SJung-uk Kim 		|  error
184*7e382390SJung-uk Kim 			{ synerr( _("bad start condition list") ); }
185*7e382390SJung-uk Kim 		;
186*7e382390SJung-uk Kim 
187*7e382390SJung-uk Kim options		:  TOK_OPTION optionlist
188*7e382390SJung-uk Kim 		;
189*7e382390SJung-uk Kim 
190*7e382390SJung-uk Kim optionlist	:  optionlist option
191*7e382390SJung-uk Kim 		|
192*7e382390SJung-uk Kim 		;
193*7e382390SJung-uk Kim 
194*7e382390SJung-uk Kim option		:  TOK_OUTFILE '=' NAME
195*7e382390SJung-uk Kim 			{
196*7e382390SJung-uk Kim 			outfilename = xstrdup(nmstr);
197*7e382390SJung-uk Kim 			did_outfilename = 1;
198*7e382390SJung-uk Kim 			}
199*7e382390SJung-uk Kim 		|  TOK_EXTRA_TYPE '=' NAME
200*7e382390SJung-uk Kim 			{ extra_type = xstrdup(nmstr); }
201*7e382390SJung-uk Kim 		|  TOK_PREFIX '=' NAME
202*7e382390SJung-uk Kim 			{ prefix = xstrdup(nmstr);
203*7e382390SJung-uk Kim                           if (strchr(prefix, '[') || strchr(prefix, ']'))
204*7e382390SJung-uk Kim                               flexerror(_("Prefix must not contain [ or ]")); }
205*7e382390SJung-uk Kim 		|  TOK_YYCLASS '=' NAME
206*7e382390SJung-uk Kim 			{ yyclass = xstrdup(nmstr); }
207*7e382390SJung-uk Kim 		|  TOK_HEADER_FILE '=' NAME
208*7e382390SJung-uk Kim 			{ headerfilename = xstrdup(nmstr); }
209*7e382390SJung-uk Kim 	    |  TOK_TABLES_FILE '=' NAME
210*7e382390SJung-uk Kim             { tablesext = true; tablesfilename = xstrdup(nmstr); }
211*7e382390SJung-uk Kim 		;
212*7e382390SJung-uk Kim 
213*7e382390SJung-uk Kim sect2		:  sect2 scon initforrule flexrule '\n'
214*7e382390SJung-uk Kim 			{ scon_stk_ptr = $2; }
215*7e382390SJung-uk Kim 		|  sect2 scon '{' sect2 '}'
216*7e382390SJung-uk Kim 			{ scon_stk_ptr = $2; }
217*7e382390SJung-uk Kim 		|
218*7e382390SJung-uk Kim 		;
219*7e382390SJung-uk Kim 
220*7e382390SJung-uk Kim initforrule	:
221*7e382390SJung-uk Kim 			{
222*7e382390SJung-uk Kim 			/* Initialize for a parse of one rule. */
223*7e382390SJung-uk Kim 			trlcontxt = variable_trail_rule = varlength = false;
224*7e382390SJung-uk Kim 			trailcnt = headcnt = rulelen = 0;
225*7e382390SJung-uk Kim 			current_state_type = STATE_NORMAL;
226*7e382390SJung-uk Kim 			previous_continued_action = continued_action;
227*7e382390SJung-uk Kim 			in_rule = true;
228*7e382390SJung-uk Kim 
229*7e382390SJung-uk Kim 			new_rule();
230*7e382390SJung-uk Kim 			}
231*7e382390SJung-uk Kim 		;
232*7e382390SJung-uk Kim 
233*7e382390SJung-uk Kim flexrule	:  '^' rule
234*7e382390SJung-uk Kim 			{
235*7e382390SJung-uk Kim 			pat = $2;
236*7e382390SJung-uk Kim 			finish_rule( pat, variable_trail_rule,
237*7e382390SJung-uk Kim 				headcnt, trailcnt , previous_continued_action);
238*7e382390SJung-uk Kim 
239*7e382390SJung-uk Kim 			if ( scon_stk_ptr > 0 )
240*7e382390SJung-uk Kim 				{
241*7e382390SJung-uk Kim 				for ( i = 1; i <= scon_stk_ptr; ++i )
242*7e382390SJung-uk Kim 					scbol[scon_stk[i]] =
243*7e382390SJung-uk Kim 						mkbranch( scbol[scon_stk[i]],
244*7e382390SJung-uk Kim 								pat );
245*7e382390SJung-uk Kim 				}
246*7e382390SJung-uk Kim 
247*7e382390SJung-uk Kim 			else
248*7e382390SJung-uk Kim 				{
249*7e382390SJung-uk Kim 				/* Add to all non-exclusive start conditions,
250*7e382390SJung-uk Kim 				 * including the default (0) start condition.
251*7e382390SJung-uk Kim 				 */
252*7e382390SJung-uk Kim 
253*7e382390SJung-uk Kim 				for ( i = 1; i <= lastsc; ++i )
254*7e382390SJung-uk Kim 					if ( ! scxclu[i] )
255*7e382390SJung-uk Kim 						scbol[i] = mkbranch( scbol[i],
256*7e382390SJung-uk Kim 									pat );
257*7e382390SJung-uk Kim 				}
258*7e382390SJung-uk Kim 
259*7e382390SJung-uk Kim 			if ( ! bol_needed )
260*7e382390SJung-uk Kim 				{
261*7e382390SJung-uk Kim 				bol_needed = true;
262*7e382390SJung-uk Kim 
263*7e382390SJung-uk Kim 				if ( performance_report > 1 )
264*7e382390SJung-uk Kim 					pinpoint_message(
265*7e382390SJung-uk Kim 			"'^' operator results in sub-optimal performance" );
266*7e382390SJung-uk Kim 				}
267*7e382390SJung-uk Kim 			}
268*7e382390SJung-uk Kim 
269*7e382390SJung-uk Kim 		|  rule
270*7e382390SJung-uk Kim 			{
271*7e382390SJung-uk Kim 			pat = $1;
272*7e382390SJung-uk Kim 			finish_rule( pat, variable_trail_rule,
273*7e382390SJung-uk Kim 				headcnt, trailcnt , previous_continued_action);
274*7e382390SJung-uk Kim 
275*7e382390SJung-uk Kim 			if ( scon_stk_ptr > 0 )
276*7e382390SJung-uk Kim 				{
277*7e382390SJung-uk Kim 				for ( i = 1; i <= scon_stk_ptr; ++i )
278*7e382390SJung-uk Kim 					scset[scon_stk[i]] =
279*7e382390SJung-uk Kim 						mkbranch( scset[scon_stk[i]],
280*7e382390SJung-uk Kim 								pat );
281*7e382390SJung-uk Kim 				}
282*7e382390SJung-uk Kim 
283*7e382390SJung-uk Kim 			else
284*7e382390SJung-uk Kim 				{
285*7e382390SJung-uk Kim 				for ( i = 1; i <= lastsc; ++i )
286*7e382390SJung-uk Kim 					if ( ! scxclu[i] )
287*7e382390SJung-uk Kim 						scset[i] =
288*7e382390SJung-uk Kim 							mkbranch( scset[i],
289*7e382390SJung-uk Kim 								pat );
290*7e382390SJung-uk Kim 				}
291*7e382390SJung-uk Kim 			}
292*7e382390SJung-uk Kim 
293*7e382390SJung-uk Kim 		|  EOF_OP
294*7e382390SJung-uk Kim 			{
295*7e382390SJung-uk Kim 			if ( scon_stk_ptr > 0 )
296*7e382390SJung-uk Kim 				build_eof_action();
297*7e382390SJung-uk Kim 
298*7e382390SJung-uk Kim 			else
299*7e382390SJung-uk Kim 				{
300*7e382390SJung-uk Kim 				/* This EOF applies to all start conditions
301*7e382390SJung-uk Kim 				 * which don't already have EOF actions.
302*7e382390SJung-uk Kim 				 */
303*7e382390SJung-uk Kim 				for ( i = 1; i <= lastsc; ++i )
304*7e382390SJung-uk Kim 					if ( ! sceof[i] )
305*7e382390SJung-uk Kim 						scon_stk[++scon_stk_ptr] = i;
306*7e382390SJung-uk Kim 
307*7e382390SJung-uk Kim 				if ( scon_stk_ptr == 0 )
308*7e382390SJung-uk Kim 					lwarn(
309*7e382390SJung-uk Kim 			"all start conditions already have <<EOF>> rules" );
310*7e382390SJung-uk Kim 
311*7e382390SJung-uk Kim 				else
312*7e382390SJung-uk Kim 					build_eof_action();
313*7e382390SJung-uk Kim 				}
314*7e382390SJung-uk Kim 			}
315*7e382390SJung-uk Kim 
316*7e382390SJung-uk Kim 		|  error
317*7e382390SJung-uk Kim 			{ synerr( _("unrecognized rule") ); }
318*7e382390SJung-uk Kim 		;
319*7e382390SJung-uk Kim 
320*7e382390SJung-uk Kim scon_stk_ptr	:
321*7e382390SJung-uk Kim 			{ $$ = scon_stk_ptr; }
322*7e382390SJung-uk Kim 		;
323*7e382390SJung-uk Kim 
324*7e382390SJung-uk Kim scon		:  '<' scon_stk_ptr namelist2 '>'
325*7e382390SJung-uk Kim 			{ $$ = $2; }
326*7e382390SJung-uk Kim 
327*7e382390SJung-uk Kim 		|  '<' '*' '>'
328*7e382390SJung-uk Kim 			{
329*7e382390SJung-uk Kim 			$$ = scon_stk_ptr;
330*7e382390SJung-uk Kim 
331*7e382390SJung-uk Kim 			for ( i = 1; i <= lastsc; ++i )
332*7e382390SJung-uk Kim 				{
333*7e382390SJung-uk Kim 				int j;
334*7e382390SJung-uk Kim 
335*7e382390SJung-uk Kim 				for ( j = 1; j <= scon_stk_ptr; ++j )
336*7e382390SJung-uk Kim 					if ( scon_stk[j] == i )
337*7e382390SJung-uk Kim 						break;
338*7e382390SJung-uk Kim 
339*7e382390SJung-uk Kim 				if ( j > scon_stk_ptr )
340*7e382390SJung-uk Kim 					scon_stk[++scon_stk_ptr] = i;
341*7e382390SJung-uk Kim 				}
342*7e382390SJung-uk Kim 			}
343*7e382390SJung-uk Kim 
344*7e382390SJung-uk Kim 		|
345*7e382390SJung-uk Kim 			{ $$ = scon_stk_ptr; }
346*7e382390SJung-uk Kim 		;
347*7e382390SJung-uk Kim 
348*7e382390SJung-uk Kim namelist2	:  namelist2 ',' sconname
349*7e382390SJung-uk Kim 
350*7e382390SJung-uk Kim 		|  sconname
351*7e382390SJung-uk Kim 
352*7e382390SJung-uk Kim 		|  error
353*7e382390SJung-uk Kim 			{ synerr( _("bad start condition list") ); }
354*7e382390SJung-uk Kim 		;
355*7e382390SJung-uk Kim 
356*7e382390SJung-uk Kim sconname	:  NAME
357*7e382390SJung-uk Kim 			{
358*7e382390SJung-uk Kim 			if ( (scnum = sclookup( nmstr )) == 0 )
359*7e382390SJung-uk Kim 				format_pinpoint_message(
360*7e382390SJung-uk Kim 					"undeclared start condition %s",
361*7e382390SJung-uk Kim 					nmstr );
362*7e382390SJung-uk Kim 			else
363*7e382390SJung-uk Kim 				{
364*7e382390SJung-uk Kim 				for ( i = 1; i <= scon_stk_ptr; ++i )
365*7e382390SJung-uk Kim 					if ( scon_stk[i] == scnum )
366*7e382390SJung-uk Kim 						{
367*7e382390SJung-uk Kim 						format_warn(
368*7e382390SJung-uk Kim 							"<%s> specified twice",
369*7e382390SJung-uk Kim 							scname[scnum] );
370*7e382390SJung-uk Kim 						break;
371*7e382390SJung-uk Kim 						}
372*7e382390SJung-uk Kim 
373*7e382390SJung-uk Kim 				if ( i > scon_stk_ptr )
374*7e382390SJung-uk Kim 					scon_stk[++scon_stk_ptr] = scnum;
375*7e382390SJung-uk Kim 				}
376*7e382390SJung-uk Kim 			}
377*7e382390SJung-uk Kim 		;
378*7e382390SJung-uk Kim 
379*7e382390SJung-uk Kim rule		:  re2 re
380*7e382390SJung-uk Kim 			{
381*7e382390SJung-uk Kim 			if ( transchar[lastst[$2]] != SYM_EPSILON )
382*7e382390SJung-uk Kim 				/* Provide final transition \now/ so it
383*7e382390SJung-uk Kim 				 * will be marked as a trailing context
384*7e382390SJung-uk Kim 				 * state.
385*7e382390SJung-uk Kim 				 */
386*7e382390SJung-uk Kim 				$2 = link_machines( $2,
387*7e382390SJung-uk Kim 						mkstate( SYM_EPSILON ) );
388*7e382390SJung-uk Kim 
389*7e382390SJung-uk Kim 			mark_beginning_as_normal( $2 );
390*7e382390SJung-uk Kim 			current_state_type = STATE_NORMAL;
391*7e382390SJung-uk Kim 
392*7e382390SJung-uk Kim 			if ( previous_continued_action )
393*7e382390SJung-uk Kim 				{
394*7e382390SJung-uk Kim 				/* We need to treat this as variable trailing
395*7e382390SJung-uk Kim 				 * context so that the backup does not happen
396*7e382390SJung-uk Kim 				 * in the action but before the action switch
397*7e382390SJung-uk Kim 				 * statement.  If the backup happens in the
398*7e382390SJung-uk Kim 				 * action, then the rules "falling into" this
399*7e382390SJung-uk Kim 				 * one's action will *also* do the backup,
400*7e382390SJung-uk Kim 				 * erroneously.
401*7e382390SJung-uk Kim 				 */
402*7e382390SJung-uk Kim 				if ( ! varlength || headcnt != 0 )
403*7e382390SJung-uk Kim 					lwarn(
404*7e382390SJung-uk Kim 		"trailing context made variable due to preceding '|' action" );
405*7e382390SJung-uk Kim 
406*7e382390SJung-uk Kim 				/* Mark as variable. */
407*7e382390SJung-uk Kim 				varlength = true;
408*7e382390SJung-uk Kim 				headcnt = 0;
409*7e382390SJung-uk Kim 
410*7e382390SJung-uk Kim 				}
411*7e382390SJung-uk Kim 
412*7e382390SJung-uk Kim 			if ( lex_compat || (varlength && headcnt == 0) )
413*7e382390SJung-uk Kim 				{ /* variable trailing context rule */
414*7e382390SJung-uk Kim 				/* Mark the first part of the rule as the
415*7e382390SJung-uk Kim 				 * accepting "head" part of a trailing
416*7e382390SJung-uk Kim 				 * context rule.
417*7e382390SJung-uk Kim 				 *
418*7e382390SJung-uk Kim 				 * By the way, we didn't do this at the
419*7e382390SJung-uk Kim 				 * beginning of this production because back
420*7e382390SJung-uk Kim 				 * then current_state_type was set up for a
421*7e382390SJung-uk Kim 				 * trail rule, and add_accept() can create
422*7e382390SJung-uk Kim 				 * a new state ...
423*7e382390SJung-uk Kim 				 */
424*7e382390SJung-uk Kim 				add_accept( $1,
425*7e382390SJung-uk Kim 					num_rules | YY_TRAILING_HEAD_MASK );
426*7e382390SJung-uk Kim 				variable_trail_rule = true;
427*7e382390SJung-uk Kim 				}
428*7e382390SJung-uk Kim 
429*7e382390SJung-uk Kim 			else
430*7e382390SJung-uk Kim 				trailcnt = rulelen;
431*7e382390SJung-uk Kim 
432*7e382390SJung-uk Kim 			$$ = link_machines( $1, $2 );
433*7e382390SJung-uk Kim 			}
434*7e382390SJung-uk Kim 
435*7e382390SJung-uk Kim 		|  re2 re '$'
436*7e382390SJung-uk Kim 			{ synerr( _("trailing context used twice") ); }
437*7e382390SJung-uk Kim 
438*7e382390SJung-uk Kim 		|  re '$'
439*7e382390SJung-uk Kim 			{
440*7e382390SJung-uk Kim 			headcnt = 0;
441*7e382390SJung-uk Kim 			trailcnt = 1;
442*7e382390SJung-uk Kim 			rulelen = 1;
443*7e382390SJung-uk Kim 			varlength = false;
444*7e382390SJung-uk Kim 
445*7e382390SJung-uk Kim 			current_state_type = STATE_TRAILING_CONTEXT;
446*7e382390SJung-uk Kim 
447*7e382390SJung-uk Kim 			if ( trlcontxt )
448*7e382390SJung-uk Kim 				{
449*7e382390SJung-uk Kim 				synerr( _("trailing context used twice") );
450*7e382390SJung-uk Kim 				$$ = mkstate( SYM_EPSILON );
451*7e382390SJung-uk Kim 				}
452*7e382390SJung-uk Kim 
453*7e382390SJung-uk Kim 			else if ( previous_continued_action )
454*7e382390SJung-uk Kim 				{
455*7e382390SJung-uk Kim 				/* See the comment in the rule for "re2 re"
456*7e382390SJung-uk Kim 				 * above.
457*7e382390SJung-uk Kim 				 */
458*7e382390SJung-uk Kim 				lwarn(
459*7e382390SJung-uk Kim 		"trailing context made variable due to preceding '|' action" );
460*7e382390SJung-uk Kim 
461*7e382390SJung-uk Kim 				varlength = true;
462*7e382390SJung-uk Kim 				}
463*7e382390SJung-uk Kim 
464*7e382390SJung-uk Kim 			if ( lex_compat || varlength )
465*7e382390SJung-uk Kim 				{
466*7e382390SJung-uk Kim 				/* Again, see the comment in the rule for
467*7e382390SJung-uk Kim 				 * "re2 re" above.
468*7e382390SJung-uk Kim 				 */
469*7e382390SJung-uk Kim 				add_accept( $1,
470*7e382390SJung-uk Kim 					num_rules | YY_TRAILING_HEAD_MASK );
471*7e382390SJung-uk Kim 				variable_trail_rule = true;
472*7e382390SJung-uk Kim 				}
473*7e382390SJung-uk Kim 
474*7e382390SJung-uk Kim 			trlcontxt = true;
475*7e382390SJung-uk Kim 
476*7e382390SJung-uk Kim 			eps = mkstate( SYM_EPSILON );
477*7e382390SJung-uk Kim 			$$ = link_machines( $1,
478*7e382390SJung-uk Kim 				link_machines( eps, mkstate( '\n' ) ) );
479*7e382390SJung-uk Kim 			}
480*7e382390SJung-uk Kim 
481*7e382390SJung-uk Kim 		|  re
482*7e382390SJung-uk Kim 			{
483*7e382390SJung-uk Kim 			$$ = $1;
484*7e382390SJung-uk Kim 
485*7e382390SJung-uk Kim 			if ( trlcontxt )
486*7e382390SJung-uk Kim 				{
487*7e382390SJung-uk Kim 				if ( lex_compat || (varlength && headcnt == 0) )
488*7e382390SJung-uk Kim 					/* Both head and trail are
489*7e382390SJung-uk Kim 					 * variable-length.
490*7e382390SJung-uk Kim 					 */
491*7e382390SJung-uk Kim 					variable_trail_rule = true;
492*7e382390SJung-uk Kim 				else
493*7e382390SJung-uk Kim 					trailcnt = rulelen;
494*7e382390SJung-uk Kim 				}
495*7e382390SJung-uk Kim 			}
496*7e382390SJung-uk Kim 		;
497*7e382390SJung-uk Kim 
498*7e382390SJung-uk Kim 
499*7e382390SJung-uk Kim re		:  re '|' series
500*7e382390SJung-uk Kim 			{
501*7e382390SJung-uk Kim 			varlength = true;
502*7e382390SJung-uk Kim 			$$ = mkor( $1, $3 );
503*7e382390SJung-uk Kim 			}
504*7e382390SJung-uk Kim 
505*7e382390SJung-uk Kim 		|  series
506*7e382390SJung-uk Kim 			{ $$ = $1; }
507*7e382390SJung-uk Kim 		;
508*7e382390SJung-uk Kim 
509*7e382390SJung-uk Kim 
510*7e382390SJung-uk Kim re2		:  re '/'
511*7e382390SJung-uk Kim 			{
512*7e382390SJung-uk Kim 			/* This rule is written separately so the
513*7e382390SJung-uk Kim 			 * reduction will occur before the trailing
514*7e382390SJung-uk Kim 			 * series is parsed.
515*7e382390SJung-uk Kim 			 */
516*7e382390SJung-uk Kim 
517*7e382390SJung-uk Kim 			if ( trlcontxt )
518*7e382390SJung-uk Kim 				synerr( _("trailing context used twice") );
519*7e382390SJung-uk Kim 			else
520*7e382390SJung-uk Kim 				trlcontxt = true;
521*7e382390SJung-uk Kim 
522*7e382390SJung-uk Kim 			if ( varlength )
523*7e382390SJung-uk Kim 				/* We hope the trailing context is
524*7e382390SJung-uk Kim 				 * fixed-length.
525*7e382390SJung-uk Kim 				 */
526*7e382390SJung-uk Kim 				varlength = false;
527*7e382390SJung-uk Kim 			else
528*7e382390SJung-uk Kim 				headcnt = rulelen;
529*7e382390SJung-uk Kim 
530*7e382390SJung-uk Kim 			rulelen = 0;
531*7e382390SJung-uk Kim 
532*7e382390SJung-uk Kim 			current_state_type = STATE_TRAILING_CONTEXT;
533*7e382390SJung-uk Kim 			$$ = $1;
534*7e382390SJung-uk Kim 			}
535*7e382390SJung-uk Kim 		;
536*7e382390SJung-uk Kim 
537*7e382390SJung-uk Kim series		:  series singleton
538*7e382390SJung-uk Kim 			{
539*7e382390SJung-uk Kim 			/* This is where concatenation of adjacent patterns
540*7e382390SJung-uk Kim 			 * gets done.
541*7e382390SJung-uk Kim 			 */
542*7e382390SJung-uk Kim 			$$ = link_machines( $1, $2 );
543*7e382390SJung-uk Kim 			}
544*7e382390SJung-uk Kim 
545*7e382390SJung-uk Kim 		|  singleton
546*7e382390SJung-uk Kim 			{ $$ = $1; }
547*7e382390SJung-uk Kim 
548*7e382390SJung-uk Kim 		|  series BEGIN_REPEAT_POSIX NUMBER ',' NUMBER END_REPEAT_POSIX
549*7e382390SJung-uk Kim 			{
550*7e382390SJung-uk Kim 			varlength = true;
551*7e382390SJung-uk Kim 
552*7e382390SJung-uk Kim 			if ( $3 > $5 || $3 < 0 )
553*7e382390SJung-uk Kim 				{
554*7e382390SJung-uk Kim 				synerr( _("bad iteration values") );
555*7e382390SJung-uk Kim 				$$ = $1;
556*7e382390SJung-uk Kim 				}
557*7e382390SJung-uk Kim 			else
558*7e382390SJung-uk Kim 				{
559*7e382390SJung-uk Kim 				if ( $3 == 0 )
560*7e382390SJung-uk Kim 					{
561*7e382390SJung-uk Kim 					if ( $5 <= 0 )
562*7e382390SJung-uk Kim 						{
563*7e382390SJung-uk Kim 						synerr(
564*7e382390SJung-uk Kim 						_("bad iteration values") );
565*7e382390SJung-uk Kim 						$$ = $1;
566*7e382390SJung-uk Kim 						}
567*7e382390SJung-uk Kim 					else
568*7e382390SJung-uk Kim 						$$ = mkopt(
569*7e382390SJung-uk Kim 							mkrep( $1, 1, $5 ) );
570*7e382390SJung-uk Kim 					}
571*7e382390SJung-uk Kim 				else
572*7e382390SJung-uk Kim 					$$ = mkrep( $1, $3, $5 );
573*7e382390SJung-uk Kim 				}
574*7e382390SJung-uk Kim 			}
575*7e382390SJung-uk Kim 
576*7e382390SJung-uk Kim 		|  series BEGIN_REPEAT_POSIX NUMBER ',' END_REPEAT_POSIX
577*7e382390SJung-uk Kim 			{
578*7e382390SJung-uk Kim 			varlength = true;
579*7e382390SJung-uk Kim 
580*7e382390SJung-uk Kim 			if ( $3 <= 0 )
581*7e382390SJung-uk Kim 				{
582*7e382390SJung-uk Kim 				synerr( _("iteration value must be positive") );
583*7e382390SJung-uk Kim 				$$ = $1;
584*7e382390SJung-uk Kim 				}
585*7e382390SJung-uk Kim 
586*7e382390SJung-uk Kim 			else
587*7e382390SJung-uk Kim 				$$ = mkrep( $1, $3, INFINITE_REPEAT );
588*7e382390SJung-uk Kim 			}
589*7e382390SJung-uk Kim 
590*7e382390SJung-uk Kim 		|  series BEGIN_REPEAT_POSIX NUMBER END_REPEAT_POSIX
591*7e382390SJung-uk Kim 			{
592*7e382390SJung-uk Kim 			/* The series could be something like "(foo)",
593*7e382390SJung-uk Kim 			 * in which case we have no idea what its length
594*7e382390SJung-uk Kim 			 * is, so we punt here.
595*7e382390SJung-uk Kim 			 */
596*7e382390SJung-uk Kim 			varlength = true;
597*7e382390SJung-uk Kim 
598*7e382390SJung-uk Kim 			if ( $3 <= 0 )
599*7e382390SJung-uk Kim 				{
600*7e382390SJung-uk Kim 				  synerr( _("iteration value must be positive")
601*7e382390SJung-uk Kim 					  );
602*7e382390SJung-uk Kim 				$$ = $1;
603*7e382390SJung-uk Kim 				}
604*7e382390SJung-uk Kim 
605*7e382390SJung-uk Kim 			else
606*7e382390SJung-uk Kim 				$$ = link_machines( $1,
607*7e382390SJung-uk Kim 						copysingl( $1, $3 - 1 ) );
608*7e382390SJung-uk Kim 			}
609*7e382390SJung-uk Kim 
610*7e382390SJung-uk Kim 		;
611*7e382390SJung-uk Kim 
612*7e382390SJung-uk Kim singleton	:  singleton '*'
613*7e382390SJung-uk Kim 			{
614*7e382390SJung-uk Kim 			varlength = true;
615*7e382390SJung-uk Kim 
616*7e382390SJung-uk Kim 			$$ = mkclos( $1 );
617*7e382390SJung-uk Kim 			}
618*7e382390SJung-uk Kim 
619*7e382390SJung-uk Kim 		|  singleton '+'
620*7e382390SJung-uk Kim 			{
621*7e382390SJung-uk Kim 			varlength = true;
622*7e382390SJung-uk Kim 			$$ = mkposcl( $1 );
623*7e382390SJung-uk Kim 			}
624*7e382390SJung-uk Kim 
625*7e382390SJung-uk Kim 		|  singleton '?'
626*7e382390SJung-uk Kim 			{
627*7e382390SJung-uk Kim 			varlength = true;
628*7e382390SJung-uk Kim 			$$ = mkopt( $1 );
629*7e382390SJung-uk Kim 			}
630*7e382390SJung-uk Kim 
631*7e382390SJung-uk Kim 		|  singleton BEGIN_REPEAT_FLEX NUMBER ',' NUMBER END_REPEAT_FLEX
632*7e382390SJung-uk Kim 			{
633*7e382390SJung-uk Kim 			varlength = true;
634*7e382390SJung-uk Kim 
635*7e382390SJung-uk Kim 			if ( $3 > $5 || $3 < 0 )
636*7e382390SJung-uk Kim 				{
637*7e382390SJung-uk Kim 				synerr( _("bad iteration values") );
638*7e382390SJung-uk Kim 				$$ = $1;
639*7e382390SJung-uk Kim 				}
640*7e382390SJung-uk Kim 			else
641*7e382390SJung-uk Kim 				{
642*7e382390SJung-uk Kim 				if ( $3 == 0 )
643*7e382390SJung-uk Kim 					{
644*7e382390SJung-uk Kim 					if ( $5 <= 0 )
645*7e382390SJung-uk Kim 						{
646*7e382390SJung-uk Kim 						synerr(
647*7e382390SJung-uk Kim 						_("bad iteration values") );
648*7e382390SJung-uk Kim 						$$ = $1;
649*7e382390SJung-uk Kim 						}
650*7e382390SJung-uk Kim 					else
651*7e382390SJung-uk Kim 						$$ = mkopt(
652*7e382390SJung-uk Kim 							mkrep( $1, 1, $5 ) );
653*7e382390SJung-uk Kim 					}
654*7e382390SJung-uk Kim 				else
655*7e382390SJung-uk Kim 					$$ = mkrep( $1, $3, $5 );
656*7e382390SJung-uk Kim 				}
657*7e382390SJung-uk Kim 			}
658*7e382390SJung-uk Kim 
659*7e382390SJung-uk Kim 		|  singleton BEGIN_REPEAT_FLEX NUMBER ',' END_REPEAT_FLEX
660*7e382390SJung-uk Kim 			{
661*7e382390SJung-uk Kim 			varlength = true;
662*7e382390SJung-uk Kim 
663*7e382390SJung-uk Kim 			if ( $3 <= 0 )
664*7e382390SJung-uk Kim 				{
665*7e382390SJung-uk Kim 				synerr( _("iteration value must be positive") );
666*7e382390SJung-uk Kim 				$$ = $1;
667*7e382390SJung-uk Kim 				}
668*7e382390SJung-uk Kim 
669*7e382390SJung-uk Kim 			else
670*7e382390SJung-uk Kim 				$$ = mkrep( $1, $3, INFINITE_REPEAT );
671*7e382390SJung-uk Kim 			}
672*7e382390SJung-uk Kim 
673*7e382390SJung-uk Kim 		|  singleton BEGIN_REPEAT_FLEX NUMBER END_REPEAT_FLEX
674*7e382390SJung-uk Kim 			{
675*7e382390SJung-uk Kim 			/* The singleton could be something like "(foo)",
676*7e382390SJung-uk Kim 			 * in which case we have no idea what its length
677*7e382390SJung-uk Kim 			 * is, so we punt here.
678*7e382390SJung-uk Kim 			 */
679*7e382390SJung-uk Kim 			varlength = true;
680*7e382390SJung-uk Kim 
681*7e382390SJung-uk Kim 			if ( $3 <= 0 )
682*7e382390SJung-uk Kim 				{
683*7e382390SJung-uk Kim 				synerr( _("iteration value must be positive") );
684*7e382390SJung-uk Kim 				$$ = $1;
685*7e382390SJung-uk Kim 				}
686*7e382390SJung-uk Kim 
687*7e382390SJung-uk Kim 			else
688*7e382390SJung-uk Kim 				$$ = link_machines( $1,
689*7e382390SJung-uk Kim 						copysingl( $1, $3 - 1 ) );
690*7e382390SJung-uk Kim 			}
691*7e382390SJung-uk Kim 
692*7e382390SJung-uk Kim 		|  '.'
693*7e382390SJung-uk Kim 			{
694*7e382390SJung-uk Kim 			if ( ! madeany )
695*7e382390SJung-uk Kim 				{
696*7e382390SJung-uk Kim 				/* Create the '.' character class. */
697*7e382390SJung-uk Kim                     ccldot = cclinit();
698*7e382390SJung-uk Kim                     ccladd( ccldot, '\n' );
699*7e382390SJung-uk Kim                     cclnegate( ccldot );
700*7e382390SJung-uk Kim 
701*7e382390SJung-uk Kim                     if ( useecs )
702*7e382390SJung-uk Kim                         mkeccl( ccltbl + cclmap[ccldot],
703*7e382390SJung-uk Kim                             ccllen[ccldot], nextecm,
704*7e382390SJung-uk Kim                             ecgroup, csize, csize );
705*7e382390SJung-uk Kim 
706*7e382390SJung-uk Kim 				/* Create the (?s:'.') character class. */
707*7e382390SJung-uk Kim                     cclany = cclinit();
708*7e382390SJung-uk Kim                     cclnegate( cclany );
709*7e382390SJung-uk Kim 
710*7e382390SJung-uk Kim                     if ( useecs )
711*7e382390SJung-uk Kim                         mkeccl( ccltbl + cclmap[cclany],
712*7e382390SJung-uk Kim                             ccllen[cclany], nextecm,
713*7e382390SJung-uk Kim                             ecgroup, csize, csize );
714*7e382390SJung-uk Kim 
715*7e382390SJung-uk Kim 				madeany = true;
716*7e382390SJung-uk Kim 				}
717*7e382390SJung-uk Kim 
718*7e382390SJung-uk Kim 			++rulelen;
719*7e382390SJung-uk Kim 
720*7e382390SJung-uk Kim             if (sf_dot_all())
721*7e382390SJung-uk Kim                 $$ = mkstate( -cclany );
722*7e382390SJung-uk Kim             else
723*7e382390SJung-uk Kim                 $$ = mkstate( -ccldot );
724*7e382390SJung-uk Kim 			}
725*7e382390SJung-uk Kim 
726*7e382390SJung-uk Kim 		|  fullccl
727*7e382390SJung-uk Kim 			{
728*7e382390SJung-uk Kim 				/* Sort characters for fast searching.
729*7e382390SJung-uk Kim 				 */
730*7e382390SJung-uk Kim 				qsort( ccltbl + cclmap[$1], (size_t) ccllen[$1], sizeof (*ccltbl), cclcmp );
731*7e382390SJung-uk Kim 
732*7e382390SJung-uk Kim 			if ( useecs )
733*7e382390SJung-uk Kim 				mkeccl( ccltbl + cclmap[$1], ccllen[$1],
734*7e382390SJung-uk Kim 					nextecm, ecgroup, csize, csize );
735*7e382390SJung-uk Kim 
736*7e382390SJung-uk Kim 			++rulelen;
737*7e382390SJung-uk Kim 
738*7e382390SJung-uk Kim 			if (ccl_has_nl[$1])
739*7e382390SJung-uk Kim 				rule_has_nl[num_rules] = true;
740*7e382390SJung-uk Kim 
741*7e382390SJung-uk Kim 			$$ = mkstate( -$1 );
742*7e382390SJung-uk Kim 			}
743*7e382390SJung-uk Kim 
744*7e382390SJung-uk Kim 		|  PREVCCL
745*7e382390SJung-uk Kim 			{
746*7e382390SJung-uk Kim 			++rulelen;
747*7e382390SJung-uk Kim 
748*7e382390SJung-uk Kim 			if (ccl_has_nl[$1])
749*7e382390SJung-uk Kim 				rule_has_nl[num_rules] = true;
750*7e382390SJung-uk Kim 
751*7e382390SJung-uk Kim 			$$ = mkstate( -$1 );
752*7e382390SJung-uk Kim 			}
753*7e382390SJung-uk Kim 
754*7e382390SJung-uk Kim 		|  '"' string '"'
755*7e382390SJung-uk Kim 			{ $$ = $2; }
756*7e382390SJung-uk Kim 
757*7e382390SJung-uk Kim 		|  '(' re ')'
758*7e382390SJung-uk Kim 			{ $$ = $2; }
759*7e382390SJung-uk Kim 
760*7e382390SJung-uk Kim 		|  CHAR
761*7e382390SJung-uk Kim 			{
762*7e382390SJung-uk Kim 			++rulelen;
763*7e382390SJung-uk Kim 
764*7e382390SJung-uk Kim 			if ($1 == nlch)
765*7e382390SJung-uk Kim 				rule_has_nl[num_rules] = true;
766*7e382390SJung-uk Kim 
767*7e382390SJung-uk Kim             if (sf_case_ins() && has_case($1))
768*7e382390SJung-uk Kim                 /* create an alternation, as in (a|A) */
769*7e382390SJung-uk Kim                 $$ = mkor (mkstate($1), mkstate(reverse_case($1)));
770*7e382390SJung-uk Kim             else
771*7e382390SJung-uk Kim                 $$ = mkstate( $1 );
772*7e382390SJung-uk Kim 			}
773*7e382390SJung-uk Kim 		;
774*7e382390SJung-uk Kim fullccl:
775*7e382390SJung-uk Kim         fullccl CCL_OP_DIFF  braceccl  { $$ = ccl_set_diff  ($1, $3); }
776*7e382390SJung-uk Kim     |   fullccl CCL_OP_UNION braceccl  { $$ = ccl_set_union ($1, $3); }
777*7e382390SJung-uk Kim     |   braceccl
778*7e382390SJung-uk Kim     ;
779*7e382390SJung-uk Kim 
780*7e382390SJung-uk Kim braceccl:
781*7e382390SJung-uk Kim 
782*7e382390SJung-uk Kim             '[' ccl ']' { $$ = $2; }
783*7e382390SJung-uk Kim 
784*7e382390SJung-uk Kim 		|  '[' '^' ccl ']'
785*7e382390SJung-uk Kim 			{
786*7e382390SJung-uk Kim 			cclnegate( $3 );
787*7e382390SJung-uk Kim 			$$ = $3;
788*7e382390SJung-uk Kim 			}
789*7e382390SJung-uk Kim 		;
790*7e382390SJung-uk Kim 
791*7e382390SJung-uk Kim ccl		:  ccl CHAR '-' CHAR
792*7e382390SJung-uk Kim 			{
793*7e382390SJung-uk Kim 
794*7e382390SJung-uk Kim 			if (sf_case_ins())
795*7e382390SJung-uk Kim 			  {
796*7e382390SJung-uk Kim 
797*7e382390SJung-uk Kim 			    /* If one end of the range has case and the other
798*7e382390SJung-uk Kim 			     * does not, or the cases are different, then we're not
799*7e382390SJung-uk Kim 			     * sure what range the user is trying to express.
800*7e382390SJung-uk Kim 			     * Examples: [@-z] or [S-t]
801*7e382390SJung-uk Kim 			     */
802*7e382390SJung-uk Kim 			    if (has_case ($2) != has_case ($4)
803*7e382390SJung-uk Kim 				     || (has_case ($2) && (b_islower ($2) != b_islower ($4)))
804*7e382390SJung-uk Kim 				     || (has_case ($2) && (b_isupper ($2) != b_isupper ($4))))
805*7e382390SJung-uk Kim 			      format_warn3 (
806*7e382390SJung-uk Kim 			      _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"),
807*7e382390SJung-uk Kim 					    $2, $4);
808*7e382390SJung-uk Kim 
809*7e382390SJung-uk Kim 			    /* If the range spans uppercase characters but not
810*7e382390SJung-uk Kim 			     * lowercase (or vice-versa), then should we automatically
811*7e382390SJung-uk Kim 			     * include lowercase characters in the range?
812*7e382390SJung-uk Kim 			     * Example: [@-_] spans [a-z] but not [A-Z]
813*7e382390SJung-uk Kim 			     */
814*7e382390SJung-uk Kim 			    else if (!has_case ($2) && !has_case ($4) && !range_covers_case ($2, $4))
815*7e382390SJung-uk Kim 			      format_warn3 (
816*7e382390SJung-uk Kim 			      _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"),
817*7e382390SJung-uk Kim 					    $2, $4);
818*7e382390SJung-uk Kim 			  }
819*7e382390SJung-uk Kim 
820*7e382390SJung-uk Kim 			if ( $2 > $4 )
821*7e382390SJung-uk Kim 				synerr( _("negative range in character class") );
822*7e382390SJung-uk Kim 
823*7e382390SJung-uk Kim 			else
824*7e382390SJung-uk Kim 				{
825*7e382390SJung-uk Kim 				for ( i = $2; i <= $4; ++i )
826*7e382390SJung-uk Kim 					ccladd( $1, i );
827*7e382390SJung-uk Kim 
828*7e382390SJung-uk Kim 				/* Keep track if this ccl is staying in
829*7e382390SJung-uk Kim 				 * alphabetical order.
830*7e382390SJung-uk Kim 				 */
831*7e382390SJung-uk Kim 				cclsorted = cclsorted && ($2 > lastchar);
832*7e382390SJung-uk Kim 				lastchar = $4;
833*7e382390SJung-uk Kim 
834*7e382390SJung-uk Kim                 /* Do it again for upper/lowercase */
835*7e382390SJung-uk Kim                 if (sf_case_ins() && has_case($2) && has_case($4)){
836*7e382390SJung-uk Kim                     $2 = reverse_case ($2);
837*7e382390SJung-uk Kim                     $4 = reverse_case ($4);
838*7e382390SJung-uk Kim 
839*7e382390SJung-uk Kim                     for ( i = $2; i <= $4; ++i )
840*7e382390SJung-uk Kim                         ccladd( $1, i );
841*7e382390SJung-uk Kim 
842*7e382390SJung-uk Kim                     cclsorted = cclsorted && ($2 > lastchar);
843*7e382390SJung-uk Kim                     lastchar = $4;
844*7e382390SJung-uk Kim                 }
845*7e382390SJung-uk Kim 
846*7e382390SJung-uk Kim 				}
847*7e382390SJung-uk Kim 
848*7e382390SJung-uk Kim 			$$ = $1;
849*7e382390SJung-uk Kim 			}
850*7e382390SJung-uk Kim 
851*7e382390SJung-uk Kim 		|  ccl CHAR
852*7e382390SJung-uk Kim 			{
853*7e382390SJung-uk Kim 			ccladd( $1, $2 );
854*7e382390SJung-uk Kim 			cclsorted = cclsorted && ($2 > lastchar);
855*7e382390SJung-uk Kim 			lastchar = $2;
856*7e382390SJung-uk Kim 
857*7e382390SJung-uk Kim             /* Do it again for upper/lowercase */
858*7e382390SJung-uk Kim             if (sf_case_ins() && has_case($2)){
859*7e382390SJung-uk Kim                 $2 = reverse_case ($2);
860*7e382390SJung-uk Kim                 ccladd ($1, $2);
861*7e382390SJung-uk Kim 
862*7e382390SJung-uk Kim                 cclsorted = cclsorted && ($2 > lastchar);
863*7e382390SJung-uk Kim                 lastchar = $2;
864*7e382390SJung-uk Kim             }
865*7e382390SJung-uk Kim 
866*7e382390SJung-uk Kim 			$$ = $1;
867*7e382390SJung-uk Kim 			}
868*7e382390SJung-uk Kim 
869*7e382390SJung-uk Kim 		|  ccl ccl_expr
870*7e382390SJung-uk Kim 			{
871*7e382390SJung-uk Kim 			/* Too hard to properly maintain cclsorted. */
872*7e382390SJung-uk Kim 			cclsorted = false;
873*7e382390SJung-uk Kim 			$$ = $1;
874*7e382390SJung-uk Kim 			}
875*7e382390SJung-uk Kim 
876*7e382390SJung-uk Kim 		|
877*7e382390SJung-uk Kim 			{
878*7e382390SJung-uk Kim 			cclsorted = true;
879*7e382390SJung-uk Kim 			lastchar = 0;
880*7e382390SJung-uk Kim 			currccl = $$ = cclinit();
881*7e382390SJung-uk Kim 			}
882*7e382390SJung-uk Kim 		;
883*7e382390SJung-uk Kim 
884*7e382390SJung-uk Kim ccl_expr:
885*7e382390SJung-uk Kim            CCE_ALNUM	{ CCL_EXPR(isalnum); }
886*7e382390SJung-uk Kim 		|  CCE_ALPHA	{ CCL_EXPR(isalpha); }
887*7e382390SJung-uk Kim 		|  CCE_BLANK	{ CCL_EXPR(IS_BLANK); }
888*7e382390SJung-uk Kim 		|  CCE_CNTRL	{ CCL_EXPR(iscntrl); }
889*7e382390SJung-uk Kim 		|  CCE_DIGIT	{ CCL_EXPR(isdigit); }
890*7e382390SJung-uk Kim 		|  CCE_GRAPH	{ CCL_EXPR(isgraph); }
891*7e382390SJung-uk Kim 		|  CCE_LOWER	{
892*7e382390SJung-uk Kim                           CCL_EXPR(islower);
893*7e382390SJung-uk Kim                           if (sf_case_ins())
894*7e382390SJung-uk Kim                               CCL_EXPR(isupper);
895*7e382390SJung-uk Kim                         }
896*7e382390SJung-uk Kim 		|  CCE_PRINT	{ CCL_EXPR(isprint); }
897*7e382390SJung-uk Kim 		|  CCE_PUNCT	{ CCL_EXPR(ispunct); }
898*7e382390SJung-uk Kim 		|  CCE_SPACE	{ CCL_EXPR(isspace); }
899*7e382390SJung-uk Kim 		|  CCE_XDIGIT	{ CCL_EXPR(isxdigit); }
900*7e382390SJung-uk Kim 		|  CCE_UPPER	{
901*7e382390SJung-uk Kim                     CCL_EXPR(isupper);
902*7e382390SJung-uk Kim                     if (sf_case_ins())
903*7e382390SJung-uk Kim                         CCL_EXPR(islower);
904*7e382390SJung-uk Kim 				}
905*7e382390SJung-uk Kim 
906*7e382390SJung-uk Kim         |  CCE_NEG_ALNUM	{ CCL_NEG_EXPR(isalnum); }
907*7e382390SJung-uk Kim 		|  CCE_NEG_ALPHA	{ CCL_NEG_EXPR(isalpha); }
908*7e382390SJung-uk Kim 		|  CCE_NEG_BLANK	{ CCL_NEG_EXPR(IS_BLANK); }
909*7e382390SJung-uk Kim 		|  CCE_NEG_CNTRL	{ CCL_NEG_EXPR(iscntrl); }
910*7e382390SJung-uk Kim 		|  CCE_NEG_DIGIT	{ CCL_NEG_EXPR(isdigit); }
911*7e382390SJung-uk Kim 		|  CCE_NEG_GRAPH	{ CCL_NEG_EXPR(isgraph); }
912*7e382390SJung-uk Kim 		|  CCE_NEG_PRINT	{ CCL_NEG_EXPR(isprint); }
913*7e382390SJung-uk Kim 		|  CCE_NEG_PUNCT	{ CCL_NEG_EXPR(ispunct); }
914*7e382390SJung-uk Kim 		|  CCE_NEG_SPACE	{ CCL_NEG_EXPR(isspace); }
915*7e382390SJung-uk Kim 		|  CCE_NEG_XDIGIT	{ CCL_NEG_EXPR(isxdigit); }
916*7e382390SJung-uk Kim 		|  CCE_NEG_LOWER	{
917*7e382390SJung-uk Kim 				if ( sf_case_ins() )
918*7e382390SJung-uk Kim 					lwarn(_("[:^lower:] is ambiguous in case insensitive scanner"));
919*7e382390SJung-uk Kim 				else
920*7e382390SJung-uk Kim 					CCL_NEG_EXPR(islower);
921*7e382390SJung-uk Kim 				}
922*7e382390SJung-uk Kim 		|  CCE_NEG_UPPER	{
923*7e382390SJung-uk Kim 				if ( sf_case_ins() )
924*7e382390SJung-uk Kim 					lwarn(_("[:^upper:] ambiguous in case insensitive scanner"));
925*7e382390SJung-uk Kim 				else
926*7e382390SJung-uk Kim 					CCL_NEG_EXPR(isupper);
927*7e382390SJung-uk Kim 				}
928*7e382390SJung-uk Kim 		;
929*7e382390SJung-uk Kim 
930*7e382390SJung-uk Kim string		:  string CHAR
931*7e382390SJung-uk Kim 			{
932*7e382390SJung-uk Kim 			if ( $2 == nlch )
933*7e382390SJung-uk Kim 				rule_has_nl[num_rules] = true;
934*7e382390SJung-uk Kim 
935*7e382390SJung-uk Kim 			++rulelen;
936*7e382390SJung-uk Kim 
937*7e382390SJung-uk Kim             if (sf_case_ins() && has_case($2))
938*7e382390SJung-uk Kim                 $$ = mkor (mkstate($2), mkstate(reverse_case($2)));
939*7e382390SJung-uk Kim             else
940*7e382390SJung-uk Kim                 $$ = mkstate ($2);
941*7e382390SJung-uk Kim 
942*7e382390SJung-uk Kim 			$$ = link_machines( $1, $$);
943*7e382390SJung-uk Kim 			}
944*7e382390SJung-uk Kim 
945*7e382390SJung-uk Kim 		|
946*7e382390SJung-uk Kim 			{ $$ = mkstate( SYM_EPSILON ); }
947*7e382390SJung-uk Kim 		;
948*7e382390SJung-uk Kim 
949*7e382390SJung-uk Kim %%
950*7e382390SJung-uk Kim 
951*7e382390SJung-uk Kim 
952*7e382390SJung-uk Kim /* build_eof_action - build the "<<EOF>>" action for the active start
953*7e382390SJung-uk Kim  *                    conditions
954*7e382390SJung-uk Kim  */
955*7e382390SJung-uk Kim 
956*7e382390SJung-uk Kim void build_eof_action(void)
957*7e382390SJung-uk Kim 	{
958*7e382390SJung-uk Kim 	int i;
959*7e382390SJung-uk Kim 	char action_text[MAXLINE];
960*7e382390SJung-uk Kim 
961*7e382390SJung-uk Kim 	for ( i = 1; i <= scon_stk_ptr; ++i )
962*7e382390SJung-uk Kim 		{
963*7e382390SJung-uk Kim 		if ( sceof[scon_stk[i]] )
964*7e382390SJung-uk Kim 			format_pinpoint_message(
965*7e382390SJung-uk Kim 				"multiple <<EOF>> rules for start condition %s",
966*7e382390SJung-uk Kim 				scname[scon_stk[i]] );
967*7e382390SJung-uk Kim 
968*7e382390SJung-uk Kim 		else
969*7e382390SJung-uk Kim 			{
970*7e382390SJung-uk Kim 			sceof[scon_stk[i]] = true;
971*7e382390SJung-uk Kim 
972*7e382390SJung-uk Kim 			if (previous_continued_action /* && previous action was regular */)
973*7e382390SJung-uk Kim 				add_action("YY_RULE_SETUP\n");
974*7e382390SJung-uk Kim 
975*7e382390SJung-uk Kim 			snprintf( action_text, sizeof(action_text), "case YY_STATE_EOF(%s):\n",
976*7e382390SJung-uk Kim 				scname[scon_stk[i]] );
977*7e382390SJung-uk Kim 			add_action( action_text );
978*7e382390SJung-uk Kim 			}
979*7e382390SJung-uk Kim 		}
980*7e382390SJung-uk Kim 
981*7e382390SJung-uk Kim 	line_directive_out(NULL, 1);
982*7e382390SJung-uk Kim         add_action("[[");
983*7e382390SJung-uk Kim 
984*7e382390SJung-uk Kim 	/* This isn't a normal rule after all - don't count it as
985*7e382390SJung-uk Kim 	 * such, so we don't have any holes in the rule numbering
986*7e382390SJung-uk Kim 	 * (which make generating "rule can never match" warnings
987*7e382390SJung-uk Kim 	 * more difficult.
988*7e382390SJung-uk Kim 	 */
989*7e382390SJung-uk Kim 	--num_rules;
990*7e382390SJung-uk Kim 	++num_eof_rules;
991*7e382390SJung-uk Kim 	}
992*7e382390SJung-uk Kim 
993*7e382390SJung-uk Kim 
994*7e382390SJung-uk Kim /* format_synerr - write out formatted syntax error */
995*7e382390SJung-uk Kim 
format_synerr(const char * msg,const char arg[])996*7e382390SJung-uk Kim void format_synerr( const char *msg, const char arg[] )
997*7e382390SJung-uk Kim 	{
998*7e382390SJung-uk Kim 	char errmsg[MAXLINE];
999*7e382390SJung-uk Kim 
1000*7e382390SJung-uk Kim 	(void) snprintf( errmsg, sizeof(errmsg), msg, arg );
1001*7e382390SJung-uk Kim 	synerr( errmsg );
1002*7e382390SJung-uk Kim 	}
1003*7e382390SJung-uk Kim 
1004*7e382390SJung-uk Kim 
1005*7e382390SJung-uk Kim /* synerr - report a syntax error */
1006*7e382390SJung-uk Kim 
synerr(const char * str)1007*7e382390SJung-uk Kim void synerr( const char *str )
1008*7e382390SJung-uk Kim 	{
1009*7e382390SJung-uk Kim 	syntaxerror = true;
1010*7e382390SJung-uk Kim 	pinpoint_message( str );
1011*7e382390SJung-uk Kim 	}
1012*7e382390SJung-uk Kim 
1013*7e382390SJung-uk Kim 
1014*7e382390SJung-uk Kim /* format_warn - write out formatted warning */
1015*7e382390SJung-uk Kim 
format_warn(const char * msg,const char arg[])1016*7e382390SJung-uk Kim void format_warn( const char *msg, const char arg[] )
1017*7e382390SJung-uk Kim 	{
1018*7e382390SJung-uk Kim 	char warn_msg[MAXLINE];
1019*7e382390SJung-uk Kim 
1020*7e382390SJung-uk Kim 	snprintf( warn_msg, sizeof(warn_msg), msg, arg );
1021*7e382390SJung-uk Kim 	lwarn( warn_msg );
1022*7e382390SJung-uk Kim 	}
1023*7e382390SJung-uk Kim 
1024*7e382390SJung-uk Kim 
1025*7e382390SJung-uk Kim /* lwarn - report a warning, unless -w was given */
1026*7e382390SJung-uk Kim 
lwarn(const char * str)1027*7e382390SJung-uk Kim void lwarn( const char *str )
1028*7e382390SJung-uk Kim 	{
1029*7e382390SJung-uk Kim 	line_warning( str, linenum );
1030*7e382390SJung-uk Kim 	}
1031*7e382390SJung-uk Kim 
1032*7e382390SJung-uk Kim /* format_pinpoint_message - write out a message formatted with one string,
1033*7e382390SJung-uk Kim  *			     pinpointing its location
1034*7e382390SJung-uk Kim  */
1035*7e382390SJung-uk Kim 
format_pinpoint_message(const char * msg,const char arg[])1036*7e382390SJung-uk Kim void format_pinpoint_message( const char *msg, const char arg[] )
1037*7e382390SJung-uk Kim 	{
1038*7e382390SJung-uk Kim 	char errmsg[MAXLINE];
1039*7e382390SJung-uk Kim 
1040*7e382390SJung-uk Kim 	snprintf( errmsg, sizeof(errmsg), msg, arg );
1041*7e382390SJung-uk Kim 	pinpoint_message( errmsg );
1042*7e382390SJung-uk Kim 	}
1043*7e382390SJung-uk Kim 
1044*7e382390SJung-uk Kim 
1045*7e382390SJung-uk Kim /* pinpoint_message - write out a message, pinpointing its location */
1046*7e382390SJung-uk Kim 
pinpoint_message(const char * str)1047*7e382390SJung-uk Kim void pinpoint_message( const char *str )
1048*7e382390SJung-uk Kim 	{
1049*7e382390SJung-uk Kim 	line_pinpoint( str, linenum );
1050*7e382390SJung-uk Kim 	}
1051*7e382390SJung-uk Kim 
1052*7e382390SJung-uk Kim 
1053*7e382390SJung-uk Kim /* line_warning - report a warning at a given line, unless -w was given */
1054*7e382390SJung-uk Kim 
line_warning(const char * str,int line)1055*7e382390SJung-uk Kim void line_warning( const char *str, int line )
1056*7e382390SJung-uk Kim 	{
1057*7e382390SJung-uk Kim 	char warning[MAXLINE];
1058*7e382390SJung-uk Kim 
1059*7e382390SJung-uk Kim 	if ( ! nowarn )
1060*7e382390SJung-uk Kim 		{
1061*7e382390SJung-uk Kim 		snprintf( warning, sizeof(warning), "warning, %s", str );
1062*7e382390SJung-uk Kim 		line_pinpoint( warning, line );
1063*7e382390SJung-uk Kim 		}
1064*7e382390SJung-uk Kim 	}
1065*7e382390SJung-uk Kim 
1066*7e382390SJung-uk Kim 
1067*7e382390SJung-uk Kim /* line_pinpoint - write out a message, pinpointing it at the given line */
1068*7e382390SJung-uk Kim 
line_pinpoint(const char * str,int line)1069*7e382390SJung-uk Kim void line_pinpoint( const char *str, int line )
1070*7e382390SJung-uk Kim 	{
1071*7e382390SJung-uk Kim 	fprintf( stderr, "%s:%d: %s\n", infilename, line, str );
1072*7e382390SJung-uk Kim 	}
1073*7e382390SJung-uk Kim 
1074*7e382390SJung-uk Kim 
1075*7e382390SJung-uk Kim /* yyerror - eat up an error message from the parser;
1076*7e382390SJung-uk Kim  *	     currently, messages are ignore
1077*7e382390SJung-uk Kim  */
1078*7e382390SJung-uk Kim 
yyerror(const char * msg)1079*7e382390SJung-uk Kim void yyerror( const char *msg )
1080*7e382390SJung-uk Kim 	{
1081*7e382390SJung-uk Kim 		(void)msg;
1082*7e382390SJung-uk Kim 	}
1083