perl 4.0 patch 34: (combined patch)
[perl.git] / perly.y
1 /* $RCSfile: perly.y,v $$Revision: 4.0.1.5 $$Date: 92/06/11 21:12:50 $
2  *
3  *    Copyright (c) 1991, Larry Wall
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  * $Log:        perly.y,v $
9  * Revision 4.0.1.5  92/06/11  21:12:50  lwall
10  * patch34: expectterm incorrectly set to indicate start of program or block
11  * 
12  * Revision 4.0.1.4  92/06/08  17:33:25  lwall
13  * patch20: one of the backdoors to expectterm was on the wrong reduction
14  * 
15  * Revision 4.0.1.3  92/06/08  15:18:16  lwall
16  * patch20: an expression may now start with a bareword
17  * patch20: relaxed requirement for semicolon at the end of a block
18  * patch20: added ... as variant on ..
19  * patch20: fixed double debug break in foreach with implicit array assignment
20  * patch20: if {block} {block} didn't work any more
21  * patch20: deleted some minor memory leaks
22  * 
23  * Revision 4.0.1.2  91/11/05  18:17:38  lwall
24  * patch11: extra comma at end of list is now allowed in more places (Hi, Felix!)
25  * patch11: once-thru blocks didn't display right in the debugger
26  * patch11: debugger got confused over nested subroutine definitions
27  * 
28  * Revision 4.0.1.1  91/06/07  11:42:34  lwall
29  * patch4: new copyright notice
30  * 
31  * Revision 4.0  91/03/20  01:38:40  lwall
32  * 4.0 baseline.
33  * 
34  */
35
36 %{
37 #include "INTERN.h"
38 #include "perl.h"
39
40 /*SUPPRESS 530*/
41 /*SUPPRESS 593*/
42 /*SUPPRESS 595*/
43
44 STAB *scrstab;
45 ARG *arg4;      /* rarely used arguments to make_op() */
46 ARG *arg5;
47
48 %}
49
50 %start prog
51
52 %union {
53     int ival;
54     char *cval;
55     ARG *arg;
56     CMD *cmdval;
57     struct compcmd compval;
58     STAB *stabval;
59     FCMD *formval;
60 }
61
62 %token <ival> '{' ')'
63
64 %token <cval> WORD LABEL
65 %token <ival> APPEND OPEN SSELECT LOOPEX DOTDOT
66 %token <ival> USING FORMAT DO SHIFT PUSH POP LVALFUN
67 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT FLIST
68 %token <ival> FOR FILOP FILOP2 FILOP3 FILOP4 FILOP22 FILOP25
69 %token <ival> FUNC0 FUNC1 FUNC2 FUNC2x FUNC3 FUNC4 FUNC5 HSHFUN HSHFUN3
70 %token <ival> FLIST2 SUB FILETEST LOCAL DELETE
71 %token <ival> RELOP EQOP MULOP ADDOP PACKAGE AMPER
72 %token <formval> FORMLIST
73 %token <stabval> REG ARYLEN ARY HSH STAR
74 %token <arg> SUBST PATTERN
75 %token <arg> RSTRING TRANS
76
77 %type <ival> prog decl format remember crp
78 %type <cmdval> block lineseq line loop cond sideff nexpr else
79 %type <arg> expr sexpr cexpr csexpr term handle aryword hshword
80 %type <arg> texpr listop bareword
81 %type <cval> label
82 %type <compval> compblock
83
84 %nonassoc <ival> LISTOP
85 %left ','
86 %right '='
87 %right '?' ':'
88 %nonassoc DOTDOT
89 %left OROR
90 %left ANDAND
91 %left '|' '^'
92 %left '&'
93 %nonassoc EQOP
94 %nonassoc RELOP
95 %nonassoc <ival> UNIOP
96 %nonassoc FILETEST
97 %left LS RS
98 %left ADDOP
99 %left MULOP
100 %left MATCH NMATCH 
101 %right '!' '~' UMINUS
102 %right POW
103 %nonassoc INC DEC
104 %left '('
105
106 %% /* RULES */
107
108 prog    :       /* NULL */
109                 {
110 #if defined(YYDEBUG) && defined(DEBUGGING)
111                     yydebug = (debug & 1);
112 #endif
113                     expectterm = 2;
114                 }
115         /*CONTINUED*/   lineseq
116                         { if (in_eval)
117                                 eval_root = block_head($2);
118                             else
119                                 main_root = block_head($2); }
120         ;
121
122 compblock:      block CONTINUE block
123                         { $$.comp_true = $1; $$.comp_alt = $3; }
124         |       block else
125                         { $$.comp_true = $1; $$.comp_alt = $2; }
126         ;
127
128 else    :       /* NULL */
129                         { $$ = Nullcmd; }
130         |       ELSE block
131                         { $$ = $2; }
132         |       ELSIF '(' expr ')' compblock
133                         { cmdline = $1;
134                             $$ = make_ccmd(C_ELSIF,1,$3,$5); }
135         ;
136
137 block   :       '{' remember lineseq '}'
138                         { $$ = block_head($3);
139                           if (cmdline > (line_t)$1)
140                               cmdline = $1;
141                           if (savestack->ary_fill > $2)
142                             restorelist($2);
143                           expectterm = 2; }
144         ;
145
146 remember:       /* NULL */      /* in case they push a package name */
147                         { $$ = savestack->ary_fill; }
148         ;
149
150 lineseq :       /* NULL */
151                         { $$ = Nullcmd; }
152         |       lineseq line
153                         { $$ = append_line($1,$2); }
154         ;
155
156 line    :       decl
157                         { $$ = Nullcmd; }
158         |       label cond
159                         { $$ = add_label($1,$2); }
160         |       loop    /* loops add their own labels */
161         |       label ';'
162                         { if ($1 != Nullch) {
163                               $$ = add_label($1, make_acmd(C_EXPR, Nullstab,
164                                   Nullarg, Nullarg) );
165                             }
166                             else {
167                               $$ = Nullcmd;
168                               cmdline = NOLINE;
169                             }
170                             expectterm = 2; }
171         |       label sideff ';'
172                         { $$ = add_label($1,$2);
173                           expectterm = 2; }
174         ;
175
176 sideff  :       error
177                         { $$ = Nullcmd; }
178         |       expr
179                         { $$ = make_acmd(C_EXPR, Nullstab, $1, Nullarg); }
180         |       expr IF expr
181                         { $$ = addcond(
182                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
183         |       expr UNLESS expr
184                         { $$ = addcond(invert(
185                                make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
186         |       expr WHILE expr
187                         { $$ = addloop(
188                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $3); }
189         |       expr UNTIL expr
190                         { $$ = addloop(invert(
191                                make_acmd(C_EXPR, Nullstab, Nullarg, $1)), $3); }
192         ;
193
194 cond    :       IF '(' expr ')' compblock
195                         { cmdline = $1;
196                             $$ = make_icmd(C_IF,$3,$5); }
197         |       UNLESS '(' expr ')' compblock
198                         { cmdline = $1;
199                             $$ = invert(make_icmd(C_IF,$3,$5)); }
200         |       IF block compblock
201                         { cmdline = $1;
202                             $$ = make_icmd(C_IF,cmd_to_arg($2),$3); }
203         |       UNLESS block compblock
204                         { cmdline = $1;
205                             $$ = invert(make_icmd(C_IF,cmd_to_arg($2),$3)); }
206         ;
207
208 loop    :       label WHILE '(' texpr ')' compblock
209                         { cmdline = $2;
210                             $$ = wopt(add_label($1,
211                             make_ccmd(C_WHILE,1,$4,$6) )); }
212         |       label UNTIL '(' expr ')' compblock
213                         { cmdline = $2;
214                             $$ = wopt(add_label($1,
215                             invert(make_ccmd(C_WHILE,1,$4,$6)) )); }
216         |       label WHILE block compblock
217                         { cmdline = $2;
218                             $$ = wopt(add_label($1,
219                             make_ccmd(C_WHILE, 1, cmd_to_arg($3),$4) )); }
220         |       label UNTIL block compblock
221                         { cmdline = $2;
222                             $$ = wopt(add_label($1,
223                             invert(make_ccmd(C_WHILE,1,cmd_to_arg($3),$4)) )); }
224         |       label FOR REG '(' expr crp compblock
225                         { cmdline = $2;
226                             /*
227                              * The following gobbledygook catches EXPRs that
228                              * aren't explicit array refs and translates
229                              *          foreach VAR (EXPR) {
230                              * into
231                              *          @ary = EXPR;
232                              *          foreach VAR (@ary) {
233                              * where @ary is a hidden array made by genstab().
234                              * (Note that @ary may become a local array if
235                              * it is determined that it might be called
236                              * recursively.  See cmd_tosave().)
237                              */
238                             if ($5->arg_type != O_ARRAY) {
239                                 scrstab = aadd(genstab());
240                                 $$ = append_line(
241                                     make_acmd(C_EXPR, Nullstab,
242                                       l(make_op(O_ASSIGN,2,
243                                         listish(make_op(O_ARRAY, 1,
244                                           stab2arg(A_STAB,scrstab),
245                                           Nullarg,Nullarg )),
246                                         listish(make_list($5)),
247                                         Nullarg)),
248                                       Nullarg),
249                                     wopt(over($3,add_label($1,
250                                       make_ccmd(C_WHILE, 0,
251                                         make_op(O_ARRAY, 1,
252                                           stab2arg(A_STAB,scrstab),
253                                           Nullarg,Nullarg ),
254                                         $7)))));
255                                 $$->c_line = $2;
256                                 $$->c_head->c_line = $2;
257                             }
258                             else {
259                                 $$ = wopt(over($3,add_label($1,
260                                 make_ccmd(C_WHILE,1,$5,$7) )));
261                             }
262                         }
263         |       label FOR '(' expr crp compblock
264                         { cmdline = $2;
265                             if ($4->arg_type != O_ARRAY) {
266                                 scrstab = aadd(genstab());
267                                 $$ = append_line(
268                                     make_acmd(C_EXPR, Nullstab,
269                                       l(make_op(O_ASSIGN,2,
270                                         listish(make_op(O_ARRAY, 1,
271                                           stab2arg(A_STAB,scrstab),
272                                           Nullarg,Nullarg )),
273                                         listish(make_list($4)),
274                                         Nullarg)),
275                                       Nullarg),
276                                     wopt(over(defstab,add_label($1,
277                                       make_ccmd(C_WHILE, 0,
278                                         make_op(O_ARRAY, 1,
279                                           stab2arg(A_STAB,scrstab),
280                                           Nullarg,Nullarg ),
281                                         $6)))));
282                                 $$->c_line = $2;
283                                 $$->c_head->c_line = $2;
284                             }
285                             else {      /* lisp, anyone? */
286                                 $$ = wopt(over(defstab,add_label($1,
287                                 make_ccmd(C_WHILE,1,$4,$6) )));
288                             }
289                         }
290         |       label FOR '(' nexpr ';' texpr ';' nexpr ')' block
291                         /* basically fake up an initialize-while lineseq */
292                         {   yyval.compval.comp_true = $10;
293                             yyval.compval.comp_alt = $8;
294                             cmdline = $2;
295                             $$ = append_line($4,wopt(add_label($1,
296                                 make_ccmd(C_WHILE,1,$6,yyval.compval) ))); }
297         |       label compblock /* a block is a loop that happens once */
298                         { $$ = add_label($1,make_ccmd(C_BLOCK,1,Nullarg,$2)); }
299         ;
300
301 nexpr   :       /* NULL */
302                         { $$ = Nullcmd; }
303         |       sideff
304         ;
305
306 texpr   :       /* NULL means true */
307                         { (void)scanstr("1",SCAN_DEF); $$ = yylval.arg; }
308         |       expr
309         ;
310
311 label   :       /* empty */
312                         { $$ = Nullch; }
313         |       LABEL
314         ;
315
316 decl    :       format
317                         { $$ = 0; }
318         |       subrout
319                         { $$ = 0; }
320         |       package
321                         { $$ = 0; }
322         ;
323
324 format  :       FORMAT WORD '=' FORMLIST
325                         { if (strEQ($2,"stdout"))
326                             make_form(stabent("STDOUT",TRUE),$4);
327                           else if (strEQ($2,"stderr"))
328                             make_form(stabent("STDERR",TRUE),$4);
329                           else
330                             make_form(stabent($2,TRUE),$4);
331                           Safefree($2); $2 = Nullch; }
332         |       FORMAT '=' FORMLIST
333                         { make_form(stabent("STDOUT",TRUE),$3); }
334         ;
335
336 subrout :       SUB WORD block
337                         { make_sub($2,$3);
338                           cmdline = NOLINE;
339                           if (savestack->ary_fill > $1)
340                             restorelist($1); }
341         ;
342
343 package :       PACKAGE WORD ';'
344                         { char tmpbuf[256];
345                           STAB *tmpstab;
346
347                           savehptr(&curstash);
348                           saveitem(curstname);
349                           str_set(curstname,$2);
350                           sprintf(tmpbuf,"'_%s",$2);
351                           tmpstab = stabent(tmpbuf,TRUE);
352                           if (!stab_xhash(tmpstab))
353                               stab_xhash(tmpstab) = hnew(0);
354                           curstash = stab_xhash(tmpstab);
355                           if (!curstash->tbl_name)
356                               curstash->tbl_name = savestr($2);
357                           curstash->tbl_coeffsize = 0;
358                           Safefree($2); $2 = Nullch;
359                           cmdline = NOLINE;
360                           expectterm = 2;
361                         }
362         ;
363
364 cexpr   :       ',' expr
365                         { $$ = $2; }
366         ;
367
368 expr    :       expr ',' sexpr
369                         { $$ = make_op(O_COMMA, 2, $1, $3, Nullarg); }
370         |       sexpr
371         ;
372
373 csexpr  :       ',' sexpr
374                         { $$ = $2; }
375         ;
376
377 sexpr   :       sexpr '=' sexpr
378                         {   $1 = listish($1);
379                             if ($1->arg_type == O_ASSIGN && $1->arg_len == 1)
380                                 $1->arg_type = O_ITEM;  /* a local() */
381                             if ($1->arg_type == O_LIST)
382                                 $3 = listish($3);
383                             $$ = l(make_op(O_ASSIGN, 2, $1, $3, Nullarg)); }
384         |       sexpr POW '=' sexpr
385                         { $$ = l(make_op(O_POW, 2, $1, $4, Nullarg)); }
386         |       sexpr MULOP '=' sexpr
387                         { $$ = l(make_op($2, 2, $1, $4, Nullarg)); }
388         |       sexpr ADDOP '=' sexpr
389                         { $$ = rcatmaybe(l(make_op($2, 2, $1, $4, Nullarg)));}
390         |       sexpr LS '=' sexpr
391                         { $$ = l(make_op(O_LEFT_SHIFT, 2, $1, $4, Nullarg)); }
392         |       sexpr RS '=' sexpr
393                         { $$ = l(make_op(O_RIGHT_SHIFT, 2, $1, $4, Nullarg)); }
394         |       sexpr '&' '=' sexpr
395                         { $$ = l(make_op(O_BIT_AND, 2, $1, $4, Nullarg)); }
396         |       sexpr '^' '=' sexpr
397                         { $$ = l(make_op(O_XOR, 2, $1, $4, Nullarg)); }
398         |       sexpr '|' '=' sexpr
399                         { $$ = l(make_op(O_BIT_OR, 2, $1, $4, Nullarg)); }
400
401
402         |       sexpr POW sexpr
403                         { $$ = make_op(O_POW, 2, $1, $3, Nullarg); }
404         |       sexpr MULOP sexpr
405                         { if ($2 == O_REPEAT)
406                               $1 = listish($1);
407                             $$ = make_op($2, 2, $1, $3, Nullarg);
408                             if ($2 == O_REPEAT) {
409                                 if ($$[1].arg_type != A_EXPR ||
410                                   $$[1].arg_ptr.arg_arg->arg_type != O_LIST)
411                                     $$[1].arg_flags &= ~AF_ARYOK;
412                             } }
413         |       sexpr ADDOP sexpr
414                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
415         |       sexpr LS sexpr
416                         { $$ = make_op(O_LEFT_SHIFT, 2, $1, $3, Nullarg); }
417         |       sexpr RS sexpr
418                         { $$ = make_op(O_RIGHT_SHIFT, 2, $1, $3, Nullarg); }
419         |       sexpr RELOP sexpr
420                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
421         |       sexpr EQOP sexpr
422                         { $$ = make_op($2, 2, $1, $3, Nullarg); }
423         |       sexpr '&' sexpr
424                         { $$ = make_op(O_BIT_AND, 2, $1, $3, Nullarg); }
425         |       sexpr '^' sexpr
426                         { $$ = make_op(O_XOR, 2, $1, $3, Nullarg); }
427         |       sexpr '|' sexpr
428                         { $$ = make_op(O_BIT_OR, 2, $1, $3, Nullarg); }
429         |       sexpr DOTDOT sexpr
430                         { arg4 = Nullarg;
431                           $$ = make_op(O_F_OR_R, 4, $1, $3, Nullarg);
432                           $$[0].arg_flags |= $2; }
433         |       sexpr ANDAND sexpr
434                         { $$ = make_op(O_AND, 2, $1, $3, Nullarg); }
435         |       sexpr OROR sexpr
436                         { $$ = make_op(O_OR, 2, $1, $3, Nullarg); }
437         |       sexpr '?' sexpr ':' sexpr
438                         { $$ = make_op(O_COND_EXPR, 3, $1, $3, $5); }
439         |       sexpr MATCH sexpr
440                         { $$ = mod_match(O_MATCH, $1, $3); }
441         |       sexpr NMATCH sexpr
442                         { $$ = mod_match(O_NMATCH, $1, $3); }
443         |       term
444                         { $$ = $1; }
445         ;
446
447 term    :       '-' term %prec UMINUS
448                         { $$ = make_op(O_NEGATE, 1, $2, Nullarg, Nullarg); }
449         |       '+' term %prec UMINUS
450                         { $$ = $2; }
451         |       '!' term
452                         { $$ = make_op(O_NOT, 1, $2, Nullarg, Nullarg); }
453         |       '~' term
454                         { $$ = make_op(O_COMPLEMENT, 1, $2, Nullarg, Nullarg);}
455         |       term INC
456                         { $$ = addflags(1, AF_POST|AF_UP,
457                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
458         |       term DEC
459                         { $$ = addflags(1, AF_POST,
460                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg))); }
461         |       INC term
462                         { $$ = addflags(1, AF_PRE|AF_UP,
463                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
464         |       DEC term
465                         { $$ = addflags(1, AF_PRE,
466                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg))); }
467         |       FILETEST WORD
468                         { opargs[$1] = 0;       /* force it special */
469                             $$ = make_op($1, 1,
470                                 stab2arg(A_STAB,stabent($2,TRUE)),
471                                 Nullarg, Nullarg);
472                             Safefree($2); $2 = Nullch;
473                         }
474         |       FILETEST sexpr
475                         { opargs[$1] = 1;
476                             $$ = make_op($1, 1, $2, Nullarg, Nullarg); }
477         |       FILETEST
478                         { opargs[$1] = ($1 != O_FTTTY);
479                             $$ = make_op($1, 1,
480                                 stab2arg(A_STAB,
481                                   $1 == O_FTTTY?stabent("STDIN",TRUE):defstab),
482                                 Nullarg, Nullarg); }
483         |       LOCAL '(' expr crp
484                         { $$ = l(localize(make_op(O_ASSIGN, 1,
485                                 localize(listish(make_list($3))),
486                                 Nullarg,Nullarg))); }
487         |       '(' expr crp
488                         { $$ = make_list($2); }
489         |       '(' ')'
490                         { $$ = make_list(Nullarg); }
491         |       DO sexpr        %prec FILETEST
492                         { $$ = make_op(O_DOFILE,2,$2,Nullarg,Nullarg);
493                           allstabs = TRUE;}
494         |       DO block        %prec '('
495                         { $$ = cmd_to_arg($2); }
496         |       REG     %prec '('
497                         { $$ = stab2arg(A_STAB,$1); }
498         |       STAR    %prec '('
499                         { $$ = stab2arg(A_STAR,$1); }
500         |       REG '[' expr ']'        %prec '('
501                         { $$ = make_op(O_AELEM, 2,
502                                 stab2arg(A_STAB,aadd($1)), $3, Nullarg); }
503         |       HSH     %prec '('
504                         { $$ = make_op(O_HASH, 1,
505                                 stab2arg(A_STAB,$1),
506                                 Nullarg, Nullarg); }
507         |       ARY     %prec '('
508                         { $$ = make_op(O_ARRAY, 1,
509                                 stab2arg(A_STAB,$1),
510                                 Nullarg, Nullarg); }
511         |       REG '{' expr ';' '}'    %prec '('
512                         { $$ = make_op(O_HELEM, 2,
513                                 stab2arg(A_STAB,hadd($1)),
514                                 jmaybe($3),
515                                 Nullarg);
516                             expectterm = FALSE; }
517         |       '(' expr crp '[' expr ']'       %prec '('
518                         { $$ = make_op(O_LSLICE, 3,
519                                 Nullarg,
520                                 listish(make_list($5)),
521                                 listish(make_list($2))); }
522         |       '(' ')' '[' expr ']'    %prec '('
523                         { $$ = make_op(O_LSLICE, 3,
524                                 Nullarg,
525                                 listish(make_list($4)),
526                                 Nullarg); }
527         |       ARY '[' expr ']'        %prec '('
528                         { $$ = make_op(O_ASLICE, 2,
529                                 stab2arg(A_STAB,aadd($1)),
530                                 listish(make_list($3)),
531                                 Nullarg); }
532         |       ARY '{' expr ';' '}'    %prec '('
533                         { $$ = make_op(O_HSLICE, 2,
534                                 stab2arg(A_STAB,hadd($1)),
535                                 listish(make_list($3)),
536                                 Nullarg);
537                             expectterm = FALSE; }
538         |       DELETE REG '{' expr ';' '}'     %prec '('
539                         { $$ = make_op(O_DELETE, 2,
540                                 stab2arg(A_STAB,hadd($2)),
541                                 jmaybe($4),
542                                 Nullarg);
543                             expectterm = FALSE; }
544         |       DELETE '(' REG '{' expr ';' '}' ')'     %prec '('
545                         { $$ = make_op(O_DELETE, 2,
546                                 stab2arg(A_STAB,hadd($3)),
547                                 jmaybe($4),
548                                 Nullarg);
549                             expectterm = FALSE; }
550         |       ARYLEN  %prec '('
551                         { $$ = stab2arg(A_ARYLEN,$1); }
552         |       RSTRING %prec '('
553                         { $$ = $1; }
554         |       PATTERN %prec '('
555                         { $$ = $1; }
556         |       SUBST   %prec '('
557                         { $$ = $1; }
558         |       TRANS   %prec '('
559                         { $$ = $1; }
560         |       DO WORD '(' expr crp
561                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
562                                 stab2arg(A_WORD,stabent($2,MULTI)),
563                                 make_list($4),
564                                 Nullarg); Safefree($2); $2 = Nullch;
565                             $$->arg_flags |= AF_DEPR; }
566         |       AMPER WORD '(' expr crp
567                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
568                                 stab2arg(A_WORD,stabent($2,MULTI)),
569                                 make_list($4),
570                                 Nullarg); Safefree($2); $2 = Nullch; }
571         |       DO WORD '(' ')'
572                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
573                                 stab2arg(A_WORD,stabent($2,MULTI)),
574                                 make_list(Nullarg),
575                                 Nullarg);
576                             Safefree($2); $2 = Nullch;
577                             $$->arg_flags |= AF_DEPR; }
578         |       AMPER WORD '(' ')'
579                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
580                                 stab2arg(A_WORD,stabent($2,MULTI)),
581                                 make_list(Nullarg),
582                                 Nullarg);
583                             Safefree($2); $2 = Nullch;
584                         }
585         |       AMPER WORD
586                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
587                                 stab2arg(A_WORD,stabent($2,MULTI)),
588                                 Nullarg,
589                                 Nullarg);
590                             Safefree($2); $2 = Nullch;
591                         }
592         |       DO REG '(' expr crp
593                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
594                                 stab2arg(A_STAB,$2),
595                                 make_list($4),
596                                 Nullarg);
597                             $$->arg_flags |= AF_DEPR; }
598         |       AMPER REG '(' expr crp
599                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
600                                 stab2arg(A_STAB,$2),
601                                 make_list($4),
602                                 Nullarg); }
603         |       DO REG '(' ')'
604                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
605                                 stab2arg(A_STAB,$2),
606                                 make_list(Nullarg),
607                                 Nullarg);
608                             $$->arg_flags |= AF_DEPR; }
609         |       AMPER REG '(' ')'
610                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
611                                 stab2arg(A_STAB,$2),
612                                 make_list(Nullarg),
613                                 Nullarg); }
614         |       AMPER REG
615                         { $$ = make_op((perldb ? O_DBSUBR : O_SUBR), 2,
616                                 stab2arg(A_STAB,$2),
617                                 Nullarg,
618                                 Nullarg); }
619         |       LOOPEX
620                         { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg); }
621         |       LOOPEX WORD
622                         { $$ = make_op($1,1,cval_to_arg($2),
623                             Nullarg,Nullarg); }
624         |       UNIOP
625                         { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg); }
626         |       UNIOP block
627                         { $$ = make_op($1,1,cmd_to_arg($2),Nullarg,Nullarg); }
628         |       UNIOP sexpr
629                         { $$ = make_op($1,1,$2,Nullarg,Nullarg); }
630         |       SSELECT
631                         { $$ = make_op(O_SELECT, 0, Nullarg, Nullarg, Nullarg);}
632         |       SSELECT  WORD
633                         { $$ = make_op(O_SELECT, 1,
634                             stab2arg(A_WORD,stabent($2,TRUE)),
635                             Nullarg,
636                             Nullarg);
637                             Safefree($2); $2 = Nullch; }
638         |       SSELECT '(' handle ')'
639                         { $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg); }
640         |       SSELECT '(' sexpr csexpr csexpr csexpr ')'
641                         { arg4 = $6;
642                           $$ = make_op(O_SSELECT, 4, $3, $4, $5); }
643         |       OPEN WORD       %prec '('
644                         { $$ = make_op(O_OPEN, 2,
645                             stab2arg(A_WORD,stabent($2,TRUE)),
646                             stab2arg(A_STAB,stabent($2,TRUE)),
647                             Nullarg);
648                             Safefree($2); $2 = Nullch;
649                         }
650         |       OPEN '(' WORD ')'
651                         { $$ = make_op(O_OPEN, 2,
652                             stab2arg(A_WORD,stabent($3,TRUE)),
653                             stab2arg(A_STAB,stabent($3,TRUE)),
654                             Nullarg);
655                             Safefree($3); $3 = Nullch;
656                         }
657         |       OPEN '(' handle cexpr ')'
658                         { $$ = make_op(O_OPEN, 2,
659                             $3,
660                             $4, Nullarg); }
661         |       FILOP '(' handle ')'
662                         { $$ = make_op($1, 1,
663                             $3,
664                             Nullarg, Nullarg); }
665         |       FILOP WORD
666                         { $$ = make_op($1, 1,
667                             stab2arg(A_WORD,stabent($2,TRUE)),
668                             Nullarg, Nullarg);
669                           Safefree($2); $2 = Nullch; }
670         |       FILOP REG
671                         { $$ = make_op($1, 1,
672                             stab2arg(A_STAB,$2),
673                             Nullarg, Nullarg); }
674         |       FILOP '(' ')'
675                         { $$ = make_op($1, 1,
676                             stab2arg(A_WORD,Nullstab),
677                             Nullarg, Nullarg); }
678         |       FILOP   %prec '('
679                         { $$ = make_op($1, 0,
680                             Nullarg, Nullarg, Nullarg); }
681         |       FILOP2 '(' handle cexpr ')'
682                         { $$ = make_op($1, 2, $3, $4, Nullarg); }
683         |       FILOP3 '(' handle csexpr cexpr ')'
684                         { $$ = make_op($1, 3, $3, $4, make_list($5)); }
685         |       FILOP22 '(' handle ',' handle ')'
686                         { $$ = make_op($1, 2, $3, $5, Nullarg); }
687         |       FILOP4 '(' handle csexpr csexpr cexpr ')'
688                         { arg4 = $6; $$ = make_op($1, 4, $3, $4, $5); }
689         |       FILOP25 '(' handle ',' handle csexpr csexpr cexpr ')'
690                         { arg4 = $7; arg5 = $8;
691                           $$ = make_op($1, 5, $3, $5, $6); }
692         |       PUSH '(' aryword ',' expr crp
693                         { $$ = make_op($1, 2,
694                             $3,
695                             make_list($5),
696                             Nullarg); }
697         |       POP aryword     %prec '('
698                         { $$ = make_op(O_POP, 1, $2, Nullarg, Nullarg); }
699         |       POP '(' aryword ')'
700                         { $$ = make_op(O_POP, 1, $3, Nullarg, Nullarg); }
701         |       SHIFT aryword   %prec '('
702                         { $$ = make_op(O_SHIFT, 1, $2, Nullarg, Nullarg); }
703         |       SHIFT '(' aryword ')'
704                         { $$ = make_op(O_SHIFT, 1, $3, Nullarg, Nullarg); }
705         |       SHIFT   %prec '('
706                         { $$ = make_op(O_SHIFT, 1,
707                             stab2arg(A_STAB,
708                               aadd(stabent(subline ? "_" : "ARGV", TRUE))),
709                             Nullarg, Nullarg); }
710         |       SPLIT   %prec '('
711                         {   static char p[]="/\\s+/";
712                             char *oldend = bufend;
713                             ARG *oldarg = yylval.arg;
714                             
715                             bufend=p+5;
716                             (void)scanpat(p);
717                             bufend=oldend;
718                             $$ = make_split(defstab,yylval.arg,Nullarg);
719                             yylval.arg = oldarg; }
720         |       SPLIT '(' sexpr csexpr csexpr ')'
721                         { $$ = mod_match(O_MATCH, $4,
722                           make_split(defstab,$3,$5));}
723         |       SPLIT '(' sexpr csexpr ')'
724                         { $$ = mod_match(O_MATCH, $4,
725                           make_split(defstab,$3,Nullarg) ); }
726         |       SPLIT '(' sexpr ')'
727                         { $$ = mod_match(O_MATCH,
728                             stab2arg(A_STAB,defstab),
729                             make_split(defstab,$3,Nullarg) ); }
730         |       FLIST2 '(' sexpr cexpr ')'
731                         { $$ = make_op($1, 2,
732                             $3,
733                             listish(make_list($4)),
734                             Nullarg); }
735         |       FLIST '(' expr crp
736                         { $$ = make_op($1, 1,
737                             make_list($3),
738                             Nullarg,
739                             Nullarg); }
740         |       LVALFUN sexpr   %prec '('
741                         { $$ = l(make_op($1, 1, fixl($1,$2),
742                             Nullarg, Nullarg)); }
743         |       LVALFUN
744                         { $$ = l(make_op($1, 1,
745                             stab2arg(A_STAB,defstab),
746                             Nullarg, Nullarg)); }
747         |       FUNC0
748                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
749         |       FUNC0 '(' ')'
750                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
751         |       FUNC1 '(' ')'
752                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
753         |       FUNC1 '(' expr ')'
754                         { $$ = make_op($1, 1, $3, Nullarg, Nullarg); }
755         |       FUNC2 '(' sexpr cexpr ')'
756                         { $$ = make_op($1, 2, $3, $4, Nullarg);
757                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
758                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
759         |       FUNC2x '(' sexpr csexpr ')'
760                         { $$ = make_op($1, 2, $3, $4, Nullarg);
761                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
762                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
763         |       FUNC2x '(' sexpr csexpr cexpr ')'
764                         { $$ = make_op($1, 3, $3, $4, $5);
765                             if ($1 == O_INDEX && $$[2].arg_type == A_SINGLE)
766                                 fbmcompile($$[2].arg_ptr.arg_str,0); }
767         |       FUNC3 '(' sexpr csexpr cexpr ')'
768                         { $$ = make_op($1, 3, $3, $4, $5); }
769         |       FUNC4 '(' sexpr csexpr csexpr cexpr ')'
770                         { arg4 = $6;
771                           $$ = make_op($1, 4, $3, $4, $5); }
772         |       FUNC5 '(' sexpr csexpr csexpr csexpr cexpr ')'
773                         { arg4 = $6; arg5 = $7;
774                           $$ = make_op($1, 5, $3, $4, $5); }
775         |       HSHFUN '(' hshword ')'
776                         { $$ = make_op($1, 1,
777                                 $3,
778                                 Nullarg,
779                                 Nullarg); }
780         |       HSHFUN hshword
781                         { $$ = make_op($1, 1,
782                                 $2,
783                                 Nullarg,
784                                 Nullarg); }
785         |       HSHFUN3 '(' hshword csexpr cexpr ')'
786                         { $$ = make_op($1, 3, $3, $4, $5); }
787         |       bareword
788         |       listop
789         ;
790
791 listop  :       LISTOP
792                         { $$ = make_op($1,2,
793                                 stab2arg(A_WORD,Nullstab),
794                                 stab2arg(A_STAB,defstab),
795                                 Nullarg); }
796         |       LISTOP expr
797                         { $$ = make_op($1,2,
798                                 stab2arg(A_WORD,Nullstab),
799                                 maybelistish($1,make_list($2)),
800                                 Nullarg); }
801         |       LISTOP WORD
802                         { $$ = make_op($1,2,
803                                 stab2arg(A_WORD,stabent($2,TRUE)),
804                                 stab2arg(A_STAB,defstab),
805                                 Nullarg);
806                             Safefree($2); $2 = Nullch;
807                         }
808         |       LISTOP WORD expr
809                         { $$ = make_op($1,2,
810                                 stab2arg(A_WORD,stabent($2,TRUE)),
811                                 maybelistish($1,make_list($3)),
812                                 Nullarg); Safefree($2); $2 = Nullch; }
813         |       LISTOP REG expr
814                         { $$ = make_op($1,2,
815                                 stab2arg(A_STAB,$2),
816                                 maybelistish($1,make_list($3)),
817                                 Nullarg); }
818         |       LISTOP block expr
819                         { $$ = make_op($1,2,
820                                 cmd_to_arg($2),
821                                 maybelistish($1,make_list($3)),
822                                 Nullarg); }
823         ;
824
825 handle  :       WORD
826                         { $$ = stab2arg(A_WORD,stabent($1,TRUE));
827                           Safefree($1); $1 = Nullch;}
828         |       sexpr
829         ;
830
831 aryword :       WORD
832                         { $$ = stab2arg(A_WORD,aadd(stabent($1,TRUE)));
833                             Safefree($1); $1 = Nullch; }
834         |       ARY
835                         { $$ = stab2arg(A_STAB,$1); }
836         ;
837
838 hshword :       WORD
839                         { $$ = stab2arg(A_WORD,hadd(stabent($1,TRUE)));
840                             Safefree($1); $1 = Nullch; }
841         |       HSH
842                         { $$ = stab2arg(A_STAB,$1); }
843         ;
844
845 crp     :       ',' ')'
846                         { $$ = 1; }
847         |       ')'
848                         { $$ = 0; }
849         ;
850
851 /*
852  * NOTE:  The following entry must stay at the end of the file so that
853  * reduce/reduce conflicts resolve to it only if it's the only option.
854  */
855
856 bareword:       WORD
857                         { char *s;
858                             $$ = op_new(1);
859                             $$->arg_type = O_ITEM;
860                             $$[1].arg_type = A_SINGLE;
861                             $$[1].arg_ptr.arg_str = str_make($1,0);
862                             for (s = $1; *s && isLOWER(*s); s++) ;
863                             if (dowarn && !*s)
864                                 warn(
865                                   "\"%s\" may clash with future reserved word",
866                                   $1 );
867                             Safefree($1); $1 = Nullch;
868                         }
869                 ;
870 %% /* PROGRAM */