xref: /titanic_51/usr/src/cmd/awk_xpg4/awk.y (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate %{
2*7c478bd9Sstevel@tonic-gate /*
3*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
6*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
7*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
8*7c478bd9Sstevel@tonic-gate  * with the License.
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
12*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
13*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
16*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
18*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
19*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
20*7c478bd9Sstevel@tonic-gate  *
21*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
22*7c478bd9Sstevel@tonic-gate  */
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * awk -- YACC grammar
25*7c478bd9Sstevel@tonic-gate  *
26*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1995 by Sun Microsystems, Inc.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * Copyright 1986, 1992 by Mortice Kern Systems Inc.  All rights reserved.
29*7c478bd9Sstevel@tonic-gate  *
30*7c478bd9Sstevel@tonic-gate  * This Software is unpublished, valuable, confidential property of
31*7c478bd9Sstevel@tonic-gate  * Mortice Kern Systems Inc.  Use is authorized only in accordance
32*7c478bd9Sstevel@tonic-gate  * with the terms and conditions of the source licence agreement
33*7c478bd9Sstevel@tonic-gate  * protecting this Software.  Any unauthorized use or disclosure of
34*7c478bd9Sstevel@tonic-gate  * this Software is strictly prohibited and will result in the
35*7c478bd9Sstevel@tonic-gate  * termination of the licence agreement.
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * NOTE: this grammar correctly produces NO shift/reduce conflicts from YACC.
38*7c478bd9Sstevel@tonic-gate  *
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate  * Do not use any character constants as tokens, so the resulting C file
43*7c478bd9Sstevel@tonic-gate  * is codeset independent.
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"
47*7c478bd9Sstevel@tonic-gate #include "awk.h"
48*7c478bd9Sstevel@tonic-gate static NODE * fliplist ANSI((NODE *np));
49*7c478bd9Sstevel@tonic-gate %}
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate %union	{
52*7c478bd9Sstevel@tonic-gate 	NODE	*node;
53*7c478bd9Sstevel@tonic-gate };
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate  * Do not use any character constants as tokens, so the resulting C file
57*7c478bd9Sstevel@tonic-gate  * is codeset independent.
58*7c478bd9Sstevel@tonic-gate  *
59*7c478bd9Sstevel@tonic-gate  * Declare terminal symbols before their operator
60*7c478bd9Sstevel@tonic-gate  * precedences to get them in a contiguous block
61*7c478bd9Sstevel@tonic-gate  * for giant switches in action() and exprreduce().
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate /* Tokens from exprreduce() */
64*7c478bd9Sstevel@tonic-gate %token	<node>	PARM ARRAY UFUNC FIELD IN INDEX CONCAT
65*7c478bd9Sstevel@tonic-gate %token	<node>	NOT AND OR EXP QUEST
66*7c478bd9Sstevel@tonic-gate %token	<node>	EQ NE GE LE GT LT
67*7c478bd9Sstevel@tonic-gate %token	<node>	ADD SUB MUL DIV REM INC DEC PRE_INC PRE_DEC
68*7c478bd9Sstevel@tonic-gate %token	<node>	GETLINE CALLFUNC RE TILDE NRE
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /* Tokens shared by exprreduce() and action() */
71*7c478bd9Sstevel@tonic-gate %token		ASG
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate /* Tokens from action() */
74*7c478bd9Sstevel@tonic-gate %token	<node>	PRINT PRINTF
75*7c478bd9Sstevel@tonic-gate %token	<node>	EXIT RETURN BREAK CONTINUE NEXT
76*7c478bd9Sstevel@tonic-gate %token	<node>	DELETE WHILE DO FOR FORIN IF
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  * Terminal symbols not used in action() and exprrreduce()
80*7c478bd9Sstevel@tonic-gate  * switch statements.
81*7c478bd9Sstevel@tonic-gate  */
82*7c478bd9Sstevel@tonic-gate %token	<node>	CONSTANT VAR FUNC
83*7c478bd9Sstevel@tonic-gate %token	<node>	DEFFUNC BEGIN END CLOSE ELSE PACT
84*7c478bd9Sstevel@tonic-gate %right		ELSE
85*7c478bd9Sstevel@tonic-gate %token		DOT CALLUFUNC
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate /*
88*7c478bd9Sstevel@tonic-gate  * Tokens not used in grammar
89*7c478bd9Sstevel@tonic-gate  */
90*7c478bd9Sstevel@tonic-gate %token		KEYWORD SVAR
91*7c478bd9Sstevel@tonic-gate %token		PIPESYM
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate  * Tokens representing character constants
95*7c478bd9Sstevel@tonic-gate  * TILDE, '~', taken care of above
96*7c478bd9Sstevel@tonic-gate  */
97*7c478bd9Sstevel@tonic-gate %token BAR		/* '|' */
98*7c478bd9Sstevel@tonic-gate        CARAT		/* '^' */
99*7c478bd9Sstevel@tonic-gate        LANGLE		/* '<' */
100*7c478bd9Sstevel@tonic-gate        RANGLE		/* '>' */
101*7c478bd9Sstevel@tonic-gate        PLUSC		/* '+' */
102*7c478bd9Sstevel@tonic-gate        HYPHEN		/* '-' */
103*7c478bd9Sstevel@tonic-gate        STAR		/* '*' */
104*7c478bd9Sstevel@tonic-gate        SLASH		/* '/' */
105*7c478bd9Sstevel@tonic-gate        PERCENT		/* '%' */
106*7c478bd9Sstevel@tonic-gate        EXCLAMATION	/* '!' */
107*7c478bd9Sstevel@tonic-gate        DOLLAR		/* '$' */
108*7c478bd9Sstevel@tonic-gate        LSQUARE		/* '[' */
109*7c478bd9Sstevel@tonic-gate        RSQUARE		/* ']' */
110*7c478bd9Sstevel@tonic-gate        LPAREN		/* '(' */
111*7c478bd9Sstevel@tonic-gate        RPAREN		/* ')' */
112*7c478bd9Sstevel@tonic-gate        SEMI		/* ';' */
113*7c478bd9Sstevel@tonic-gate        LBRACE		/* '{' */
114*7c478bd9Sstevel@tonic-gate        RBRACE		/* '}' */
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate /*
117*7c478bd9Sstevel@tonic-gate  * Priorities of operators
118*7c478bd9Sstevel@tonic-gate  * Lowest to highest
119*7c478bd9Sstevel@tonic-gate  */
120*7c478bd9Sstevel@tonic-gate %left	COMMA
121*7c478bd9Sstevel@tonic-gate %right	BAR PIPE WRITE APPEND
122*7c478bd9Sstevel@tonic-gate %right	ASG AADD ASUB AMUL ADIV AREM AEXP
123*7c478bd9Sstevel@tonic-gate %right	QUEST COLON
124*7c478bd9Sstevel@tonic-gate %left	OR
125*7c478bd9Sstevel@tonic-gate %left	AND
126*7c478bd9Sstevel@tonic-gate %left	IN
127*7c478bd9Sstevel@tonic-gate %left	CARAT
128*7c478bd9Sstevel@tonic-gate %left	TILDE NRE
129*7c478bd9Sstevel@tonic-gate %left	EQ NE LANGLE RANGLE GE LE
130*7c478bd9Sstevel@tonic-gate %left	CONCAT
131*7c478bd9Sstevel@tonic-gate %left	PLUSC HYPHEN
132*7c478bd9Sstevel@tonic-gate %left	STAR SLASH PERCENT
133*7c478bd9Sstevel@tonic-gate %right	UPLUS UMINUS
134*7c478bd9Sstevel@tonic-gate %right	EXCLAMATION
135*7c478bd9Sstevel@tonic-gate %right	EXP
136*7c478bd9Sstevel@tonic-gate %right	INC DEC URE
137*7c478bd9Sstevel@tonic-gate %left	DOLLAR LSQUARE RSQUARE
138*7c478bd9Sstevel@tonic-gate %left	LPAREN RPAREN
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate %type	<node>	prog rule pattern expr rvalue lvalue fexpr varlist varlist2
141*7c478bd9Sstevel@tonic-gate %type	<node>	statement statlist fileout exprlist eexprlist simplepattern
142*7c478bd9Sstevel@tonic-gate %type	<node>	getline optvar var
143*7c478bd9Sstevel@tonic-gate %type	<node>	dummy
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate %start	dummy
146*7c478bd9Sstevel@tonic-gate %%
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate dummy:
149*7c478bd9Sstevel@tonic-gate 		prog			= {
150*7c478bd9Sstevel@tonic-gate 			yytree = fliplist(yytree);
151*7c478bd9Sstevel@tonic-gate 		}
152*7c478bd9Sstevel@tonic-gate 		;
153*7c478bd9Sstevel@tonic-gate prog:
154*7c478bd9Sstevel@tonic-gate 	  rule				= {
155*7c478bd9Sstevel@tonic-gate 		yytree = $1;
156*7c478bd9Sstevel@tonic-gate 	}
157*7c478bd9Sstevel@tonic-gate 	| rule SEMI prog		= {
158*7c478bd9Sstevel@tonic-gate 		if ($1 != NNULL) {
159*7c478bd9Sstevel@tonic-gate 			if (yytree != NNULL)
160*7c478bd9Sstevel@tonic-gate 				yytree = node(COMMA, $1, yytree); else
161*7c478bd9Sstevel@tonic-gate 				yytree = $1;
162*7c478bd9Sstevel@tonic-gate 		}
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 	;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate rule:	  pattern LBRACE statlist RBRACE	= {
167*7c478bd9Sstevel@tonic-gate 		$$ = node(PACT, $1, $3);
168*7c478bd9Sstevel@tonic-gate 		doing_begin = 0;
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 	| LBRACE statlist RBRACE		= {
171*7c478bd9Sstevel@tonic-gate 		npattern++;
172*7c478bd9Sstevel@tonic-gate 		$$ = node(PACT, NNULL, $2);
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	| pattern				= {
175*7c478bd9Sstevel@tonic-gate 		$$ = node(PACT, $1, node(PRINT, NNULL, NNULL));
176*7c478bd9Sstevel@tonic-gate 		doing_begin = 0;
177*7c478bd9Sstevel@tonic-gate 	}
178*7c478bd9Sstevel@tonic-gate 	| DEFFUNC VAR
179*7c478bd9Sstevel@tonic-gate 		{ $2->n_type = UFUNC; funparm = 1; }
180*7c478bd9Sstevel@tonic-gate 	    LPAREN varlist RPAREN
181*7c478bd9Sstevel@tonic-gate 		{ funparm = 0; }
182*7c478bd9Sstevel@tonic-gate 	    LBRACE statlist { uexit($5); } RBRACE = {
183*7c478bd9Sstevel@tonic-gate 		$2->n_ufunc = node(DEFFUNC, $5, fliplist($9));
184*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 	| DEFFUNC UFUNC				= {
187*7c478bd9Sstevel@tonic-gate 		awkerr((char *) gettext("function \"%S\" redefined"), $2->n_name);
188*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
189*7c478bd9Sstevel@tonic-gate 	}
190*7c478bd9Sstevel@tonic-gate 	|					= {
191*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
192*7c478bd9Sstevel@tonic-gate 	}
193*7c478bd9Sstevel@tonic-gate 	;
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate pattern:
196*7c478bd9Sstevel@tonic-gate 	  simplepattern
197*7c478bd9Sstevel@tonic-gate 	| expr COMMA expr			= {
198*7c478bd9Sstevel@tonic-gate 		++npattern;
199*7c478bd9Sstevel@tonic-gate 		$$ = node(COMMA, $1, $3);
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate simplepattern:
204*7c478bd9Sstevel@tonic-gate 	  BEGIN					= {
205*7c478bd9Sstevel@tonic-gate 		$$ = node(BEGIN, NNULL, NNULL);
206*7c478bd9Sstevel@tonic-gate 		doing_begin++;
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate 	| END					= {
209*7c478bd9Sstevel@tonic-gate 		++npattern;
210*7c478bd9Sstevel@tonic-gate 		$$ = node(END, NNULL, NNULL);
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 	| expr					 = {
213*7c478bd9Sstevel@tonic-gate 		++npattern;
214*7c478bd9Sstevel@tonic-gate 		$$ = $1;
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 	;
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate eexprlist:
219*7c478bd9Sstevel@tonic-gate 	  exprlist
220*7c478bd9Sstevel@tonic-gate 	|					= {
221*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
222*7c478bd9Sstevel@tonic-gate 	}
223*7c478bd9Sstevel@tonic-gate 	;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate exprlist:
226*7c478bd9Sstevel@tonic-gate 	  expr %prec COMMA
227*7c478bd9Sstevel@tonic-gate 	| exprlist COMMA expr			= {
228*7c478bd9Sstevel@tonic-gate 		$$ = node(COMMA, $1, $3);
229*7c478bd9Sstevel@tonic-gate 	}
230*7c478bd9Sstevel@tonic-gate 	;
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate varlist:
233*7c478bd9Sstevel@tonic-gate 	  					= {
234*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 	| varlist2
237*7c478bd9Sstevel@tonic-gate 	;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate varlist2:
240*7c478bd9Sstevel@tonic-gate 	  var
241*7c478bd9Sstevel@tonic-gate 	| var COMMA varlist2			= {
242*7c478bd9Sstevel@tonic-gate 		$$ = node(COMMA, $1, $3);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 	;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate fexpr:
247*7c478bd9Sstevel@tonic-gate 	  expr
248*7c478bd9Sstevel@tonic-gate 	|					= {
249*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate 	;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate /*
254*7c478bd9Sstevel@tonic-gate  * Normal expression (includes regular expression)
255*7c478bd9Sstevel@tonic-gate  */
256*7c478bd9Sstevel@tonic-gate expr:
257*7c478bd9Sstevel@tonic-gate 	  expr PLUSC expr			= {
258*7c478bd9Sstevel@tonic-gate 		$$ = node(ADD, $1, $3);
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate 	| expr HYPHEN expr			= {
261*7c478bd9Sstevel@tonic-gate 		$$ = node(SUB, $1, $3);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 	| expr STAR expr			= {
264*7c478bd9Sstevel@tonic-gate 		$$ = node(MUL, $1, $3);
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 	| expr SLASH expr			= {
267*7c478bd9Sstevel@tonic-gate 		$$ = node(DIV, $1, $3);
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	| expr PERCENT expr			= {
270*7c478bd9Sstevel@tonic-gate 		$$ = node(REM, $1, $3);
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate 	| expr EXP expr				= {
273*7c478bd9Sstevel@tonic-gate 		$$ = node(EXP, $1, $3);
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 	| expr AND expr				= {
276*7c478bd9Sstevel@tonic-gate 		$$ = node(AND, $1, $3);
277*7c478bd9Sstevel@tonic-gate 	}
278*7c478bd9Sstevel@tonic-gate 	| expr OR expr				= {
279*7c478bd9Sstevel@tonic-gate 		$$ = node(OR, $1, $3);
280*7c478bd9Sstevel@tonic-gate 	}
281*7c478bd9Sstevel@tonic-gate 	| expr QUEST expr COLON expr		= {
282*7c478bd9Sstevel@tonic-gate 		$$ = node(QUEST, $1, node(COLON, $3, $5));
283*7c478bd9Sstevel@tonic-gate 	}
284*7c478bd9Sstevel@tonic-gate 	| lvalue ASG expr			= {
285*7c478bd9Sstevel@tonic-gate 		$$ = node(ASG, $1, $3);
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 	| lvalue AADD expr			= {
288*7c478bd9Sstevel@tonic-gate 		$$ = node(AADD, $1, $3);
289*7c478bd9Sstevel@tonic-gate 	}
290*7c478bd9Sstevel@tonic-gate 	| lvalue ASUB expr			= {
291*7c478bd9Sstevel@tonic-gate 		$$ = node(ASUB, $1, $3);
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 	| lvalue AMUL expr			= {
294*7c478bd9Sstevel@tonic-gate 		$$ = node(AMUL, $1, $3);
295*7c478bd9Sstevel@tonic-gate 	}
296*7c478bd9Sstevel@tonic-gate 	| lvalue ADIV expr			= {
297*7c478bd9Sstevel@tonic-gate 		$$ = node(ADIV, $1, $3);
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 	| lvalue AREM expr			= {
300*7c478bd9Sstevel@tonic-gate 		$$ = node(AREM, $1, $3);
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 	| lvalue AEXP expr			= {
303*7c478bd9Sstevel@tonic-gate 		$$ = node(AEXP, $1, $3);
304*7c478bd9Sstevel@tonic-gate 	}
305*7c478bd9Sstevel@tonic-gate 	| lvalue INC				= {
306*7c478bd9Sstevel@tonic-gate 		$$ = node(INC, $1, NNULL);
307*7c478bd9Sstevel@tonic-gate 	}
308*7c478bd9Sstevel@tonic-gate 	| lvalue DEC				= {
309*7c478bd9Sstevel@tonic-gate 		$$ = node(DEC, $1, NNULL);
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 	| expr EQ expr				= {
312*7c478bd9Sstevel@tonic-gate 		$$ = node(EQ, $1, $3);
313*7c478bd9Sstevel@tonic-gate 	}
314*7c478bd9Sstevel@tonic-gate 	| expr NE expr				= {
315*7c478bd9Sstevel@tonic-gate 		$$ = node(NE, $1, $3);
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 	| expr RANGLE expr			= {
318*7c478bd9Sstevel@tonic-gate 		$$ = node(GT, $1, $3);
319*7c478bd9Sstevel@tonic-gate 	}
320*7c478bd9Sstevel@tonic-gate 	| expr LANGLE expr			= {
321*7c478bd9Sstevel@tonic-gate 		$$ = node(LT, $1, $3);
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 	| expr GE expr				= {
324*7c478bd9Sstevel@tonic-gate 		$$ = node(GE, $1, $3);
325*7c478bd9Sstevel@tonic-gate 	}
326*7c478bd9Sstevel@tonic-gate 	| expr LE expr				= {
327*7c478bd9Sstevel@tonic-gate 		$$ = node(LE, $1, $3);
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 	| expr TILDE expr			= {
330*7c478bd9Sstevel@tonic-gate 		$$ = node(TILDE, $1, $3);
331*7c478bd9Sstevel@tonic-gate 	}
332*7c478bd9Sstevel@tonic-gate 	| expr NRE expr				= {
333*7c478bd9Sstevel@tonic-gate 		$$ = node(NRE, $1, $3);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	| expr IN var				= {
336*7c478bd9Sstevel@tonic-gate 		$$ = node(IN, $3, $1);
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate 	| LPAREN exprlist RPAREN IN var		= {
339*7c478bd9Sstevel@tonic-gate 		$$ = node(IN, $5, $2);
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 	| getline
342*7c478bd9Sstevel@tonic-gate 	| rvalue
343*7c478bd9Sstevel@tonic-gate 	| expr CONCAT expr			= {
344*7c478bd9Sstevel@tonic-gate 		$$ = node(CONCAT, $1, $3);
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate 	;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate lvalue:
349*7c478bd9Sstevel@tonic-gate 	  DOLLAR rvalue				= {
350*7c478bd9Sstevel@tonic-gate 		$$ = node(FIELD, $2, NNULL);
351*7c478bd9Sstevel@tonic-gate 	}
352*7c478bd9Sstevel@tonic-gate 	/*
353*7c478bd9Sstevel@tonic-gate 	 * Prevents conflict with FOR LPAREN var IN var RPAREN production
354*7c478bd9Sstevel@tonic-gate 	 */
355*7c478bd9Sstevel@tonic-gate 	| var %prec COMMA
356*7c478bd9Sstevel@tonic-gate 	| var LSQUARE exprlist RSQUARE		= {
357*7c478bd9Sstevel@tonic-gate 		$$ = node(INDEX, $1, $3);
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 	;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate var:
362*7c478bd9Sstevel@tonic-gate 	  VAR
363*7c478bd9Sstevel@tonic-gate 	| PARM
364*7c478bd9Sstevel@tonic-gate 	;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate rvalue:
367*7c478bd9Sstevel@tonic-gate 	  lvalue %prec COMMA
368*7c478bd9Sstevel@tonic-gate 	| CONSTANT
369*7c478bd9Sstevel@tonic-gate 	| LPAREN expr RPAREN term		= {
370*7c478bd9Sstevel@tonic-gate 		$$ = $2;
371*7c478bd9Sstevel@tonic-gate 	}
372*7c478bd9Sstevel@tonic-gate 	| EXCLAMATION expr			= {
373*7c478bd9Sstevel@tonic-gate 		$$ = node(NOT, $2, NNULL);
374*7c478bd9Sstevel@tonic-gate 	}
375*7c478bd9Sstevel@tonic-gate 	| HYPHEN expr %prec UMINUS		= {
376*7c478bd9Sstevel@tonic-gate 		$$ = node(SUB, const0, $2);
377*7c478bd9Sstevel@tonic-gate 	}
378*7c478bd9Sstevel@tonic-gate 	| PLUSC expr %prec UPLUS		= {
379*7c478bd9Sstevel@tonic-gate 		$$ = $2;
380*7c478bd9Sstevel@tonic-gate 	}
381*7c478bd9Sstevel@tonic-gate 	| DEC lvalue				= {
382*7c478bd9Sstevel@tonic-gate 		$$ = node(PRE_DEC, $2, NNULL);
383*7c478bd9Sstevel@tonic-gate 	}
384*7c478bd9Sstevel@tonic-gate 	| INC lvalue				= {
385*7c478bd9Sstevel@tonic-gate 		$$ = node(PRE_INC, $2, NNULL);
386*7c478bd9Sstevel@tonic-gate 	}
387*7c478bd9Sstevel@tonic-gate 	| FUNC					= {
388*7c478bd9Sstevel@tonic-gate 		$$ = node(CALLFUNC, $1, NNULL);
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate 	| FUNC LPAREN eexprlist RPAREN term	= {
391*7c478bd9Sstevel@tonic-gate 		$$ = node(CALLFUNC, $1, $3);
392*7c478bd9Sstevel@tonic-gate 	}
393*7c478bd9Sstevel@tonic-gate 	| UFUNC LPAREN eexprlist RPAREN term	= {
394*7c478bd9Sstevel@tonic-gate 		$$ = node(CALLUFUNC, $1, $3);
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 	| VAR LPAREN eexprlist RPAREN term	= {
397*7c478bd9Sstevel@tonic-gate 		$$ = node(CALLUFUNC, $1, $3);
398*7c478bd9Sstevel@tonic-gate 	}
399*7c478bd9Sstevel@tonic-gate 	| SLASH {redelim='/';} URE SLASH %prec URE	= {
400*7c478bd9Sstevel@tonic-gate 		$$ = $<node>3;
401*7c478bd9Sstevel@tonic-gate 	}
402*7c478bd9Sstevel@tonic-gate 	;
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate statement:
405*7c478bd9Sstevel@tonic-gate 	  FOR LPAREN fexpr SEMI fexpr SEMI fexpr RPAREN statement = {
406*7c478bd9Sstevel@tonic-gate 		$$ = node(FOR, node(COMMA, $3, node(COMMA, $5, $7)), $9);
407*7c478bd9Sstevel@tonic-gate 	}
408*7c478bd9Sstevel@tonic-gate 	| FOR LPAREN var IN var RPAREN statement = {
409*7c478bd9Sstevel@tonic-gate 		register NODE *np;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 		/*
412*7c478bd9Sstevel@tonic-gate 		 * attempt to optimize statements for the form
413*7c478bd9Sstevel@tonic-gate 		 *    for (i in x) delete x[i]
414*7c478bd9Sstevel@tonic-gate 		 * to
415*7c478bd9Sstevel@tonic-gate 		 *    delete x
416*7c478bd9Sstevel@tonic-gate 		 */
417*7c478bd9Sstevel@tonic-gate 		np = $7;
418*7c478bd9Sstevel@tonic-gate 		if (np != NNULL
419*7c478bd9Sstevel@tonic-gate 		 && np->n_type == DELETE
420*7c478bd9Sstevel@tonic-gate 		 && (np = np->n_left)->n_type == INDEX
421*7c478bd9Sstevel@tonic-gate 		 && np->n_left == $5
422*7c478bd9Sstevel@tonic-gate 		 && np->n_right == $3)
423*7c478bd9Sstevel@tonic-gate 			$$ = node(DELETE, $5, NNULL);
424*7c478bd9Sstevel@tonic-gate 		else
425*7c478bd9Sstevel@tonic-gate 			$$ = node(FORIN, node(IN, $3, $5), $7);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	| WHILE LPAREN expr RPAREN statement	= {
428*7c478bd9Sstevel@tonic-gate 		$$ = node(WHILE, $3, $5);
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 	| DO statement WHILE LPAREN expr RPAREN	= {
431*7c478bd9Sstevel@tonic-gate 		$$ = node(DO, $5, $2);
432*7c478bd9Sstevel@tonic-gate 	}
433*7c478bd9Sstevel@tonic-gate 	| IF LPAREN expr RPAREN statement ELSE statement = {
434*7c478bd9Sstevel@tonic-gate 		$$ = node(IF, $3, node(ELSE, $5, $7));
435*7c478bd9Sstevel@tonic-gate 	}
436*7c478bd9Sstevel@tonic-gate 	| IF LPAREN expr RPAREN statement %prec ELSE	= {
437*7c478bd9Sstevel@tonic-gate 		$$ = node(IF, $3, node(ELSE, $5, NNULL));
438*7c478bd9Sstevel@tonic-gate 	}
439*7c478bd9Sstevel@tonic-gate 	| CONTINUE SEMI				= {
440*7c478bd9Sstevel@tonic-gate 		$$ = node(CONTINUE, NNULL, NNULL);
441*7c478bd9Sstevel@tonic-gate 	}
442*7c478bd9Sstevel@tonic-gate 	| BREAK SEMI				= {
443*7c478bd9Sstevel@tonic-gate 		$$ = node(BREAK, NNULL, NNULL);
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 	| NEXT SEMI				= {
446*7c478bd9Sstevel@tonic-gate 		$$ = node(NEXT, NNULL, NNULL);
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate 	| DELETE lvalue SEMI			= {
449*7c478bd9Sstevel@tonic-gate 		$$ = node(DELETE, $2, NNULL);
450*7c478bd9Sstevel@tonic-gate 	}
451*7c478bd9Sstevel@tonic-gate 	| RETURN fexpr SEMI			= {
452*7c478bd9Sstevel@tonic-gate 		$$ = node(RETURN, $2, NNULL);
453*7c478bd9Sstevel@tonic-gate 	}
454*7c478bd9Sstevel@tonic-gate 	| EXIT fexpr SEMI			= {
455*7c478bd9Sstevel@tonic-gate 		$$ = node(EXIT, $2, NNULL);
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate 	| PRINT eexprlist fileout SEMI		= {
458*7c478bd9Sstevel@tonic-gate 		$$ = node(PRINT, $2, $3);
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 	| PRINT LPAREN exprlist RPAREN fileout SEMI	= {
461*7c478bd9Sstevel@tonic-gate 		$$ = node(PRINT, $3, $5);
462*7c478bd9Sstevel@tonic-gate 	}
463*7c478bd9Sstevel@tonic-gate 	| PRINTF exprlist fileout SEMI		= {
464*7c478bd9Sstevel@tonic-gate 		$$ = node(PRINTF, $2, $3);
465*7c478bd9Sstevel@tonic-gate 	}
466*7c478bd9Sstevel@tonic-gate 	| PRINTF LPAREN exprlist RPAREN fileout SEMI	= {
467*7c478bd9Sstevel@tonic-gate 		$$ = node(PRINTF, $3, $5);
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate 	| expr SEMI 				= {
470*7c478bd9Sstevel@tonic-gate 		$$ = $1;
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 	| SEMI					= {
473*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
474*7c478bd9Sstevel@tonic-gate 	}
475*7c478bd9Sstevel@tonic-gate 	| LBRACE statlist RBRACE		= {
476*7c478bd9Sstevel@tonic-gate 		$$ = $2;
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 	;
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate statlist:
482*7c478bd9Sstevel@tonic-gate 	  statement
483*7c478bd9Sstevel@tonic-gate 	| statlist statement			= {
484*7c478bd9Sstevel@tonic-gate 		if ($1 == NNULL)
485*7c478bd9Sstevel@tonic-gate 			$$ = $2;
486*7c478bd9Sstevel@tonic-gate 		else if ($2 == NNULL)
487*7c478bd9Sstevel@tonic-gate 			$$ = $1;
488*7c478bd9Sstevel@tonic-gate 		else
489*7c478bd9Sstevel@tonic-gate 			$$ = node(COMMA, $1, $2);
490*7c478bd9Sstevel@tonic-gate 	}
491*7c478bd9Sstevel@tonic-gate 	;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate fileout:
494*7c478bd9Sstevel@tonic-gate 	  WRITE expr				= {
495*7c478bd9Sstevel@tonic-gate 		$$ = node(WRITE, $2, NNULL);
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate 	| APPEND expr				= {
498*7c478bd9Sstevel@tonic-gate 		$$ = node(APPEND, $2, NNULL);
499*7c478bd9Sstevel@tonic-gate 	}
500*7c478bd9Sstevel@tonic-gate 	| PIPE expr				= {
501*7c478bd9Sstevel@tonic-gate 		$$ = node(PIPE, $2, NNULL);
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 	|					= {
504*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
505*7c478bd9Sstevel@tonic-gate 	}
506*7c478bd9Sstevel@tonic-gate 	;
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate getline:
509*7c478bd9Sstevel@tonic-gate 	  GETLINE optvar %prec WRITE		= {
510*7c478bd9Sstevel@tonic-gate 		$$ = node(GETLINE, $2, NNULL);
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 	| expr BAR GETLINE optvar		= {
513*7c478bd9Sstevel@tonic-gate 		$$ = node(GETLINE, $4, node(PIPESYM, $1, NNULL));
514*7c478bd9Sstevel@tonic-gate 	}
515*7c478bd9Sstevel@tonic-gate 	| GETLINE optvar LANGLE expr		= {
516*7c478bd9Sstevel@tonic-gate 		$$ = node(GETLINE, $2, node(LT, $4, NNULL));
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 	;
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate optvar:
521*7c478bd9Sstevel@tonic-gate 	  lvalue
522*7c478bd9Sstevel@tonic-gate 	|					= {
523*7c478bd9Sstevel@tonic-gate 		$$ = NNULL;
524*7c478bd9Sstevel@tonic-gate 	}
525*7c478bd9Sstevel@tonic-gate 	;
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate term:
528*7c478bd9Sstevel@tonic-gate 	  {catterm = 1;}
529*7c478bd9Sstevel@tonic-gate 	;
530*7c478bd9Sstevel@tonic-gate %%
531*7c478bd9Sstevel@tonic-gate /*
532*7c478bd9Sstevel@tonic-gate  * Flip a left-recursively generated list
533*7c478bd9Sstevel@tonic-gate  * so that it can easily be traversed from left
534*7c478bd9Sstevel@tonic-gate  * to right without recursion.
535*7c478bd9Sstevel@tonic-gate  */
536*7c478bd9Sstevel@tonic-gate static NODE *
537*7c478bd9Sstevel@tonic-gate fliplist(np)
538*7c478bd9Sstevel@tonic-gate register NODE *np;
539*7c478bd9Sstevel@tonic-gate {
540*7c478bd9Sstevel@tonic-gate 	int type;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	if (np!=NNULL && !isleaf(np->n_flags)
543*7c478bd9Sstevel@tonic-gate #if 0
544*7c478bd9Sstevel@tonic-gate 		 && (type = np->n_type)!=FUNC && type!=UFUNC
545*7c478bd9Sstevel@tonic-gate #endif
546*7c478bd9Sstevel@tonic-gate 	) {
547*7c478bd9Sstevel@tonic-gate 		np->n_right = fliplist(np->n_right);
548*7c478bd9Sstevel@tonic-gate 		if ((type=np->n_type)==COMMA) {
549*7c478bd9Sstevel@tonic-gate 			register NODE *lp;
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 			while ((lp = np->n_left)!=NNULL && lp->n_type==COMMA) {
552*7c478bd9Sstevel@tonic-gate 				register NODE* *spp;
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 				lp->n_right = fliplist(lp->n_right);
555*7c478bd9Sstevel@tonic-gate 				for (spp = &lp->n_right;
556*7c478bd9Sstevel@tonic-gate 				    *spp != NNULL && (*spp)->n_type==COMMA;
557*7c478bd9Sstevel@tonic-gate 				     spp = &(*spp)->n_right)
558*7c478bd9Sstevel@tonic-gate 					;
559*7c478bd9Sstevel@tonic-gate 				np->n_left = *spp;
560*7c478bd9Sstevel@tonic-gate 				*spp = np;
561*7c478bd9Sstevel@tonic-gate 				np = lp;
562*7c478bd9Sstevel@tonic-gate 			}
563*7c478bd9Sstevel@tonic-gate 		}
564*7c478bd9Sstevel@tonic-gate 		if (np->n_left != NULL &&
565*7c478bd9Sstevel@tonic-gate 		    (type = np->n_left->n_type)!= FUNC && type!=UFUNC)
566*7c478bd9Sstevel@tonic-gate 			np->n_left = fliplist(np->n_left);
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 	return (np);
569*7c478bd9Sstevel@tonic-gate }
570