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