xref: /dragonfly/contrib/awk/awkgram.y (revision ed569bc2)
14b588458SPeter Avalos /****************************************************************
24b588458SPeter Avalos Copyright (C) Lucent Technologies 1997
34b588458SPeter Avalos All Rights Reserved
44b588458SPeter Avalos 
54b588458SPeter Avalos Permission to use, copy, modify, and distribute this software and
64b588458SPeter Avalos its documentation for any purpose and without fee is hereby
74b588458SPeter Avalos granted, provided that the above copyright notice appear in all
84b588458SPeter Avalos copies and that both that the copyright notice and this
94b588458SPeter Avalos permission notice and warranty disclaimer appear in supporting
104b588458SPeter Avalos documentation, and that the name Lucent Technologies or any of
114b588458SPeter Avalos its entities not be used in advertising or publicity pertaining
124b588458SPeter Avalos to distribution of the software without specific, written prior
134b588458SPeter Avalos permission.
144b588458SPeter Avalos 
154b588458SPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
164b588458SPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
174b588458SPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
184b588458SPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
194b588458SPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
204b588458SPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
214b588458SPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
224b588458SPeter Avalos THIS SOFTWARE.
234b588458SPeter Avalos ****************************************************************/
244b588458SPeter Avalos 
254b588458SPeter Avalos %{
264b588458SPeter Avalos #include <stdio.h>
274b588458SPeter Avalos #include <string.h>
284b588458SPeter Avalos #include "awk.h"
294b588458SPeter Avalos 
304b588458SPeter Avalos void checkdup(Node *list, Cell *item);
yywrap(void)314b588458SPeter Avalos int yywrap(void) { return(1); }
324b588458SPeter Avalos 
334b588458SPeter Avalos Node	*beginloc = 0;
344b588458SPeter Avalos Node	*endloc = 0;
351d48fce0SDaniel Fojt bool	infunc	= false;	/* = true if in arglist or body of func */
361d48fce0SDaniel Fojt int	inloop	= 0;	/* >= 1 if in while, for, do; can't be bool, since loops can next */
374b588458SPeter Avalos char	*curfname = 0;	/* current function name */
384b588458SPeter Avalos Node	*arglist = 0;	/* list of args for current function */
394b588458SPeter Avalos %}
404b588458SPeter Avalos 
414b588458SPeter Avalos %union {
424b588458SPeter Avalos 	Node	*p;
434b588458SPeter Avalos 	Cell	*cp;
444b588458SPeter Avalos 	int	i;
454b588458SPeter Avalos 	char	*s;
464b588458SPeter Avalos }
474b588458SPeter Avalos 
484b588458SPeter Avalos %token	<i>	FIRSTTOKEN	/* must be first */
494b588458SPeter Avalos %token	<p>	PROGRAM PASTAT PASTAT2 XBEGIN XEND
504b588458SPeter Avalos %token	<i>	NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
514b588458SPeter Avalos %token	<i>	ARRAY
524b588458SPeter Avalos %token	<i>	MATCH NOTMATCH MATCHOP
531d48fce0SDaniel Fojt %token	<i>	FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE ZERO
544b588458SPeter Avalos %token	<i>	AND BOR APPEND EQ GE GT LE LT NE IN
554b588458SPeter Avalos %token	<i>	ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
564b588458SPeter Avalos %token	<i>	SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
574b588458SPeter Avalos %token	<i>	ADD MINUS MULT DIVIDE MOD
584b588458SPeter Avalos %token	<i>	ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
594b588458SPeter Avalos %token	<i>	PRINT PRINTF SPRINTF
604b588458SPeter Avalos %token	<p>	ELSE INTEST CONDEXPR
614b588458SPeter Avalos %token	<i>	POSTINCR PREINCR POSTDECR PREDECR
624b588458SPeter Avalos %token	<cp>	VAR IVAR VARNF CALL NUMBER STRING
634b588458SPeter Avalos %token	<s>	REGEXPR
644b588458SPeter Avalos 
654b588458SPeter Avalos %type	<p>	pas pattern ppattern plist pplist patlist prarg term re
664b588458SPeter Avalos %type	<p>	pa_pat pa_stat pa_stats
674b588458SPeter Avalos %type	<s>	reg_expr
684b588458SPeter Avalos %type	<p>	simple_stmt opt_simple_stmt stmt stmtlist
694b588458SPeter Avalos %type	<p>	var varname funcname varlist
704b588458SPeter Avalos %type	<p>	for if else while
714b588458SPeter Avalos %type	<i>	do st
724b588458SPeter Avalos %type	<i>	pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
734b588458SPeter Avalos %type	<i>	subop print
741d48fce0SDaniel Fojt %type	<cp>	string
754b588458SPeter Avalos 
764b588458SPeter Avalos %right	ASGNOP
774b588458SPeter Avalos %right	'?'
784b588458SPeter Avalos %right	':'
794b588458SPeter Avalos %left	BOR
804b588458SPeter Avalos %left	AND
814b588458SPeter Avalos %left	GETLINE
824b588458SPeter Avalos %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
834b588458SPeter Avalos %left	ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC
844b588458SPeter Avalos %left	GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
854b588458SPeter Avalos %left	PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
864b588458SPeter Avalos %left	REGEXPR VAR VARNF IVAR WHILE '('
874b588458SPeter Avalos %left	CAT
884b588458SPeter Avalos %left	'+' '-'
894b588458SPeter Avalos %left	'*' '/' '%'
901d48fce0SDaniel Fojt %left	NOT UMINUS UPLUS
914b588458SPeter Avalos %right	POWER
924b588458SPeter Avalos %right	DECR INCR
934b588458SPeter Avalos %left	INDIRECT
944b588458SPeter Avalos %token	LASTTOKEN	/* must be last */
954b588458SPeter Avalos 
964b588458SPeter Avalos %%
974b588458SPeter Avalos 
984b588458SPeter Avalos program:
994b588458SPeter Avalos 	  pas	{ if (errorflag==0)
1004b588458SPeter Avalos 			winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
1014b588458SPeter Avalos 	| error	{ yyclearin; bracecheck(); SYNTAX("bailing out"); }
1024b588458SPeter Avalos 	;
1034b588458SPeter Avalos 
1044b588458SPeter Avalos and:
1054b588458SPeter Avalos 	  AND | and NL
1064b588458SPeter Avalos 	;
1074b588458SPeter Avalos 
1084b588458SPeter Avalos bor:
1094b588458SPeter Avalos 	  BOR | bor NL
1104b588458SPeter Avalos 	;
1114b588458SPeter Avalos 
1124b588458SPeter Avalos comma:
1134b588458SPeter Avalos 	  ',' | comma NL
1144b588458SPeter Avalos 	;
1154b588458SPeter Avalos 
1164b588458SPeter Avalos do:
1174b588458SPeter Avalos 	  DO | do NL
1184b588458SPeter Avalos 	;
1194b588458SPeter Avalos 
1204b588458SPeter Avalos else:
1214b588458SPeter Avalos 	  ELSE | else NL
1224b588458SPeter Avalos 	;
1234b588458SPeter Avalos 
1244b588458SPeter Avalos for:
1254b588458SPeter Avalos 	  FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
1264b588458SPeter Avalos 		{ --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
1274b588458SPeter Avalos 	| FOR '(' opt_simple_stmt ';'  ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
1284b588458SPeter Avalos 		{ --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
1294b588458SPeter Avalos 	| FOR '(' varname IN varname rparen {inloop++;} stmt
1304b588458SPeter Avalos 		{ --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
1314b588458SPeter Avalos 	;
1324b588458SPeter Avalos 
1334b588458SPeter Avalos funcname:
1344b588458SPeter Avalos 	  VAR	{ setfname($1); }
1354b588458SPeter Avalos 	| CALL	{ setfname($1); }
1364b588458SPeter Avalos 	;
1374b588458SPeter Avalos 
1384b588458SPeter Avalos if:
1394b588458SPeter Avalos 	  IF '(' pattern rparen		{ $$ = notnull($3); }
1404b588458SPeter Avalos 	;
1414b588458SPeter Avalos 
1424b588458SPeter Avalos lbrace:
1434b588458SPeter Avalos 	  '{' | lbrace NL
1444b588458SPeter Avalos 	;
1454b588458SPeter Avalos 
1464b588458SPeter Avalos nl:
1474b588458SPeter Avalos 	  NL | nl NL
1484b588458SPeter Avalos 	;
1494b588458SPeter Avalos 
1504b588458SPeter Avalos opt_nl:
1514b588458SPeter Avalos 	  /* empty */	{ $$ = 0; }
1524b588458SPeter Avalos 	| nl
1534b588458SPeter Avalos 	;
1544b588458SPeter Avalos 
1554b588458SPeter Avalos opt_pst:
1564b588458SPeter Avalos 	  /* empty */	{ $$ = 0; }
1574b588458SPeter Avalos 	| pst
1584b588458SPeter Avalos 	;
1594b588458SPeter Avalos 
1604b588458SPeter Avalos 
1614b588458SPeter Avalos opt_simple_stmt:
1624b588458SPeter Avalos 	  /* empty */			{ $$ = 0; }
1634b588458SPeter Avalos 	| simple_stmt
1644b588458SPeter Avalos 	;
1654b588458SPeter Avalos 
1664b588458SPeter Avalos pas:
1674b588458SPeter Avalos 	  opt_pst			{ $$ = 0; }
1684b588458SPeter Avalos 	| opt_pst pa_stats opt_pst	{ $$ = $2; }
1694b588458SPeter Avalos 	;
1704b588458SPeter Avalos 
1714b588458SPeter Avalos pa_pat:
1724b588458SPeter Avalos 	  pattern	{ $$ = notnull($1); }
1734b588458SPeter Avalos 	;
1744b588458SPeter Avalos 
1754b588458SPeter Avalos pa_stat:
1764b588458SPeter Avalos 	  pa_pat			{ $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
1774b588458SPeter Avalos 	| pa_pat lbrace stmtlist '}'	{ $$ = stat2(PASTAT, $1, $3); }
178b12bae18SSascha Wildner 	| pa_pat ',' opt_nl pa_pat		{ $$ = pa2stat($1, $4, stat2(PRINT, rectonode(), NIL)); }
179b12bae18SSascha Wildner 	| pa_pat ',' opt_nl pa_pat lbrace stmtlist '}'	{ $$ = pa2stat($1, $4, $6); }
1804b588458SPeter Avalos 	| lbrace stmtlist '}'		{ $$ = stat2(PASTAT, NIL, $2); }
1814b588458SPeter Avalos 	| XBEGIN lbrace stmtlist '}'
1824b588458SPeter Avalos 		{ beginloc = linkum(beginloc, $3); $$ = 0; }
1834b588458SPeter Avalos 	| XEND lbrace stmtlist '}'
1844b588458SPeter Avalos 		{ endloc = linkum(endloc, $3); $$ = 0; }
1851d48fce0SDaniel Fojt 	| FUNC funcname '(' varlist rparen {infunc = true;} lbrace stmtlist '}'
1861d48fce0SDaniel Fojt 		{ infunc = false; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
1874b588458SPeter Avalos 	;
1884b588458SPeter Avalos 
1894b588458SPeter Avalos pa_stats:
1904b588458SPeter Avalos 	  pa_stat
1914b588458SPeter Avalos 	| pa_stats opt_pst pa_stat	{ $$ = linkum($1, $3); }
1924b588458SPeter Avalos 	;
1934b588458SPeter Avalos 
1944b588458SPeter Avalos patlist:
1954b588458SPeter Avalos 	  pattern
1964b588458SPeter Avalos 	| patlist comma pattern		{ $$ = linkum($1, $3); }
1974b588458SPeter Avalos 	;
1984b588458SPeter Avalos 
1994b588458SPeter Avalos ppattern:
2004b588458SPeter Avalos 	  var ASGNOP ppattern		{ $$ = op2($2, $1, $3); }
2014b588458SPeter Avalos 	| ppattern '?' ppattern ':' ppattern %prec '?'
2024b588458SPeter Avalos 	 	{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2034b588458SPeter Avalos 	| ppattern bor ppattern %prec BOR
2044b588458SPeter Avalos 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2054b588458SPeter Avalos 	| ppattern and ppattern %prec AND
2064b588458SPeter Avalos 		{ $$ = op2(AND, notnull($1), notnull($3)); }
207*ed569bc2SAaron LI 	| ppattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); free($3); }
2084b588458SPeter Avalos 	| ppattern MATCHOP ppattern
20948f09a05SAntonio Huete Jimenez 		{ if (constnode($3)) {
2104b588458SPeter Avalos 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
21148f09a05SAntonio Huete Jimenez 			free($3);
21248f09a05SAntonio Huete Jimenez 		  } else
2134b588458SPeter Avalos 			$$ = op3($2, (Node *)1, $1, $3); }
2144b588458SPeter Avalos 	| ppattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2154b588458SPeter Avalos 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
2164b588458SPeter Avalos 	| ppattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
2174b588458SPeter Avalos 	| re
2184b588458SPeter Avalos 	| term
2194b588458SPeter Avalos 	;
2204b588458SPeter Avalos 
2214b588458SPeter Avalos pattern:
2224b588458SPeter Avalos 	  var ASGNOP pattern		{ $$ = op2($2, $1, $3); }
2234b588458SPeter Avalos 	| pattern '?' pattern ':' pattern %prec '?'
2244b588458SPeter Avalos 	 	{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2254b588458SPeter Avalos 	| pattern bor pattern %prec BOR
2264b588458SPeter Avalos 		{ $$ = op2(BOR, notnull($1), notnull($3)); }
2274b588458SPeter Avalos 	| pattern and pattern %prec AND
2284b588458SPeter Avalos 		{ $$ = op2(AND, notnull($1), notnull($3)); }
2294b588458SPeter Avalos 	| pattern EQ pattern		{ $$ = op2($2, $1, $3); }
2304b588458SPeter Avalos 	| pattern GE pattern		{ $$ = op2($2, $1, $3); }
2314b588458SPeter Avalos 	| pattern GT pattern		{ $$ = op2($2, $1, $3); }
2324b588458SPeter Avalos 	| pattern LE pattern		{ $$ = op2($2, $1, $3); }
2334b588458SPeter Avalos 	| pattern LT pattern		{ $$ = op2($2, $1, $3); }
2344b588458SPeter Avalos 	| pattern NE pattern		{ $$ = op2($2, $1, $3); }
235*ed569bc2SAaron LI 	| pattern MATCHOP reg_expr	{ $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); free($3); }
2364b588458SPeter Avalos 	| pattern MATCHOP pattern
23748f09a05SAntonio Huete Jimenez 		{ if (constnode($3)) {
2384b588458SPeter Avalos 			$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
23948f09a05SAntonio Huete Jimenez 			free($3);
24048f09a05SAntonio Huete Jimenez 		  } else
2414b588458SPeter Avalos 			$$ = op3($2, (Node *)1, $1, $3); }
2424b588458SPeter Avalos 	| pattern IN varname		{ $$ = op2(INTEST, $1, makearr($3)); }
2434b588458SPeter Avalos 	| '(' plist ')' IN varname	{ $$ = op2(INTEST, $2, makearr($5)); }
2444b588458SPeter Avalos 	| pattern '|' GETLINE var	{
2454b588458SPeter Avalos 			if (safe) SYNTAX("cmd | getline is unsafe");
2464b588458SPeter Avalos 			else $$ = op3(GETLINE, $4, itonp($2), $1); }
2474b588458SPeter Avalos 	| pattern '|' GETLINE		{
2484b588458SPeter Avalos 			if (safe) SYNTAX("cmd | getline is unsafe");
2494b588458SPeter Avalos 			else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); }
2504b588458SPeter Avalos 	| pattern term %prec CAT	{ $$ = op2(CAT, $1, $2); }
2514b588458SPeter Avalos 	| re
2524b588458SPeter Avalos 	| term
2534b588458SPeter Avalos 	;
2544b588458SPeter Avalos 
2554b588458SPeter Avalos plist:
2564b588458SPeter Avalos 	  pattern comma pattern		{ $$ = linkum($1, $3); }
2574b588458SPeter Avalos 	| plist comma pattern		{ $$ = linkum($1, $3); }
2584b588458SPeter Avalos 	;
2594b588458SPeter Avalos 
2604b588458SPeter Avalos pplist:
2614b588458SPeter Avalos 	  ppattern
2624b588458SPeter Avalos 	| pplist comma ppattern		{ $$ = linkum($1, $3); }
2634b588458SPeter Avalos 	;
2644b588458SPeter Avalos 
2654b588458SPeter Avalos prarg:
2664b588458SPeter Avalos 	  /* empty */			{ $$ = rectonode(); }
2674b588458SPeter Avalos 	| pplist
2684b588458SPeter Avalos 	| '(' plist ')'			{ $$ = $2; }
2694b588458SPeter Avalos 	;
2704b588458SPeter Avalos 
2714b588458SPeter Avalos print:
2724b588458SPeter Avalos 	  PRINT | PRINTF
2734b588458SPeter Avalos 	;
2744b588458SPeter Avalos 
2754b588458SPeter Avalos pst:
2764b588458SPeter Avalos 	  NL | ';' | pst NL | pst ';'
2774b588458SPeter Avalos 	;
2784b588458SPeter Avalos 
2794b588458SPeter Avalos rbrace:
2804b588458SPeter Avalos 	  '}' | rbrace NL
2814b588458SPeter Avalos 	;
2824b588458SPeter Avalos 
2834b588458SPeter Avalos re:
2844b588458SPeter Avalos 	   reg_expr
285*ed569bc2SAaron LI 		{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); free($1); }
2864b588458SPeter Avalos 	| NOT re	{ $$ = op1(NOT, notnull($2)); }
2874b588458SPeter Avalos 	;
2884b588458SPeter Avalos 
2894b588458SPeter Avalos reg_expr:
2904b588458SPeter Avalos 	  '/' {startreg();} REGEXPR '/'		{ $$ = $3; }
2914b588458SPeter Avalos 	;
2924b588458SPeter Avalos 
2934b588458SPeter Avalos rparen:
2944b588458SPeter Avalos 	  ')' | rparen NL
2954b588458SPeter Avalos 	;
2964b588458SPeter Avalos 
2974b588458SPeter Avalos simple_stmt:
2984b588458SPeter Avalos 	  print prarg '|' term		{
2994b588458SPeter Avalos 			if (safe) SYNTAX("print | is unsafe");
3004b588458SPeter Avalos 			else $$ = stat3($1, $2, itonp($3), $4); }
3014b588458SPeter Avalos 	| print prarg APPEND term	{
3024b588458SPeter Avalos 			if (safe) SYNTAX("print >> is unsafe");
3034b588458SPeter Avalos 			else $$ = stat3($1, $2, itonp($3), $4); }
3044b588458SPeter Avalos 	| print prarg GT term		{
3054b588458SPeter Avalos 			if (safe) SYNTAX("print > is unsafe");
3064b588458SPeter Avalos 			else $$ = stat3($1, $2, itonp($3), $4); }
3074b588458SPeter Avalos 	| print prarg			{ $$ = stat3($1, $2, NIL, NIL); }
3084b588458SPeter Avalos 	| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
3094b588458SPeter Avalos 	| DELETE varname		 { $$ = stat2(DELETE, makearr($2), 0); }
3104b588458SPeter Avalos 	| pattern			{ $$ = exptostat($1); }
3114b588458SPeter Avalos 	| error				{ yyclearin; SYNTAX("illegal statement"); }
3124b588458SPeter Avalos 	;
3134b588458SPeter Avalos 
3144b588458SPeter Avalos st:
3154b588458SPeter Avalos 	  nl
3164b588458SPeter Avalos 	| ';' opt_nl
3174b588458SPeter Avalos 	;
3184b588458SPeter Avalos 
3194b588458SPeter Avalos stmt:
3204b588458SPeter Avalos 	  BREAK st		{ if (!inloop) SYNTAX("break illegal outside of loops");
3214b588458SPeter Avalos 				  $$ = stat1(BREAK, NIL); }
3224b588458SPeter Avalos 	| CONTINUE st		{  if (!inloop) SYNTAX("continue illegal outside of loops");
3234b588458SPeter Avalos 				  $$ = stat1(CONTINUE, NIL); }
3244b588458SPeter Avalos 	| do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
3254b588458SPeter Avalos 		{ $$ = stat2(DO, $3, notnull($7)); }
3264b588458SPeter Avalos 	| EXIT pattern st	{ $$ = stat1(EXIT, $2); }
3274b588458SPeter Avalos 	| EXIT st		{ $$ = stat1(EXIT, NIL); }
3284b588458SPeter Avalos 	| for
3294b588458SPeter Avalos 	| if stmt else stmt	{ $$ = stat3(IF, $1, $2, $4); }
3304b588458SPeter Avalos 	| if stmt		{ $$ = stat3(IF, $1, $2, NIL); }
3314b588458SPeter Avalos 	| lbrace stmtlist rbrace { $$ = $2; }
3324b588458SPeter Avalos 	| NEXT st	{ if (infunc)
3334b588458SPeter Avalos 				SYNTAX("next is illegal inside a function");
3344b588458SPeter Avalos 			  $$ = stat1(NEXT, NIL); }
3354b588458SPeter Avalos 	| NEXTFILE st	{ if (infunc)
3364b588458SPeter Avalos 				SYNTAX("nextfile is illegal inside a function");
3374b588458SPeter Avalos 			  $$ = stat1(NEXTFILE, NIL); }
3384b588458SPeter Avalos 	| RETURN pattern st	{ $$ = stat1(RETURN, $2); }
3394b588458SPeter Avalos 	| RETURN st		{ $$ = stat1(RETURN, NIL); }
3404b588458SPeter Avalos 	| simple_stmt st
3414b588458SPeter Avalos 	| while {inloop++;} stmt	{ --inloop; $$ = stat2(WHILE, $1, $3); }
3424b588458SPeter Avalos 	| ';' opt_nl		{ $$ = 0; }
3434b588458SPeter Avalos 	;
3444b588458SPeter Avalos 
3454b588458SPeter Avalos stmtlist:
3464b588458SPeter Avalos 	  stmt
3474b588458SPeter Avalos 	| stmtlist stmt		{ $$ = linkum($1, $2); }
3484b588458SPeter Avalos 	;
3494b588458SPeter Avalos 
3504b588458SPeter Avalos subop:
3514b588458SPeter Avalos 	  SUB | GSUB
3524b588458SPeter Avalos 	;
3534b588458SPeter Avalos 
3541d48fce0SDaniel Fojt string:
3551d48fce0SDaniel Fojt 	  STRING
3561d48fce0SDaniel Fojt 	| string STRING		{ $$ = catstr($1, $2); }
3571d48fce0SDaniel Fojt 	;
3581d48fce0SDaniel Fojt 
3594b588458SPeter Avalos term:
3604b588458SPeter Avalos  	  term '/' ASGNOP term		{ $$ = op2(DIVEQ, $1, $4); }
3614b588458SPeter Avalos  	| term '+' term			{ $$ = op2(ADD, $1, $3); }
3624b588458SPeter Avalos 	| term '-' term			{ $$ = op2(MINUS, $1, $3); }
3634b588458SPeter Avalos 	| term '*' term			{ $$ = op2(MULT, $1, $3); }
3644b588458SPeter Avalos 	| term '/' term			{ $$ = op2(DIVIDE, $1, $3); }
3654b588458SPeter Avalos 	| term '%' term			{ $$ = op2(MOD, $1, $3); }
3664b588458SPeter Avalos 	| term POWER term		{ $$ = op2(POWER, $1, $3); }
3674b588458SPeter Avalos 	| '-' term %prec UMINUS		{ $$ = op1(UMINUS, $2); }
3681d48fce0SDaniel Fojt 	| '+' term %prec UMINUS		{ $$ = op1(UPLUS, $2); }
3694b588458SPeter Avalos 	| NOT term %prec UMINUS		{ $$ = op1(NOT, notnull($2)); }
3704b588458SPeter Avalos 	| BLTIN '(' ')'			{ $$ = op2(BLTIN, itonp($1), rectonode()); }
3714b588458SPeter Avalos 	| BLTIN '(' patlist ')'		{ $$ = op2(BLTIN, itonp($1), $3); }
3724b588458SPeter Avalos 	| BLTIN				{ $$ = op2(BLTIN, itonp($1), rectonode()); }
3734b588458SPeter Avalos 	| CALL '(' ')'			{ $$ = op2(CALL, celltonode($1,CVAR), NIL); }
3744b588458SPeter Avalos 	| CALL '(' patlist ')'		{ $$ = op2(CALL, celltonode($1,CVAR), $3); }
3754b588458SPeter Avalos 	| CLOSE term			{ $$ = op1(CLOSE, $2); }
3764b588458SPeter Avalos 	| DECR var			{ $$ = op1(PREDECR, $2); }
3774b588458SPeter Avalos 	| INCR var			{ $$ = op1(PREINCR, $2); }
3784b588458SPeter Avalos 	| var DECR			{ $$ = op1(POSTDECR, $1); }
3794b588458SPeter Avalos 	| var INCR			{ $$ = op1(POSTINCR, $1); }
3804b588458SPeter Avalos 	| GETLINE var LT term		{ $$ = op3(GETLINE, $2, itonp($3), $4); }
3814b588458SPeter Avalos 	| GETLINE LT term		{ $$ = op3(GETLINE, NIL, itonp($2), $3); }
3824b588458SPeter Avalos 	| GETLINE var			{ $$ = op3(GETLINE, $2, NIL, NIL); }
3834b588458SPeter Avalos 	| GETLINE			{ $$ = op3(GETLINE, NIL, NIL, NIL); }
3844b588458SPeter Avalos 	| INDEX '(' pattern comma pattern ')'
3854b588458SPeter Avalos 		{ $$ = op2(INDEX, $3, $5); }
3864b588458SPeter Avalos 	| INDEX '(' pattern comma reg_expr ')'
3874b588458SPeter Avalos 		{ SYNTAX("index() doesn't permit regular expressions");
3884b588458SPeter Avalos 		  $$ = op2(INDEX, $3, (Node*)$5); }
3894b588458SPeter Avalos 	| '(' pattern ')'		{ $$ = $2; }
3904b588458SPeter Avalos 	| MATCHFCN '(' pattern comma reg_expr ')'
391*ed569bc2SAaron LI 		{ $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); free($5); }
3924b588458SPeter Avalos 	| MATCHFCN '(' pattern comma pattern ')'
39348f09a05SAntonio Huete Jimenez 		{ if (constnode($5)) {
3944b588458SPeter Avalos 			$$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
39548f09a05SAntonio Huete Jimenez 			free($5);
39648f09a05SAntonio Huete Jimenez 		  } else
3974b588458SPeter Avalos 			$$ = op3(MATCHFCN, (Node *)1, $3, $5); }
3984b588458SPeter Avalos 	| NUMBER			{ $$ = celltonode($1, CCON); }
3994b588458SPeter Avalos 	| SPLIT '(' pattern comma varname comma pattern ')'     /* string */
4004b588458SPeter Avalos 		{ $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
4014b588458SPeter Avalos 	| SPLIT '(' pattern comma varname comma reg_expr ')'    /* const /regexp/ */
402*ed569bc2SAaron LI 		{ $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); free($7); }
4034b588458SPeter Avalos 	| SPLIT '(' pattern comma varname ')'
4044b588458SPeter Avalos 		{ $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); }  /* default */
4054b588458SPeter Avalos 	| SPRINTF '(' patlist ')'	{ $$ = op1($1, $3); }
4061d48fce0SDaniel Fojt 	| string	 		{ $$ = celltonode($1, CCON); }
4074b588458SPeter Avalos 	| subop '(' reg_expr comma pattern ')'
408*ed569bc2SAaron LI 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); free($3); }
4094b588458SPeter Avalos 	| subop '(' pattern comma pattern ')'
41048f09a05SAntonio Huete Jimenez 		{ if (constnode($3)) {
4114b588458SPeter Avalos 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
41248f09a05SAntonio Huete Jimenez 			free($3);
41348f09a05SAntonio Huete Jimenez 		  } else
4144b588458SPeter Avalos 			$$ = op4($1, (Node *)1, $3, $5, rectonode()); }
4154b588458SPeter Avalos 	| subop '(' reg_expr comma pattern comma var ')'
416*ed569bc2SAaron LI 		{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); free($3); }
4174b588458SPeter Avalos 	| subop '(' pattern comma pattern comma var ')'
41848f09a05SAntonio Huete Jimenez 		{ if (constnode($3)) {
4194b588458SPeter Avalos 			$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
42048f09a05SAntonio Huete Jimenez 			free($3);
42148f09a05SAntonio Huete Jimenez 		  } else
4224b588458SPeter Avalos 			$$ = op4($1, (Node *)1, $3, $5, $7); }
4234b588458SPeter Avalos 	| SUBSTR '(' pattern comma pattern comma pattern ')'
4244b588458SPeter Avalos 		{ $$ = op3(SUBSTR, $3, $5, $7); }
4254b588458SPeter Avalos 	| SUBSTR '(' pattern comma pattern ')'
4264b588458SPeter Avalos 		{ $$ = op3(SUBSTR, $3, $5, NIL); }
4274b588458SPeter Avalos 	| var
4284b588458SPeter Avalos 	;
4294b588458SPeter Avalos 
4304b588458SPeter Avalos var:
4314b588458SPeter Avalos 	  varname
4324b588458SPeter Avalos 	| varname '[' patlist ']'	{ $$ = op2(ARRAY, makearr($1), $3); }
4334b588458SPeter Avalos 	| IVAR				{ $$ = op1(INDIRECT, celltonode($1, CVAR)); }
4344b588458SPeter Avalos 	| INDIRECT term	 		{ $$ = op1(INDIRECT, $2); }
4354b588458SPeter Avalos 	;
4364b588458SPeter Avalos 
4374b588458SPeter Avalos varlist:
4384b588458SPeter Avalos 	  /* nothing */		{ arglist = $$ = 0; }
4394b588458SPeter Avalos 	| VAR			{ arglist = $$ = celltonode($1,CVAR); }
4404b588458SPeter Avalos 	| varlist comma VAR	{
4414b588458SPeter Avalos 			checkdup($1, $3);
4424b588458SPeter Avalos 			arglist = $$ = linkum($1,celltonode($3,CVAR)); }
4434b588458SPeter Avalos 	;
4444b588458SPeter Avalos 
4454b588458SPeter Avalos varname:
4464b588458SPeter Avalos 	  VAR			{ $$ = celltonode($1, CVAR); }
4474b588458SPeter Avalos 	| ARG 			{ $$ = op1(ARG, itonp($1)); }
4484b588458SPeter Avalos 	| VARNF			{ $$ = op1(VARNF, (Node *) $1); }
4494b588458SPeter Avalos 	;
4504b588458SPeter Avalos 
4514b588458SPeter Avalos 
4524b588458SPeter Avalos while:
4534b588458SPeter Avalos 	  WHILE '(' pattern rparen	{ $$ = notnull($3); }
4544b588458SPeter Avalos 	;
4554b588458SPeter Avalos 
4564b588458SPeter Avalos %%
4574b588458SPeter Avalos 
4584b588458SPeter Avalos void setfname(Cell *p)
4594b588458SPeter Avalos {
4604b588458SPeter Avalos 	if (isarr(p))
4614b588458SPeter Avalos 		SYNTAX("%s is an array, not a function", p->nval);
4624b588458SPeter Avalos 	else if (isfcn(p))
4634b588458SPeter Avalos 		SYNTAX("you can't define function %s more than once", p->nval);
4644b588458SPeter Avalos 	curfname = p->nval;
4654b588458SPeter Avalos }
4664b588458SPeter Avalos 
4674b588458SPeter Avalos int constnode(Node *p)
4684b588458SPeter Avalos {
4694b588458SPeter Avalos 	return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
4704b588458SPeter Avalos }
4714b588458SPeter Avalos 
4724b588458SPeter Avalos char *strnode(Node *p)
4734b588458SPeter Avalos {
4744b588458SPeter Avalos 	return ((Cell *)(p->narg[0]))->sval;
4754b588458SPeter Avalos }
4764b588458SPeter Avalos 
4774b588458SPeter Avalos Node *notnull(Node *n)
4784b588458SPeter Avalos {
4794b588458SPeter Avalos 	switch (n->nobj) {
4804b588458SPeter Avalos 	case LE: case LT: case EQ: case NE: case GT: case GE:
4814b588458SPeter Avalos 	case BOR: case AND: case NOT:
4824b588458SPeter Avalos 		return n;
4834b588458SPeter Avalos 	default:
4844b588458SPeter Avalos 		return op2(NE, n, nullnode);
4854b588458SPeter Avalos 	}
4864b588458SPeter Avalos }
4874b588458SPeter Avalos 
4884b588458SPeter Avalos void checkdup(Node *vl, Cell *cp)	/* check if name already in list */
4894b588458SPeter Avalos {
4904b588458SPeter Avalos 	char *s = cp->nval;
4914b588458SPeter Avalos 	for ( ; vl; vl = vl->nnext) {
4924b588458SPeter Avalos 		if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) {
4934b588458SPeter Avalos 			SYNTAX("duplicate argument %s", s);
4944b588458SPeter Avalos 			break;
4954b588458SPeter Avalos 		}
4964b588458SPeter Avalos 	}
4974b588458SPeter Avalos }
498