xref: /illumos-gate/usr/src/cmd/awk/awk.g.y (revision 3ee4fc2a)
17c478bd9Sstevel@tonic-gate %{
2*3ee4fc2aSCody Peter Mello /*
3*3ee4fc2aSCody Peter Mello  * Copyright (C) Lucent Technologies 1997
4*3ee4fc2aSCody Peter Mello  * All Rights Reserved
5*3ee4fc2aSCody Peter Mello  *
6*3ee4fc2aSCody Peter Mello  * Permission to use, copy, modify, and distribute this software and
7*3ee4fc2aSCody Peter Mello  * its documentation for any purpose and without fee is hereby
8*3ee4fc2aSCody Peter Mello  * granted, provided that the above copyright notice appear in all
9*3ee4fc2aSCody Peter Mello  * copies and that both that the copyright notice and this
10*3ee4fc2aSCody Peter Mello  * permission notice and warranty disclaimer appear in supporting
11*3ee4fc2aSCody Peter Mello  * documentation, and that the name Lucent Technologies or any of
12*3ee4fc2aSCody Peter Mello  * its entities not be used in advertising or publicity pertaining
13*3ee4fc2aSCody Peter Mello  * to distribution of the software without specific, written prior
14*3ee4fc2aSCody Peter Mello  * permission.
15*3ee4fc2aSCody Peter Mello  *
16*3ee4fc2aSCody Peter Mello  * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17*3ee4fc2aSCody Peter Mello  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18*3ee4fc2aSCody Peter Mello  * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19*3ee4fc2aSCody Peter Mello  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20*3ee4fc2aSCody Peter Mello  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21*3ee4fc2aSCody Peter Mello  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22*3ee4fc2aSCody Peter Mello  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23*3ee4fc2aSCody Peter Mello  * THIS SOFTWARE.
24*3ee4fc2aSCody Peter Mello  */
25*3ee4fc2aSCody Peter Mello 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * CDDL HEADER START
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
307c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
317c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
327c478bd9Sstevel@tonic-gate  * with the License.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
357c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
367c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
377c478bd9Sstevel@tonic-gate  * and limitations under the License.
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
407c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
417c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
427c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
437c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  * CDDL HEADER END
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate %}
481ee2e5faSnakanon /*
491ee2e5faSnakanon  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
501ee2e5faSnakanon  * Use is subject to license terms.
511ee2e5faSnakanon  */
521ee2e5faSnakanon 
537c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
547c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate %{
577c478bd9Sstevel@tonic-gate #include "awk.h"
58*3ee4fc2aSCody Peter Mello 
59*3ee4fc2aSCody Peter Mello void checkdup(Node *list, Cell *item);
yywrap(void)601ee2e5faSnakanon int yywrap(void) { return(1); }
61*3ee4fc2aSCody Peter Mello 
62*3ee4fc2aSCody Peter Mello Node	*beginloc = NULL;
63*3ee4fc2aSCody Peter Mello Node	*endloc = NULL;
64*3ee4fc2aSCody Peter Mello int	infunc	= 0;		/* = 1 if in arglist or body of func */
65*3ee4fc2aSCody Peter Mello int	inloop	= 0;		/* = 1 if in while, for, do */
66*3ee4fc2aSCody Peter Mello char	*curfname = NULL;	/* current function name */
67*3ee4fc2aSCody Peter Mello Node	*arglist = NULL;	/* list of args for current function */
681ee2e5faSnakanon static void	setfname(Cell *);
691ee2e5faSnakanon static int	constnode(Node *);
70*3ee4fc2aSCody Peter Mello static char	*strnode(Node *);
71*3ee4fc2aSCody Peter Mello static Node	*notnull(Node *);
727c478bd9Sstevel@tonic-gate %}
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate %union {
757c478bd9Sstevel@tonic-gate 	Node	*p;
767c478bd9Sstevel@tonic-gate 	Cell	*cp;
777c478bd9Sstevel@tonic-gate 	int	i;
78*3ee4fc2aSCody Peter Mello 	char	*s;
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate %token	<i>	FIRSTTOKEN	/* must be first */
827c478bd9Sstevel@tonic-gate %token	<p>	PROGRAM PASTAT PASTAT2 XBEGIN XEND
837c478bd9Sstevel@tonic-gate %token	<i>	NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
847c478bd9Sstevel@tonic-gate %token	<i>	ARRAY
857c478bd9Sstevel@tonic-gate %token	<i>	MATCH NOTMATCH MATCHOP
86*3ee4fc2aSCody Peter Mello %token	<i>	FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE
877c478bd9Sstevel@tonic-gate %token	<i>	AND BOR APPEND EQ GE GT LE LT NE IN
88*3ee4fc2aSCody Peter Mello %token	<i>	ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
89*3ee4fc2aSCody Peter Mello %token	<i>	SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
907c478bd9Sstevel@tonic-gate %token	<i>	ADD MINUS MULT DIVIDE MOD
917c478bd9Sstevel@tonic-gate %token	<i>	ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
927c478bd9Sstevel@tonic-gate %token	<i>	PRINT PRINTF SPRINTF
937c478bd9Sstevel@tonic-gate %token	<p>	ELSE INTEST CONDEXPR
947c478bd9Sstevel@tonic-gate %token	<i>	POSTINCR PREINCR POSTDECR PREDECR
95*3ee4fc2aSCody Peter Mello %token	<cp>	VAR IVAR VARNF CALL NUMBER STRING
967c478bd9Sstevel@tonic-gate %token	<s>	REGEXPR
977c478bd9Sstevel@tonic-gate 
98*3ee4fc2aSCody Peter Mello %type	<p>	pas pattern ppattern plist pplist patlist prarg term re
997c478bd9Sstevel@tonic-gate %type	<p>	pa_pat pa_stat pa_stats
1007c478bd9Sstevel@tonic-gate %type	<s>	reg_expr
1017c478bd9Sstevel@tonic-gate %type	<p>	simple_stmt opt_simple_stmt stmt stmtlist
1027c478bd9Sstevel@tonic-gate %type	<p>	var varname funcname varlist
103*3ee4fc2aSCody Peter Mello %type	<p>	for if else while
104*3ee4fc2aSCody Peter Mello %type	<i>	do st
105*3ee4fc2aSCody Peter Mello %type	<i>	pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
1067c478bd9Sstevel@tonic-gate %type	<i>	subop print
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate %right	ASGNOP
1097c478bd9Sstevel@tonic-gate %right	'?'
1107c478bd9Sstevel@tonic-gate %right	':'
1117c478bd9Sstevel@tonic-gate %left	BOR
1127c478bd9Sstevel@tonic-gate %left	AND
1137c478bd9Sstevel@tonic-gate %left	GETLINE
1147c478bd9Sstevel@tonic-gate %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
115*3ee4fc2aSCody Peter Mello %left	ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC
1167c478bd9Sstevel@tonic-gate %left	GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
1177c478bd9Sstevel@tonic-gate %left	PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
1187c478bd9Sstevel@tonic-gate %left	REGEXPR VAR VARNF IVAR WHILE '('
1197c478bd9Sstevel@tonic-gate %left	CAT
1207c478bd9Sstevel@tonic-gate %left	'+' '-'
1217c478bd9Sstevel@tonic-gate %left	'*' '/' '%'
122*3ee4fc2aSCody Peter Mello %left	NOT UMINUS UPLUS
1237c478bd9Sstevel@tonic-gate %right	POWER
1247c478bd9Sstevel@tonic-gate %right	DECR INCR
1257c478bd9Sstevel@tonic-gate %left	INDIRECT
1267c478bd9Sstevel@tonic-gate %token	LASTTOKEN	/* must be last */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate %%
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate program:
1317c478bd9Sstevel@tonic-gate 	  pas	{ if (errorflag==0)
1327c478bd9Sstevel@tonic-gate 			winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
133*3ee4fc2aSCody Peter Mello 	| error	{ yyclearin; bracecheck(); SYNTAX("bailing out"); }
1347c478bd9Sstevel@tonic-gate 	;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate and:
1377c478bd9Sstevel@tonic-gate 	  AND | and NL
1387c478bd9Sstevel@tonic-gate 	;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate bor:
1417c478bd9Sstevel@tonic-gate 	  BOR | bor NL
1427c478bd9Sstevel@tonic-gate 	;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate comma:
1457c478bd9Sstevel@tonic-gate 	  ',' | comma NL
1467c478bd9Sstevel@tonic-gate 	;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate do:
1497c478bd9Sstevel@tonic-gate 	  DO | do NL
1507c478bd9Sstevel@tonic-gate 	;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate else:
1537c478bd9Sstevel@tonic-gate 	  ELSE | else NL
1547c478bd9Sstevel@tonic-gate 	;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate for:
157*3ee4fc2aSCody Peter Mello 	  FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
158*3ee4fc2aSCody Peter Mello 		{ --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
159*3ee4fc2aSCody Peter Mello 	| FOR '(' opt_simple_stmt ';'  ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
160*3ee4fc2aSCody Peter Mello 		{ --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
161*3ee4fc2aSCody Peter Mello 	| FOR '(' varname IN varname rparen {inloop++;} stmt
162*3ee4fc2aSCody Peter Mello 		{ --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
1637c478bd9Sstevel@tonic-gate 	;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate funcname:
1667c478bd9Sstevel@tonic-gate 	  VAR	{ setfname($1); }
1677c478bd9Sstevel@tonic-gate 	| CALL	{ setfname($1); }
1687c478bd9Sstevel@tonic-gate 	;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate if:
1717c478bd9Sstevel@tonic-gate 	  IF '(' pattern rparen		{ $$ = notnull($3); }
1727c478bd9Sstevel@tonic-gate 	;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate lbrace:
1757c478bd9Sstevel@tonic-gate 	  '{' | lbrace NL
1767c478bd9Sstevel@tonic-gate 	;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate nl:
1797c478bd9Sstevel@tonic-gate 	  NL | nl NL
1807c478bd9Sstevel@tonic-gate 	;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate opt_nl:
1837c478bd9Sstevel@tonic-gate 	  /* empty */	{ $$ = 0; }
1847c478bd9Sstevel@tonic-gate 	| nl
1857c478bd9Sstevel@tonic-gate 	;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate opt_pst:
1887c478bd9Sstevel@tonic-gate 	  /* empty */	{ $$ = 0; }
1897c478bd9Sstevel@tonic-gate 	| pst
1907c478bd9Sstevel@tonic-gate 	;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate opt_simple_stmt:
1947c478bd9Sstevel@tonic-gate 	  /* empty */			{ $$ = 0; }
1957c478bd9Sstevel@tonic-gate 	| simple_stmt
1967c478bd9Sstevel@tonic-gate 	;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate pas:
1997c478bd9Sstevel@tonic-gate 	  opt_pst			{ $$ = 0; }
2007c478bd9Sstevel@tonic-gate 	| opt_pst pa_stats opt_pst	{ $$ = $2; }
2017c478bd9Sstevel@tonic-gate 	;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate pa_pat:
2047c478bd9Sstevel@tonic-gate 	  pattern	{ $$ = notnull($1); }
2057c478bd9Sstevel@tonic-gate 	;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate pa_stat:
2087c478bd9Sstevel@tonic-gate 	  pa_pat			{ $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
2097c478bd9Sstevel@tonic-gate 	| pa_pat lbrace stmtlist '}'	{ $$ = stat2(PASTAT, $1, $3); }
210*3ee4fc2aSCody Peter Mello 	| pa_pat ',' opt_nl pa_pat		{ $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); }
211*3ee4fc2aSCody Peter Mello 	| pa_pat ',' opt_nl pa_pat lbrace stmtlist '}'	{ $$ = pa2stat($1, $4, $6); }
2127c478bd9Sstevel@tonic-gate 	| lbrace stmtlist '}'		{ $$ = stat2(PASTAT, NIL, $2); }
2137c478bd9Sstevel@tonic-gate 	| XBEGIN lbrace stmtlist '}'
2147c478bd9Sstevel@tonic-gate 		{ beginloc = linkum(beginloc, $3); $$ = 0; }
2157c478bd9Sstevel@tonic-gate 	| XEND lbrace stmtlist '}'
2167c478bd9Sstevel@tonic-gate 		{ endloc = linkum(endloc, $3); $$ = 0; }
2177c478bd9Sstevel@tonic-gate 	| FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
2187c478bd9Sstevel@tonic-gate 		{ infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
2197c478bd9Sstevel@tonic-gate 	;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate pa_stats:
2227c478bd9Sstevel@tonic-gate 	  pa_stat
2237c478bd9Sstevel@tonic-gate 	| pa_stats opt_pst pa_stat	{ $$ = linkum($1, $3); }
2247c478bd9Sstevel@tonic-gate 	;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate patlist:
2277c478bd9Sstevel@tonic-gate 	  pattern
228*3ee4fc2aSCody Peter Mello 	| patlist comma pattern		{ $$ = linkum($1, $3); }
2297c478bd9Sstevel@tonic-gate 	;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate ppattern:
2327c478bd9Sstevel@tonic-gate 	  var ASGNOP ppattern		{ $$ = op2($2, $1, $3); }
2337c478bd9Sstevel@tonic-gate 	| ppattern '?' ppattern ':' ppattern %prec '?'
234*3ee4fc2aSCody Peter Mello 		{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2357c478bd9Sstevel@tonic-gate 	| ppattern bor ppattern %prec BOR
2367c478bd9Sstevel@tonic-gate 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2377c478bd9Sstevel@tonic-gate 	| ppattern and ppattern %prec AND
2387c478bd9Sstevel@tonic-gate 		{ $$ = op2(AND, notnull($1), notnull($3)); }
2397c478bd9Sstevel@tonic-gate 	| ppattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2407c478bd9Sstevel@tonic-gate 	| ppattern MATCHOP ppattern
2417c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
2427c478bd9Sstevel@tonic-gate 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2437c478bd9Sstevel@tonic-gate 		  else
2447c478bd9Sstevel@tonic-gate 			$$ = op3($2, (Node *)1, $1, $3); }
2457c478bd9Sstevel@tonic-gate 	| ppattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2467c478bd9Sstevel@tonic-gate 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
2477c478bd9Sstevel@tonic-gate 	| ppattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
248*3ee4fc2aSCody Peter Mello 	| re
2497c478bd9Sstevel@tonic-gate 	| term
2507c478bd9Sstevel@tonic-gate 	;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate pattern:
2537c478bd9Sstevel@tonic-gate 	  var ASGNOP pattern		{ $$ = op2($2, $1, $3); }
2547c478bd9Sstevel@tonic-gate 	| pattern '?' pattern ':' pattern %prec '?'
255*3ee4fc2aSCody Peter Mello 		{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2567c478bd9Sstevel@tonic-gate 	| pattern bor pattern %prec BOR
2577c478bd9Sstevel@tonic-gate 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2587c478bd9Sstevel@tonic-gate 	| pattern and pattern %prec AND
2597c478bd9Sstevel@tonic-gate 		{ $$ = op2(AND, notnull($1), notnull($3)); }
2607c478bd9Sstevel@tonic-gate 	| pattern EQ pattern		{ $$ = op2($2, $1, $3); }
2617c478bd9Sstevel@tonic-gate 	| pattern GE pattern		{ $$ = op2($2, $1, $3); }
2627c478bd9Sstevel@tonic-gate 	| pattern GT pattern		{ $$ = op2($2, $1, $3); }
2637c478bd9Sstevel@tonic-gate 	| pattern LE pattern		{ $$ = op2($2, $1, $3); }
2647c478bd9Sstevel@tonic-gate 	| pattern LT pattern		{ $$ = op2($2, $1, $3); }
2657c478bd9Sstevel@tonic-gate 	| pattern NE pattern		{ $$ = op2($2, $1, $3); }
2667c478bd9Sstevel@tonic-gate 	| pattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2677c478bd9Sstevel@tonic-gate 	| pattern MATCHOP pattern
2687c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
2697c478bd9Sstevel@tonic-gate 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2707c478bd9Sstevel@tonic-gate 		  else
2717c478bd9Sstevel@tonic-gate 			$$ = op3($2, (Node *)1, $1, $3); }
2727c478bd9Sstevel@tonic-gate 	| pattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2737c478bd9Sstevel@tonic-gate 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
274*3ee4fc2aSCody Peter Mello 	| pattern '|' GETLINE var	{
275*3ee4fc2aSCody Peter Mello 			if (safe) SYNTAX("cmd | getline is unsafe");
276*3ee4fc2aSCody Peter Mello 			else $$ = op3(GETLINE, $4, itonp($2), $1); }
277*3ee4fc2aSCody Peter Mello 	| pattern '|' GETLINE		{
278*3ee4fc2aSCody Peter Mello 			if (safe) SYNTAX("cmd | getline is unsafe");
279*3ee4fc2aSCody Peter Mello 			else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); }
2807c478bd9Sstevel@tonic-gate 	| pattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
281*3ee4fc2aSCody Peter Mello 	| re
2827c478bd9Sstevel@tonic-gate 	| term
2837c478bd9Sstevel@tonic-gate 	;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate plist:
2867c478bd9Sstevel@tonic-gate 	  pattern comma pattern		{ $$ = linkum($1, $3); }
2877c478bd9Sstevel@tonic-gate 	| plist comma pattern		{ $$ = linkum($1, $3); }
2887c478bd9Sstevel@tonic-gate 	;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate pplist:
2917c478bd9Sstevel@tonic-gate 	  ppattern
2927c478bd9Sstevel@tonic-gate 	| pplist comma ppattern		{ $$ = linkum($1, $3); }
293*3ee4fc2aSCody Peter Mello 	;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate prarg:
2967c478bd9Sstevel@tonic-gate 	  /* empty */			{ $$ = rectonode(); }
2977c478bd9Sstevel@tonic-gate 	| pplist
2987c478bd9Sstevel@tonic-gate 	| '(' plist ')'			{ $$ = $2; }
2997c478bd9Sstevel@tonic-gate 	;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate print:
3027c478bd9Sstevel@tonic-gate 	  PRINT | PRINTF
3037c478bd9Sstevel@tonic-gate 	;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate pst:
3067c478bd9Sstevel@tonic-gate 	  NL | ';' | pst NL | pst ';'
3077c478bd9Sstevel@tonic-gate 	;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate rbrace:
3107c478bd9Sstevel@tonic-gate 	  '}' | rbrace NL
3117c478bd9Sstevel@tonic-gate 	;
3127c478bd9Sstevel@tonic-gate 
313*3ee4fc2aSCody Peter Mello re:
314*3ee4fc2aSCody Peter Mello 	   reg_expr
315*3ee4fc2aSCody Peter Mello 		{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
316*3ee4fc2aSCody Peter Mello 	| NOT re	{ $$ = op1(NOT, notnull($2)); }
317*3ee4fc2aSCody Peter Mello 	;
318*3ee4fc2aSCody Peter Mello 
3197c478bd9Sstevel@tonic-gate reg_expr:
3207c478bd9Sstevel@tonic-gate 	  '/' {startreg();} REGEXPR '/'		{ $$ = $3; }
3217c478bd9Sstevel@tonic-gate 	;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate rparen:
3247c478bd9Sstevel@tonic-gate 	  ')' | rparen NL
3257c478bd9Sstevel@tonic-gate 	;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate simple_stmt:
328*3ee4fc2aSCody Peter Mello 	  print prarg '|' term		{
329*3ee4fc2aSCody Peter Mello 			if (safe) SYNTAX("print | is unsafe");
330*3ee4fc2aSCody Peter Mello 			else $$ = stat3($1, $2, itonp($3), $4); }
331*3ee4fc2aSCody Peter Mello 	| print prarg APPEND term	{
332*3ee4fc2aSCody Peter Mello 			if (safe) SYNTAX("print >> is unsafe");
333*3ee4fc2aSCody Peter Mello 			else $$ = stat3($1, $2, itonp($3), $4); }
334*3ee4fc2aSCody Peter Mello 	| print prarg GT term		{
335*3ee4fc2aSCody Peter Mello 			if (safe) SYNTAX("print > is unsafe");
336*3ee4fc2aSCody Peter Mello 			else $$ = stat3($1, $2, itonp($3), $4); }
3377c478bd9Sstevel@tonic-gate 	| print prarg			{ $$ = stat3($1, $2, NIL, NIL); }
3387c478bd9Sstevel@tonic-gate 	| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
339*3ee4fc2aSCody Peter Mello 	| DELETE varname		{ $$ = stat2(DELETE, makearr($2), 0); }
3407c478bd9Sstevel@tonic-gate 	| pattern			{ $$ = exptostat($1); }
341*3ee4fc2aSCody Peter Mello 	| error				{ yyclearin; SYNTAX("illegal statement"); }
3427c478bd9Sstevel@tonic-gate 	;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate st:
345*3ee4fc2aSCody Peter Mello 	  nl
346*3ee4fc2aSCody Peter Mello 	| ';' opt_nl
3477c478bd9Sstevel@tonic-gate 	;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate stmt:
350*3ee4fc2aSCody Peter Mello 	  BREAK st		{ if (!inloop) SYNTAX("break illegal outside of loops");
351*3ee4fc2aSCody Peter Mello 				  $$ = stat1(BREAK, NIL); }
352*3ee4fc2aSCody Peter Mello 	| CONTINUE st		{  if (!inloop) SYNTAX("continue illegal outside of loops");
353*3ee4fc2aSCody Peter Mello 				  $$ = stat1(CONTINUE, NIL); }
354*3ee4fc2aSCody Peter Mello 	| do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
355*3ee4fc2aSCody Peter Mello 		{ $$ = stat2(DO, $3, notnull($7)); }
3567c478bd9Sstevel@tonic-gate 	| EXIT pattern st	{ $$ = stat1(EXIT, $2); }
3577c478bd9Sstevel@tonic-gate 	| EXIT st		{ $$ = stat1(EXIT, NIL); }
3587c478bd9Sstevel@tonic-gate 	| for
3597c478bd9Sstevel@tonic-gate 	| if stmt else stmt	{ $$ = stat3(IF, $1, $2, $4); }
3607c478bd9Sstevel@tonic-gate 	| if stmt		{ $$ = stat3(IF, $1, $2, NIL); }
3617c478bd9Sstevel@tonic-gate 	| lbrace stmtlist rbrace { $$ = $2; }
3627c478bd9Sstevel@tonic-gate 	| NEXT st	{ if (infunc)
363*3ee4fc2aSCody Peter Mello 				SYNTAX("next is illegal inside a function");
3647c478bd9Sstevel@tonic-gate 			  $$ = stat1(NEXT, NIL); }
365*3ee4fc2aSCody Peter Mello 	| NEXTFILE st	{ if (infunc)
366*3ee4fc2aSCody Peter Mello 				SYNTAX("nextfile is illegal inside a function");
367*3ee4fc2aSCody Peter Mello 			  $$ = stat1(NEXTFILE, NIL); }
3687c478bd9Sstevel@tonic-gate 	| RETURN pattern st	{ $$ = stat1(RETURN, $2); }
3697c478bd9Sstevel@tonic-gate 	| RETURN st		{ $$ = stat1(RETURN, NIL); }
3707c478bd9Sstevel@tonic-gate 	| simple_stmt st
371*3ee4fc2aSCody Peter Mello 	| while {inloop++;} stmt	{ --inloop; $$ = stat2(WHILE, $1, $3); }
3727c478bd9Sstevel@tonic-gate 	| ';' opt_nl		{ $$ = 0; }
3737c478bd9Sstevel@tonic-gate 	;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate stmtlist:
3767c478bd9Sstevel@tonic-gate 	  stmt
3777c478bd9Sstevel@tonic-gate 	| stmtlist stmt		{ $$ = linkum($1, $2); }
3787c478bd9Sstevel@tonic-gate 	;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate subop:
3817c478bd9Sstevel@tonic-gate 	  SUB | GSUB
3827c478bd9Sstevel@tonic-gate 	;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate term:
385*3ee4fc2aSCody Peter Mello 	  term '/' ASGNOP term		{ $$ = op2(DIVEQ, $1, $4); }
386*3ee4fc2aSCody Peter Mello 	| term '+' term			{ $$ = op2(ADD, $1, $3); }
3877c478bd9Sstevel@tonic-gate 	| term '-' term			{ $$ = op2(MINUS, $1, $3); }
3887c478bd9Sstevel@tonic-gate 	| term '*' term			{ $$ = op2(MULT, $1, $3); }
3897c478bd9Sstevel@tonic-gate 	| term '/' term			{ $$ = op2(DIVIDE, $1, $3); }
3907c478bd9Sstevel@tonic-gate 	| term '%' term			{ $$ = op2(MOD, $1, $3); }
3917c478bd9Sstevel@tonic-gate 	| term POWER term		{ $$ = op2(POWER, $1, $3); }
3927c478bd9Sstevel@tonic-gate 	| '-' term %prec UMINUS		{ $$ = op1(UMINUS, $2); }
393*3ee4fc2aSCody Peter Mello 	| '+' term %prec UMINUS		{ $$ = op1(UPLUS, $2); }
394*3ee4fc2aSCody Peter Mello 	| NOT term %prec UMINUS		{ $$ = op1(NOT, notnull($2)); }
395*3ee4fc2aSCody Peter Mello 	| BLTIN '(' ')'			{ $$ = op2(BLTIN, itonp($1), rectonode()); }
396*3ee4fc2aSCody Peter Mello 	| BLTIN '(' patlist ')'		{ $$ = op2(BLTIN, itonp($1), $3); }
397*3ee4fc2aSCody Peter Mello 	| BLTIN				{ $$ = op2(BLTIN, itonp($1), rectonode()); }
398*3ee4fc2aSCody Peter Mello 	| CALL '(' ')'			{ $$ = op2(CALL, celltonode($1,CVAR), NIL); }
399*3ee4fc2aSCody Peter Mello 	| CALL '(' patlist ')'		{ $$ = op2(CALL, celltonode($1,CVAR), $3); }
400*3ee4fc2aSCody Peter Mello 	| CLOSE term			{ $$ = op1(CLOSE, $2); }
4017c478bd9Sstevel@tonic-gate 	| DECR var			{ $$ = op1(PREDECR, $2); }
4027c478bd9Sstevel@tonic-gate 	| INCR var			{ $$ = op1(PREINCR, $2); }
4037c478bd9Sstevel@tonic-gate 	| var DECR			{ $$ = op1(POSTDECR, $1); }
4047c478bd9Sstevel@tonic-gate 	| var INCR			{ $$ = op1(POSTINCR, $1); }
405*3ee4fc2aSCody Peter Mello 	| GETLINE var LT term		{ $$ = op3(GETLINE, $2, itonp($3), $4); }
406*3ee4fc2aSCody Peter Mello 	| GETLINE LT term		{ $$ = op3(GETLINE, NIL, itonp($2), $3); }
4077c478bd9Sstevel@tonic-gate 	| GETLINE var			{ $$ = op3(GETLINE, $2, NIL, NIL); }
4087c478bd9Sstevel@tonic-gate 	| GETLINE			{ $$ = op3(GETLINE, NIL, NIL, NIL); }
4097c478bd9Sstevel@tonic-gate 	| INDEX '(' pattern comma pattern ')'
4107c478bd9Sstevel@tonic-gate 		{ $$ = op2(INDEX, $3, $5); }
4117c478bd9Sstevel@tonic-gate 	| INDEX '(' pattern comma reg_expr ')'
412*3ee4fc2aSCody Peter Mello 		{ SYNTAX("index() doesn't permit regular expressions");
4137c478bd9Sstevel@tonic-gate 		  $$ = op2(INDEX, $3, (Node*)$5); }
4147c478bd9Sstevel@tonic-gate 	| '(' pattern ')'		{ $$ = $2; }
4157c478bd9Sstevel@tonic-gate 	| MATCHFCN '(' pattern comma reg_expr ')'
4167c478bd9Sstevel@tonic-gate 		{ $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
4177c478bd9Sstevel@tonic-gate 	| MATCHFCN '(' pattern comma pattern ')'
4187c478bd9Sstevel@tonic-gate 		{ if (constnode($5))
4197c478bd9Sstevel@tonic-gate 			$$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
4207c478bd9Sstevel@tonic-gate 		  else
4217c478bd9Sstevel@tonic-gate 			$$ = op3(MATCHFCN, (Node *)1, $3, $5); }
422*3ee4fc2aSCody Peter Mello 	| NUMBER			{ $$ = celltonode($1, CCON); }
4237c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname comma pattern ')'     /* string */
4247c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
4257c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname comma reg_expr ')'    /* const /regexp/ */
4267c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
4277c478bd9Sstevel@tonic-gate 	| SPLIT '(' pattern comma varname ')'
4287c478bd9Sstevel@tonic-gate 		{ $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); }  /* default */
4297c478bd9Sstevel@tonic-gate 	| SPRINTF '(' patlist ')'	{ $$ = op1($1, $3); }
430*3ee4fc2aSCody Peter Mello 	| STRING			{ $$ = celltonode($1, CCON); }
4317c478bd9Sstevel@tonic-gate 	| subop '(' reg_expr comma pattern ')'
4327c478bd9Sstevel@tonic-gate 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
4337c478bd9Sstevel@tonic-gate 	| subop '(' pattern comma pattern ')'
4347c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
4357c478bd9Sstevel@tonic-gate 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
4367c478bd9Sstevel@tonic-gate 		  else
4377c478bd9Sstevel@tonic-gate 			$$ = op4($1, (Node *)1, $3, $5, rectonode()); }
4387c478bd9Sstevel@tonic-gate 	| subop '(' reg_expr comma pattern comma var ')'
4397c478bd9Sstevel@tonic-gate 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
4407c478bd9Sstevel@tonic-gate 	| subop '(' pattern comma pattern comma var ')'
4417c478bd9Sstevel@tonic-gate 		{ if (constnode($3))
4427c478bd9Sstevel@tonic-gate 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
4437c478bd9Sstevel@tonic-gate 		  else
4447c478bd9Sstevel@tonic-gate 			$$ = op4($1, (Node *)1, $3, $5, $7); }
4457c478bd9Sstevel@tonic-gate 	| SUBSTR '(' pattern comma pattern comma pattern ')'
4467c478bd9Sstevel@tonic-gate 		{ $$ = op3(SUBSTR, $3, $5, $7); }
4477c478bd9Sstevel@tonic-gate 	| SUBSTR '(' pattern comma pattern ')'
4487c478bd9Sstevel@tonic-gate 		{ $$ = op3(SUBSTR, $3, $5, NIL); }
4497c478bd9Sstevel@tonic-gate 	| var
4507c478bd9Sstevel@tonic-gate 	;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate var:
4537c478bd9Sstevel@tonic-gate 	  varname
4547c478bd9Sstevel@tonic-gate 	| varname '[' patlist ']'	{ $$ = op2(ARRAY, makearr($1), $3); }
455*3ee4fc2aSCody Peter Mello 	| IVAR				{ $$ = op1(INDIRECT, celltonode($1, CVAR)); }
456*3ee4fc2aSCody Peter Mello 	| INDIRECT term			{ $$ = op1(INDIRECT, $2); }
457*3ee4fc2aSCody Peter Mello 	;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate varlist:
4607c478bd9Sstevel@tonic-gate 	  /* nothing */		{ arglist = $$ = 0; }
461*3ee4fc2aSCody Peter Mello 	| VAR			{ arglist = $$ = celltonode($1,CVAR); }
462*3ee4fc2aSCody Peter Mello 	| varlist comma VAR	{
463*3ee4fc2aSCody Peter Mello 			checkdup($1, $3);
464*3ee4fc2aSCody Peter Mello 			arglist = $$ = linkum($1,celltonode($3,CVAR)); }
4657c478bd9Sstevel@tonic-gate 	;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate varname:
468*3ee4fc2aSCody Peter Mello 	  VAR			{ $$ = celltonode($1, CVAR); }
469*3ee4fc2aSCody Peter Mello 	| ARG			{ $$ = op1(ARG, itonp($1)); }
4707c478bd9Sstevel@tonic-gate 	| VARNF			{ $$ = op1(VARNF, (Node *) $1); }
4717c478bd9Sstevel@tonic-gate 	;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate while:
4757c478bd9Sstevel@tonic-gate 	  WHILE '(' pattern rparen	{ $$ = notnull($3); }
4767c478bd9Sstevel@tonic-gate 	;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate %%
4797c478bd9Sstevel@tonic-gate 
4801ee2e5faSnakanon static void
4811ee2e5faSnakanon setfname(Cell *p)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	if (isarr(p))
484*3ee4fc2aSCody Peter Mello 		SYNTAX("%s is an array, not a function", p->nval);
485*3ee4fc2aSCody Peter Mello 	else if (isfcn(p))
486*3ee4fc2aSCody Peter Mello 		SYNTAX("you can't define function %s more than once", p->nval);
4877c478bd9Sstevel@tonic-gate 	curfname = p->nval;
488*3ee4fc2aSCody Peter Mello 	p->tval |= FCN;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4911ee2e5faSnakanon static int
4921ee2e5faSnakanon constnode(Node *p)
4937c478bd9Sstevel@tonic-gate {
494*3ee4fc2aSCody Peter Mello 	return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
497*3ee4fc2aSCody Peter Mello static char *
4981ee2e5faSnakanon strnode(Node *p)
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate 	return ((Cell *)(p->narg[0]))->sval;
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate 
5031ee2e5faSnakanon static Node *
5041ee2e5faSnakanon notnull(Node *n)
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate 	switch (n->nobj) {
5077c478bd9Sstevel@tonic-gate 	case LE: case LT: case EQ: case NE: case GT: case GE:
5087c478bd9Sstevel@tonic-gate 	case BOR: case AND: case NOT:
5097c478bd9Sstevel@tonic-gate 		return n;
5107c478bd9Sstevel@tonic-gate 	default:
5117c478bd9Sstevel@tonic-gate 		return op2(NE, n, nullnode);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate }
514*3ee4fc2aSCody Peter Mello 
515*3ee4fc2aSCody Peter Mello void
516*3ee4fc2aSCody Peter Mello checkdup(Node *vl, Cell *cp)	/* check if name already in list */
517*3ee4fc2aSCody Peter Mello {
518*3ee4fc2aSCody Peter Mello 	char *s = cp->nval;
519*3ee4fc2aSCody Peter Mello 	for (; vl; vl = vl->nnext) {
520*3ee4fc2aSCody Peter Mello 		if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) {
521*3ee4fc2aSCody Peter Mello 			SYNTAX("duplicate argument %s", s);
522*3ee4fc2aSCody Peter Mello 			break;
523*3ee4fc2aSCody Peter Mello 		}
524*3ee4fc2aSCody Peter Mello 	}
525*3ee4fc2aSCody Peter Mello }
526