xref: /titanic_51/usr/src/cmd/awk/awk.g.y (revision 1ee2e5fa222f6d33d1ff1c48f155973a5e146434)
17c478bd9Sstevel@tonic-gate %{
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * CDDL HEADER START
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
67c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
77c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
87c478bd9Sstevel@tonic-gate  * with the License.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
117c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
127c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
137c478bd9Sstevel@tonic-gate  * and limitations under the License.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
167c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
177c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
187c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
197c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * CDDL HEADER END
227c478bd9Sstevel@tonic-gate  */
237c478bd9Sstevel@tonic-gate %}
24*1ee2e5faSnakanon /*
25*1ee2e5faSnakanon  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*1ee2e5faSnakanon  * Use is subject to license terms.
27*1ee2e5faSnakanon  */
28*1ee2e5faSnakanon 
297c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
307c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate %{
337c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 2.10	*/
347c478bd9Sstevel@tonic-gate %}
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate %{
377c478bd9Sstevel@tonic-gate #include "awk.h"
38*1ee2e5faSnakanon int yywrap(void) { return(1); }
397c478bd9Sstevel@tonic-gate #ifndef	DEBUG
407c478bd9Sstevel@tonic-gate #	define	PUTS(x)
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate Node	*beginloc = 0, *endloc = 0;
437c478bd9Sstevel@tonic-gate int	infunc	= 0;	/* = 1 if in arglist or body of func */
447c478bd9Sstevel@tonic-gate uchar	*curfname = 0;
457c478bd9Sstevel@tonic-gate Node	*arglist = 0;	/* list of args for current function */
46*1ee2e5faSnakanon static void	setfname(Cell *);
47*1ee2e5faSnakanon static int	constnode(Node *);
48*1ee2e5faSnakanon static uchar	*strnode(Node *);
49*1ee2e5faSnakanon static Node	*notnull();
507c478bd9Sstevel@tonic-gate %}
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate %union {
537c478bd9Sstevel@tonic-gate 	Node	*p;
547c478bd9Sstevel@tonic-gate 	Cell	*cp;
557c478bd9Sstevel@tonic-gate 	int	i;
567c478bd9Sstevel@tonic-gate 	uchar	*s;
577c478bd9Sstevel@tonic-gate }
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate %token	<i>	FIRSTTOKEN	/* must be first */
607c478bd9Sstevel@tonic-gate %token	<p>	PROGRAM PASTAT PASTAT2 XBEGIN XEND
617c478bd9Sstevel@tonic-gate %token	<i>	NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
627c478bd9Sstevel@tonic-gate %token	<i>	ARRAY
637c478bd9Sstevel@tonic-gate %token	<i>	MATCH NOTMATCH MATCHOP
647c478bd9Sstevel@tonic-gate %token	<i>	FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
657c478bd9Sstevel@tonic-gate %token	<i>	AND BOR APPEND EQ GE GT LE LT NE IN
667c478bd9Sstevel@tonic-gate %token	<i>	ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
677c478bd9Sstevel@tonic-gate %token	<i>	SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
687c478bd9Sstevel@tonic-gate %token	<i>	ADD MINUS MULT DIVIDE MOD
697c478bd9Sstevel@tonic-gate %token	<i>	ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
707c478bd9Sstevel@tonic-gate %token	<i>	PRINT PRINTF SPRINTF
717c478bd9Sstevel@tonic-gate %token	<p>	ELSE INTEST CONDEXPR
727c478bd9Sstevel@tonic-gate %token	<i>	POSTINCR PREINCR POSTDECR PREDECR
737c478bd9Sstevel@tonic-gate %token	<cp>	VAR IVAR VARNF CALL NUMBER STRING FIELD
747c478bd9Sstevel@tonic-gate %token	<s>	REGEXPR
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate %type	<p>	pas pattern ppattern plist pplist patlist prarg term
777c478bd9Sstevel@tonic-gate %type	<p>	pa_pat pa_stat pa_stats
787c478bd9Sstevel@tonic-gate %type	<s>	reg_expr
797c478bd9Sstevel@tonic-gate %type	<p>	simple_stmt opt_simple_stmt stmt stmtlist
807c478bd9Sstevel@tonic-gate %type	<p>	var varname funcname varlist
817c478bd9Sstevel@tonic-gate %type	<p>	for if while
827c478bd9Sstevel@tonic-gate %type	<i>	pst opt_pst lbrace rparen comma nl opt_nl and bor
837c478bd9Sstevel@tonic-gate %type	<i>	subop print
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate %right	ASGNOP
867c478bd9Sstevel@tonic-gate %right	'?'
877c478bd9Sstevel@tonic-gate %right	':'
887c478bd9Sstevel@tonic-gate %left	BOR
897c478bd9Sstevel@tonic-gate %left	AND
907c478bd9Sstevel@tonic-gate %left	GETLINE
917c478bd9Sstevel@tonic-gate %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
927c478bd9Sstevel@tonic-gate %left	ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC
937c478bd9Sstevel@tonic-gate %left	GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
947c478bd9Sstevel@tonic-gate %left	PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
957c478bd9Sstevel@tonic-gate %left	REGEXPR VAR VARNF IVAR WHILE '('
967c478bd9Sstevel@tonic-gate %left	CAT
977c478bd9Sstevel@tonic-gate %left	'+' '-'
987c478bd9Sstevel@tonic-gate %left	'*' '/' '%'
997c478bd9Sstevel@tonic-gate %left	NOT UMINUS
1007c478bd9Sstevel@tonic-gate %right	POWER
1017c478bd9Sstevel@tonic-gate %right	DECR INCR
1027c478bd9Sstevel@tonic-gate %left	INDIRECT
1037c478bd9Sstevel@tonic-gate %token	LASTTOKEN	/* must be last */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate %%
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate program:
1087c478bd9Sstevel@tonic-gate 	  pas	{ if (errorflag==0)
1097c478bd9Sstevel@tonic-gate 			winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
1107c478bd9Sstevel@tonic-gate 	| error	{ yyclearin; bracecheck(); ERROR "bailing out" SYNTAX; }
1117c478bd9Sstevel@tonic-gate 	;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate and:
1147c478bd9Sstevel@tonic-gate 	  AND | and NL
1157c478bd9Sstevel@tonic-gate 	;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate bor:
1187c478bd9Sstevel@tonic-gate 	  BOR | bor NL
1197c478bd9Sstevel@tonic-gate 	;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate comma:
1227c478bd9Sstevel@tonic-gate 	  ',' | comma NL
1237c478bd9Sstevel@tonic-gate 	;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate do:
1267c478bd9Sstevel@tonic-gate 	  DO | do NL
1277c478bd9Sstevel@tonic-gate 	;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate else:
1307c478bd9Sstevel@tonic-gate 	  ELSE | else NL
1317c478bd9Sstevel@tonic-gate 	;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate for:
1347c478bd9Sstevel@tonic-gate 	  FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
1357c478bd9Sstevel@tonic-gate 		{ $$ = stat4(FOR, $3, notnull($5), $7, $9); }
1367c478bd9Sstevel@tonic-gate 	| FOR '(' opt_simple_stmt ';'  ';' opt_simple_stmt rparen stmt
1377c478bd9Sstevel@tonic-gate 		{ $$ = stat4(FOR, $3, NIL, $6, $8); }
1387c478bd9Sstevel@tonic-gate 	| FOR '(' varname IN varname rparen stmt
1397c478bd9Sstevel@tonic-gate 		{ $$ = stat3(IN, $3, makearr($5), $7); }
1407c478bd9Sstevel@tonic-gate 	;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate funcname:
1437c478bd9Sstevel@tonic-gate 	  VAR	{ setfname($1); }
1447c478bd9Sstevel@tonic-gate 	| CALL	{ setfname($1); }
1457c478bd9Sstevel@tonic-gate 	;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate if:
1487c478bd9Sstevel@tonic-gate 	  IF '(' pattern rparen		{ $$ = notnull($3); }
1497c478bd9Sstevel@tonic-gate 	;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate lbrace:
1527c478bd9Sstevel@tonic-gate 	  '{' | lbrace NL
1537c478bd9Sstevel@tonic-gate 	;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate nl:
1567c478bd9Sstevel@tonic-gate 	  NL | nl NL
1577c478bd9Sstevel@tonic-gate 	;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate opt_nl:
1607c478bd9Sstevel@tonic-gate 	  /* empty */	{ $$ = 0; }
1617c478bd9Sstevel@tonic-gate 	| nl
1627c478bd9Sstevel@tonic-gate 	;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate opt_pst:
1657c478bd9Sstevel@tonic-gate 	  /* empty */	{ $$ = 0; }
1667c478bd9Sstevel@tonic-gate 	| pst
1677c478bd9Sstevel@tonic-gate 	;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate opt_simple_stmt:
1717c478bd9Sstevel@tonic-gate 	  /* empty */			{ $$ = 0; }
1727c478bd9Sstevel@tonic-gate 	| simple_stmt
1737c478bd9Sstevel@tonic-gate 	;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate pas:
1767c478bd9Sstevel@tonic-gate 	  opt_pst			{ $$ = 0; }
1777c478bd9Sstevel@tonic-gate 	| opt_pst pa_stats opt_pst	{ $$ = $2; }
1787c478bd9Sstevel@tonic-gate 	;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate pa_pat:
1817c478bd9Sstevel@tonic-gate 	  pattern	{ $$ = notnull($1); }
1827c478bd9Sstevel@tonic-gate 	;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate pa_stat:
1857c478bd9Sstevel@tonic-gate 	  pa_pat			{ $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
1867c478bd9Sstevel@tonic-gate 	| pa_pat lbrace stmtlist '}'	{ $$ = stat2(PASTAT, $1, $3); }
1877c478bd9Sstevel@tonic-gate 	| pa_pat ',' pa_pat		{ $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
1887c478bd9Sstevel@tonic-gate 	| pa_pat ',' pa_pat lbrace stmtlist '}'	{ $$ = pa2stat($1, $3, $5); }
1897c478bd9Sstevel@tonic-gate 	| lbrace stmtlist '}'		{ $$ = stat2(PASTAT, NIL, $2); }
1907c478bd9Sstevel@tonic-gate 	| XBEGIN lbrace stmtlist '}'
1917c478bd9Sstevel@tonic-gate 		{ beginloc = linkum(beginloc, $3); $$ = 0; }
1927c478bd9Sstevel@tonic-gate 	| XEND lbrace stmtlist '}'
1937c478bd9Sstevel@tonic-gate 		{ endloc = linkum(endloc, $3); $$ = 0; }
1947c478bd9Sstevel@tonic-gate 	| FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
1957c478bd9Sstevel@tonic-gate 		{ infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
1967c478bd9Sstevel@tonic-gate 	;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate pa_stats:
1997c478bd9Sstevel@tonic-gate 	  pa_stat
2007c478bd9Sstevel@tonic-gate 	| pa_stats opt_pst pa_stat	{ $$ = linkum($1, $3); }
2017c478bd9Sstevel@tonic-gate 	;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate patlist:
2047c478bd9Sstevel@tonic-gate 	  pattern
2057c478bd9Sstevel@tonic-gate 	| patlist comma pattern	{ $$ = linkum($1, $3); }
2067c478bd9Sstevel@tonic-gate 	;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate ppattern:
2097c478bd9Sstevel@tonic-gate 	  var ASGNOP ppattern		{ $$ = op2($2, $1, $3); }
2107c478bd9Sstevel@tonic-gate 	| ppattern '?' ppattern ':' ppattern %prec '?'
2117c478bd9Sstevel@tonic-gate 	 	{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2127c478bd9Sstevel@tonic-gate 	| ppattern bor ppattern %prec BOR
2137c478bd9Sstevel@tonic-gate 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2147c478bd9Sstevel@tonic-gate 	| ppattern and ppattern %prec AND
2157c478bd9Sstevel@tonic-gate 		{ $$ = op2(AND, notnull($1), notnull($3)); }
2167c478bd9Sstevel@tonic-gate 	| NOT ppattern
2177c478bd9Sstevel@tonic-gate 		{ $$ = op1(NOT, notnull($2)); }
2187c478bd9Sstevel@tonic-gate 	| ppattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2197c478bd9Sstevel@tonic-gate 	| ppattern MATCHOP ppattern
2207c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
2217c478bd9Sstevel@tonic-gate 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2227c478bd9Sstevel@tonic-gate 		  else
2237c478bd9Sstevel@tonic-gate 			$$ = op3($2, (Node *)1, $1, $3); }
2247c478bd9Sstevel@tonic-gate 	| ppattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2257c478bd9Sstevel@tonic-gate 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
2267c478bd9Sstevel@tonic-gate 	| ppattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
2277c478bd9Sstevel@tonic-gate 	| reg_expr
2287c478bd9Sstevel@tonic-gate 		{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
2297c478bd9Sstevel@tonic-gate 	| term
2307c478bd9Sstevel@tonic-gate 	;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate pattern:
2337c478bd9Sstevel@tonic-gate 	  var ASGNOP pattern		{ $$ = op2($2, $1, $3); }
2347c478bd9Sstevel@tonic-gate 	| pattern '?' pattern ':' pattern %prec '?'
2357c478bd9Sstevel@tonic-gate 	 	{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2367c478bd9Sstevel@tonic-gate 	| pattern bor pattern %prec BOR
2377c478bd9Sstevel@tonic-gate 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2387c478bd9Sstevel@tonic-gate 	| pattern and pattern %prec AND
2397c478bd9Sstevel@tonic-gate 		{ $$ = op2(AND, notnull($1), notnull($3)); }
2407c478bd9Sstevel@tonic-gate 	| NOT pattern
241*1ee2e5faSnakanon 		{ $$ = op1(NOT, op2(NE,$2,valtonode(lookup((uchar *)"$zero&null",symtab),CCON))); }
2427c478bd9Sstevel@tonic-gate 	| pattern EQ pattern		{ $$ = op2($2, $1, $3); }
2437c478bd9Sstevel@tonic-gate 	| pattern GE pattern		{ $$ = op2($2, $1, $3); }
2447c478bd9Sstevel@tonic-gate 	| pattern GT pattern		{ $$ = op2($2, $1, $3); }
2457c478bd9Sstevel@tonic-gate 	| pattern LE pattern		{ $$ = op2($2, $1, $3); }
2467c478bd9Sstevel@tonic-gate 	| pattern LT pattern		{ $$ = op2($2, $1, $3); }
2477c478bd9Sstevel@tonic-gate 	| pattern NE pattern		{ $$ = op2($2, $1, $3); }
2487c478bd9Sstevel@tonic-gate 	| pattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2497c478bd9Sstevel@tonic-gate 	| pattern MATCHOP pattern
2507c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
2517c478bd9Sstevel@tonic-gate 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2527c478bd9Sstevel@tonic-gate 		  else
2537c478bd9Sstevel@tonic-gate 			$$ = op3($2, (Node *)1, $1, $3); }
2547c478bd9Sstevel@tonic-gate 	| pattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2557c478bd9Sstevel@tonic-gate 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
2567c478bd9Sstevel@tonic-gate 	| pattern '|' GETLINE var	{ $$ = op3(GETLINE, $4, (Node*)$2, $1); }
2577c478bd9Sstevel@tonic-gate 	| pattern '|' GETLINE		{ $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
2587c478bd9Sstevel@tonic-gate 	| pattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
2597c478bd9Sstevel@tonic-gate 	| reg_expr
2607c478bd9Sstevel@tonic-gate 		{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
2617c478bd9Sstevel@tonic-gate 	| term
2627c478bd9Sstevel@tonic-gate 	;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate plist:
2657c478bd9Sstevel@tonic-gate 	  pattern comma pattern		{ $$ = linkum($1, $3); }
2667c478bd9Sstevel@tonic-gate 	| plist comma pattern		{ $$ = linkum($1, $3); }
2677c478bd9Sstevel@tonic-gate 	;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate pplist:
2707c478bd9Sstevel@tonic-gate 	  ppattern
2717c478bd9Sstevel@tonic-gate 	| pplist comma ppattern		{ $$ = linkum($1, $3); }
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate prarg:
2747c478bd9Sstevel@tonic-gate 	  /* empty */			{ $$ = rectonode(); }
2757c478bd9Sstevel@tonic-gate 	| pplist
2767c478bd9Sstevel@tonic-gate 	| '(' plist ')'			{ $$ = $2; }
2777c478bd9Sstevel@tonic-gate 	;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate print:
2807c478bd9Sstevel@tonic-gate 	  PRINT | PRINTF
2817c478bd9Sstevel@tonic-gate 	;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate pst:
2847c478bd9Sstevel@tonic-gate 	  NL | ';' | pst NL | pst ';'
2857c478bd9Sstevel@tonic-gate 	;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate rbrace:
2887c478bd9Sstevel@tonic-gate 	  '}' | rbrace NL
2897c478bd9Sstevel@tonic-gate 	;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate reg_expr:
2927c478bd9Sstevel@tonic-gate 	  '/' {startreg();} REGEXPR '/'		{ $$ = $3; }
2937c478bd9Sstevel@tonic-gate 	;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate rparen:
2967c478bd9Sstevel@tonic-gate 	  ')' | rparen NL
2977c478bd9Sstevel@tonic-gate 	;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate simple_stmt:
3007c478bd9Sstevel@tonic-gate 	  print prarg '|' term		{ $$ = stat3($1, $2, (Node *) $3, $4); }
3017c478bd9Sstevel@tonic-gate 	| print prarg APPEND term	{ $$ = stat3($1, $2, (Node *) $3, $4); }
3027c478bd9Sstevel@tonic-gate 	| print prarg GT term		{ $$ = stat3($1, $2, (Node *) $3, $4); }
3037c478bd9Sstevel@tonic-gate 	| print prarg			{ $$ = stat3($1, $2, NIL, NIL); }
3047c478bd9Sstevel@tonic-gate 	| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
3057c478bd9Sstevel@tonic-gate 	| DELETE varname		{ yyclearin; ERROR "you can only delete array[element]" SYNTAX; $$ = stat1(DELETE, $2); }
3067c478bd9Sstevel@tonic-gate 	| pattern			{ $$ = exptostat($1); }
3077c478bd9Sstevel@tonic-gate 	| error				{ yyclearin; ERROR "illegal statement" SYNTAX; }
3087c478bd9Sstevel@tonic-gate 	;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate st:
3117c478bd9Sstevel@tonic-gate 	  nl | ';' opt_nl
3127c478bd9Sstevel@tonic-gate 	;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate stmt:
3157c478bd9Sstevel@tonic-gate 	  BREAK st		{ $$ = stat1(BREAK, NIL); }
3167c478bd9Sstevel@tonic-gate 	| CLOSE pattern st	{ $$ = stat1(CLOSE, $2); }
3177c478bd9Sstevel@tonic-gate 	| CONTINUE st		{ $$ = stat1(CONTINUE, NIL); }
3187c478bd9Sstevel@tonic-gate 	| do stmt WHILE '(' pattern ')' st
3197c478bd9Sstevel@tonic-gate 		{ $$ = stat2(DO, $2, notnull($5)); }
3207c478bd9Sstevel@tonic-gate 	| EXIT pattern st	{ $$ = stat1(EXIT, $2); }
3217c478bd9Sstevel@tonic-gate 	| EXIT st		{ $$ = stat1(EXIT, NIL); }
3227c478bd9Sstevel@tonic-gate 	| for
3237c478bd9Sstevel@tonic-gate 	| if stmt else stmt	{ $$ = stat3(IF, $1, $2, $4); }
3247c478bd9Sstevel@tonic-gate 	| if stmt		{ $$ = stat3(IF, $1, $2, NIL); }
3257c478bd9Sstevel@tonic-gate 	| lbrace stmtlist rbrace { $$ = $2; }
3267c478bd9Sstevel@tonic-gate 	| NEXT st	{ if (infunc)
3277c478bd9Sstevel@tonic-gate 				ERROR "next is illegal inside a function" SYNTAX;
3287c478bd9Sstevel@tonic-gate 			  $$ = stat1(NEXT, NIL); }
3297c478bd9Sstevel@tonic-gate 	| RETURN pattern st	{ $$ = stat1(RETURN, $2); }
3307c478bd9Sstevel@tonic-gate 	| RETURN st		{ $$ = stat1(RETURN, NIL); }
3317c478bd9Sstevel@tonic-gate 	| simple_stmt st
3327c478bd9Sstevel@tonic-gate 	| while stmt		{ $$ = stat2(WHILE, $1, $2); }
3337c478bd9Sstevel@tonic-gate 	| ';' opt_nl		{ $$ = 0; }
3347c478bd9Sstevel@tonic-gate 	;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate stmtlist:
3377c478bd9Sstevel@tonic-gate 	  stmt
3387c478bd9Sstevel@tonic-gate 	| stmtlist stmt		{ $$ = linkum($1, $2); }
3397c478bd9Sstevel@tonic-gate 	;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate subop:
3427c478bd9Sstevel@tonic-gate 	  SUB | GSUB
3437c478bd9Sstevel@tonic-gate 	;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate term:
3467c478bd9Sstevel@tonic-gate 	  term '+' term			{ $$ = op2(ADD, $1, $3); }
3477c478bd9Sstevel@tonic-gate 	| term '-' term			{ $$ = op2(MINUS, $1, $3); }
3487c478bd9Sstevel@tonic-gate 	| term '*' term			{ $$ = op2(MULT, $1, $3); }
3497c478bd9Sstevel@tonic-gate 	| term '/' term			{ $$ = op2(DIVIDE, $1, $3); }
3507c478bd9Sstevel@tonic-gate 	| term '%' term			{ $$ = op2(MOD, $1, $3); }
3517c478bd9Sstevel@tonic-gate 	| term POWER term		{ $$ = op2(POWER, $1, $3); }
3527c478bd9Sstevel@tonic-gate 	| '-' term %prec UMINUS		{ $$ = op1(UMINUS, $2); }
3537c478bd9Sstevel@tonic-gate 	| '+' term %prec UMINUS		{ $$ = $2; }
3547c478bd9Sstevel@tonic-gate 	| BLTIN '(' ')'			{ $$ = op2(BLTIN, (Node *) $1, rectonode()); }
3557c478bd9Sstevel@tonic-gate 	| BLTIN '(' patlist ')'		{ $$ = op2(BLTIN, (Node *) $1, $3); }
3567c478bd9Sstevel@tonic-gate 	| BLTIN				{ $$ = op2(BLTIN, (Node *) $1, rectonode()); }
3577c478bd9Sstevel@tonic-gate 	| CALL '(' ')'			{ $$ = op2(CALL, valtonode($1,CVAR), NIL); }
3587c478bd9Sstevel@tonic-gate 	| CALL '(' patlist ')'		{ $$ = op2(CALL, valtonode($1,CVAR), $3); }
3597c478bd9Sstevel@tonic-gate 	| DECR var			{ $$ = op1(PREDECR, $2); }
3607c478bd9Sstevel@tonic-gate 	| INCR var			{ $$ = op1(PREINCR, $2); }
3617c478bd9Sstevel@tonic-gate 	| var DECR			{ $$ = op1(POSTDECR, $1); }
3627c478bd9Sstevel@tonic-gate 	| var INCR			{ $$ = op1(POSTINCR, $1); }
3637c478bd9Sstevel@tonic-gate 	| GETLINE var LT term		{ $$ = op3(GETLINE, $2, (Node *)$3, $4); }
3647c478bd9Sstevel@tonic-gate 	| GETLINE LT term		{ $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
3657c478bd9Sstevel@tonic-gate 	| GETLINE var			{ $$ = op3(GETLINE, $2, NIL, NIL); }
3667c478bd9Sstevel@tonic-gate 	| GETLINE			{ $$ = op3(GETLINE, NIL, NIL, NIL); }
3677c478bd9Sstevel@tonic-gate 	| INDEX '(' pattern comma pattern ')'
3687c478bd9Sstevel@tonic-gate 		{ $$ = op2(INDEX, $3, $5); }
3697c478bd9Sstevel@tonic-gate 	| INDEX '(' pattern comma reg_expr ')'
3707c478bd9Sstevel@tonic-gate 		{ ERROR "index() doesn't permit regular expressions" SYNTAX;
3717c478bd9Sstevel@tonic-gate 		  $$ = op2(INDEX, $3, (Node*)$5); }
3727c478bd9Sstevel@tonic-gate 	| '(' pattern ')'		{ $$ = $2; }
3737c478bd9Sstevel@tonic-gate 	| MATCHFCN '(' pattern comma reg_expr ')'
3747c478bd9Sstevel@tonic-gate 		{ $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
3757c478bd9Sstevel@tonic-gate 	| MATCHFCN '(' pattern comma pattern ')'
3767c478bd9Sstevel@tonic-gate 		{ if (constnode($5))
3777c478bd9Sstevel@tonic-gate 			$$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
3787c478bd9Sstevel@tonic-gate 		  else
3797c478bd9Sstevel@tonic-gate 			$$ = op3(MATCHFCN, (Node *)1, $3, $5); }
3807c478bd9Sstevel@tonic-gate 	| NUMBER			{ $$ = valtonode($1, CCON); }
3817c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname comma pattern ')'     /* string */
3827c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
3837c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname comma reg_expr ')'    /* const /regexp/ */
3847c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
3857c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname ')'
3867c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); }  /* default */
3877c478bd9Sstevel@tonic-gate 	| SPRINTF '(' patlist ')'	{ $$ = op1($1, $3); }
3887c478bd9Sstevel@tonic-gate 	| STRING	 		{ $$ = valtonode($1, CCON); }
3897c478bd9Sstevel@tonic-gate 	| subop '(' reg_expr comma pattern ')'
3907c478bd9Sstevel@tonic-gate 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
3917c478bd9Sstevel@tonic-gate 	| subop '(' pattern comma pattern ')'
3927c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
3937c478bd9Sstevel@tonic-gate 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
3947c478bd9Sstevel@tonic-gate 		  else
3957c478bd9Sstevel@tonic-gate 			$$ = op4($1, (Node *)1, $3, $5, rectonode()); }
3967c478bd9Sstevel@tonic-gate 	| subop '(' reg_expr comma pattern comma var ')'
3977c478bd9Sstevel@tonic-gate 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
3987c478bd9Sstevel@tonic-gate 	| subop '(' pattern comma pattern comma var ')'
3997c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
4007c478bd9Sstevel@tonic-gate 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
4017c478bd9Sstevel@tonic-gate 		  else
4027c478bd9Sstevel@tonic-gate 			$$ = op4($1, (Node *)1, $3, $5, $7); }
4037c478bd9Sstevel@tonic-gate 	| SUBSTR '(' pattern comma pattern comma pattern ')'
4047c478bd9Sstevel@tonic-gate 		{ $$ = op3(SUBSTR, $3, $5, $7); }
4057c478bd9Sstevel@tonic-gate 	| SUBSTR '(' pattern comma pattern ')'
4067c478bd9Sstevel@tonic-gate 		{ $$ = op3(SUBSTR, $3, $5, NIL); }
4077c478bd9Sstevel@tonic-gate 	| var
4087c478bd9Sstevel@tonic-gate 	;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate var:
4117c478bd9Sstevel@tonic-gate 	  varname
4127c478bd9Sstevel@tonic-gate 	| varname '[' patlist ']'	{ $$ = op2(ARRAY, makearr($1), $3); }
4137c478bd9Sstevel@tonic-gate 	| FIELD				{ $$ = valtonode($1, CFLD); }
4147c478bd9Sstevel@tonic-gate 	| IVAR				{ $$ = op1(INDIRECT, valtonode($1, CVAR)); }
4157c478bd9Sstevel@tonic-gate 	| INDIRECT term	 		{ $$ = op1(INDIRECT, $2); }
4167c478bd9Sstevel@tonic-gate 	;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate varlist:
4197c478bd9Sstevel@tonic-gate 	  /* nothing */		{ arglist = $$ = 0; }
4207c478bd9Sstevel@tonic-gate 	| VAR			{ arglist = $$ = valtonode($1,CVAR); }
4217c478bd9Sstevel@tonic-gate 	| varlist comma VAR	{ arglist = $$ = linkum($1,valtonode($3,CVAR)); }
4227c478bd9Sstevel@tonic-gate 	;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate varname:
4257c478bd9Sstevel@tonic-gate 	  VAR			{ $$ = valtonode($1, CVAR); }
4267c478bd9Sstevel@tonic-gate 	| ARG 			{ $$ = op1(ARG, (Node *) $1); }
4277c478bd9Sstevel@tonic-gate 	| VARNF			{ $$ = op1(VARNF, (Node *) $1); }
4287c478bd9Sstevel@tonic-gate 	;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate while:
4327c478bd9Sstevel@tonic-gate 	  WHILE '(' pattern rparen	{ $$ = notnull($3); }
4337c478bd9Sstevel@tonic-gate 	;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate %%
4367c478bd9Sstevel@tonic-gate 
437*1ee2e5faSnakanon static void
438*1ee2e5faSnakanon setfname(Cell *p)
4397c478bd9Sstevel@tonic-gate {
4407c478bd9Sstevel@tonic-gate 	if (isarr(p))
4417c478bd9Sstevel@tonic-gate 		ERROR "%s is an array, not a function", p->nval SYNTAX;
4427c478bd9Sstevel@tonic-gate 	else if (isfunc(p))
4437c478bd9Sstevel@tonic-gate 		ERROR "you can't define function %s more than once", p->nval SYNTAX;
4447c478bd9Sstevel@tonic-gate 	curfname = p->nval;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate 
447*1ee2e5faSnakanon 
448*1ee2e5faSnakanon static int
449*1ee2e5faSnakanon constnode(Node *p)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 	return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
454*1ee2e5faSnakanon static uchar *
455*1ee2e5faSnakanon strnode(Node *p)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	return ((Cell *)(p->narg[0]))->sval;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
460*1ee2e5faSnakanon static Node *
461*1ee2e5faSnakanon notnull(Node *n)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	switch (n->nobj) {
4647c478bd9Sstevel@tonic-gate 	case LE: case LT: case EQ: case NE: case GT: case GE:
4657c478bd9Sstevel@tonic-gate 	case BOR: case AND: case NOT:
4667c478bd9Sstevel@tonic-gate 		return n;
4677c478bd9Sstevel@tonic-gate 	default:
4687c478bd9Sstevel@tonic-gate 		return op2(NE, n, nullnode);
4697c478bd9Sstevel@tonic-gate 	}
4707c478bd9Sstevel@tonic-gate }
471