a "replacement" for awk and sed
[perl.git] / perl.y
1 /* $Header: perl.y,v 1.0 87/12/18 15:48:59 root Exp $
2  *
3  * $Log:        perl.y,v $
4  * Revision 1.0  87/12/18  15:48:59  root
5  * Initial revision
6  * 
7  */
8
9 %{
10 #include "handy.h"
11 #include "EXTERN.h"
12 #include "search.h"
13 #include "util.h"
14 #include "INTERN.h"
15 #include "perl.h"
16 char *tokename[] = {
17 "256",
18 "word",
19 "append","open","write","select","close","loopctl",
20 "using","format","do","shift","push","pop","chop",
21 "while","until","if","unless","else","elsif","continue","split","sprintf",
22 "for", "eof", "tell", "seek", "stat",
23 "function(no args)","function(1 arg)","function(2 args)","function(3 args)","array function",
24 "join", "sub",
25 "format lines",
26 "register","array_length", "array",
27 "s","pattern",
28 "string","y",
29 "print", "unary operation",
30 "..",
31 "||",
32 "&&",
33 "==","!=", "EQ", "NE",
34 "<=",">=", "LT", "GT", "LE", "GE",
35 "<<",">>",
36 "=~","!~",
37 "unary -",
38 "++", "--",
39 "???"
40 };
41
42 %}
43
44 %start prog
45
46 %union {
47     int ival;
48     char *cval;
49     ARG *arg;
50     CMD *cmdval;
51     struct compcmd compval;
52     STAB *stabval;
53     FCMD *formval;
54 }
55
56 %token <cval> WORD
57 %token <ival> APPEND OPEN WRITE SELECT CLOSE LOOPEX
58 %token <ival> USING FORMAT DO SHIFT PUSH POP CHOP
59 %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT SPRINTF
60 %token <ival> FOR FEOF TELL SEEK STAT 
61 %token <ival> FUNC0 FUNC1 FUNC2 FUNC3 STABFUN
62 %token <ival> JOIN SUB
63 %token <formval> FORMLIST
64 %token <stabval> REG ARYLEN ARY
65 %token <arg> SUBST PATTERN
66 %token <arg> RSTRING TRANS
67
68 %type <ival> prog decl format
69 %type <stabval>
70 %type <cmdval> block lineseq line loop cond sideff nexpr else
71 %type <arg> expr sexpr term
72 %type <arg> condmod loopmod cexpr
73 %type <arg> texpr print
74 %type <cval> label
75 %type <compval> compblock
76
77 %nonassoc <ival> PRINT
78 %left ','
79 %nonassoc <ival> UNIOP
80 %right '='
81 %right '?' ':'
82 %nonassoc DOTDOT
83 %left OROR
84 %left ANDAND
85 %left '|' '^'
86 %left '&'
87 %nonassoc EQ NE SEQ SNE
88 %nonassoc '<' '>' LE GE SLT SGT SLE SGE
89 %left LS RS
90 %left '+' '-' '.'
91 %left '*' '/' '%' 'x'
92 %left MATCH NMATCH 
93 %right '!' '~' UMINUS
94 %nonassoc INC DEC
95 %left '('
96
97 %% /* RULES */
98
99 prog    :       lineseq
100                         { main_root = block_head($1); }
101         ;
102
103 compblock:      block CONTINUE block
104                         { $$.comp_true = $1; $$.comp_alt = $3; }
105         |       block else
106                         { $$.comp_true = $1; $$.comp_alt = $2; }
107         ;
108
109 else    :       /* NULL */
110                         { $$ = Nullcmd; }
111         |       ELSE block
112                         { $$ = $2; }
113         |       ELSIF '(' expr ')' compblock
114                         { $$ = make_ccmd(C_IF,$3,$5); }
115         ;
116
117 block   :       '{' lineseq '}'
118                         { $$ = block_head($2); }
119         ;
120
121 lineseq :       /* NULL */
122                         { $$ = Nullcmd; }
123         |       lineseq line
124                         { $$ = append_line($1,$2); }
125         ;
126
127 line    :       decl
128                         { $$ = Nullcmd; }
129         |       label cond
130                         { $$ = add_label($1,$2); }
131         |       loop    /* loops add their own labels */
132         |       label ';'
133                         { if ($1 != Nullch) {
134                               $$ = add_label(make_acmd(C_EXPR, Nullstab,
135                                   Nullarg, Nullarg) );
136                             } else
137                               $$ = Nullcmd; }
138         |       label sideff ';'
139                         { $$ = add_label($1,$2); }
140         ;
141
142 sideff  :       expr
143                         { $$ = make_acmd(C_EXPR, Nullstab, $1, Nullarg); }
144         |       expr condmod
145                         { $$ = addcond(
146                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $2); }
147         |       expr loopmod
148                         { $$ = addloop(
149                                make_acmd(C_EXPR, Nullstab, Nullarg, $1), $2); }
150         ;
151
152 cond    :       IF '(' expr ')' compblock
153                         { $$ = make_ccmd(C_IF,$3,$5); }
154         |       UNLESS '(' expr ')' compblock
155                         { $$ = invert(make_ccmd(C_IF,$3,$5)); }
156         |       IF block compblock
157                         { $$ = make_ccmd(C_IF,cmd_to_arg($2),$3); }
158         |       UNLESS block compblock
159                         { $$ = invert(make_ccmd(C_IF,cmd_to_arg($2),$3)); }
160         ;
161
162 loop    :       label WHILE '(' texpr ')' compblock
163                         { $$ = wopt(add_label($1,
164                             make_ccmd(C_WHILE,$4,$6) )); }
165         |       label UNTIL '(' expr ')' compblock
166                         { $$ = wopt(add_label($1,
167                             invert(make_ccmd(C_WHILE,$4,$6)) )); }
168         |       label WHILE block compblock
169                         { $$ = wopt(add_label($1,
170                             make_ccmd(C_WHILE, cmd_to_arg($3),$4) )); }
171         |       label UNTIL block compblock
172                         { $$ = wopt(add_label($1,
173                             invert(make_ccmd(C_WHILE, cmd_to_arg($3),$4)) )); }
174         |       label FOR '(' nexpr ';' texpr ';' nexpr ')' block
175                         /* basically fake up an initialize-while lineseq */
176                         {   yyval.compval.comp_true = $10;
177                             yyval.compval.comp_alt = $8;
178                             $$ = append_line($4,wopt(add_label($1,
179                                 make_ccmd(C_WHILE,$6,yyval.compval) ))); }
180         |       label compblock /* a block is a loop that happens once */
181                         { $$ = add_label($1,make_ccmd(C_BLOCK,Nullarg,$2)); }
182         ;
183
184 nexpr   :       /* NULL */
185                         { $$ = Nullcmd; }
186         |       sideff
187         ;
188
189 texpr   :       /* NULL means true */
190                         {   scanstr("1"); $$ = yylval.arg; }
191         |       expr
192         ;
193
194 label   :       /* empty */
195                         { $$ = Nullch; }
196         |       WORD ':'
197         ;
198
199 loopmod :       WHILE expr
200                         { $$ = $2; }
201         |       UNTIL expr
202                         { $$ = make_op(O_NOT,1,$2,Nullarg,Nullarg,0); }
203         ;
204
205 condmod :       IF expr
206                         { $$ = $2; }
207         |       UNLESS expr
208                         { $$ = make_op(O_NOT,1,$2,Nullarg,Nullarg,0); }
209         ;
210
211 decl    :       format
212                         { $$ = 0; }
213         |       subrout
214                         { $$ = 0; }
215         ;
216
217 format  :       FORMAT WORD '=' FORMLIST '.' 
218                         { stabent($2,TRUE)->stab_form = $4; safefree($2); }
219         |       FORMAT '=' FORMLIST '.'
220                         { stabent("stdout",TRUE)->stab_form = $3; }
221         ;
222
223 subrout :       SUB WORD block
224                         { stabent($2,TRUE)->stab_sub = $3; }
225         ;
226
227 expr    :       print
228         |       cexpr
229         ;
230
231 cexpr   :       sexpr ',' cexpr
232                         { $$ = make_op(O_COMMA, 2, $1, $3, Nullarg,0); }
233         |       sexpr
234         ;
235
236 sexpr   :       sexpr '=' sexpr
237                         {   $1 = listish($1);
238                             if ($1->arg_type == O_LIST)
239                                 $3 = listish($3);
240                             $$ = l(make_op(O_ASSIGN, 2, $1, $3, Nullarg,1)); }
241         |       sexpr '*' '=' sexpr
242                         { $$ = l(make_op(O_MULTIPLY, 2, $1, $4, Nullarg,0)); }
243         |       sexpr '/' '=' sexpr
244                         { $$ = l(make_op(O_DIVIDE, 2, $1, $4, Nullarg,0)); }
245         |       sexpr '%' '=' sexpr
246                         { $$ = l(make_op(O_MODULO, 2, $1, $4, Nullarg,0)); }
247         |       sexpr 'x' '=' sexpr
248                         { $$ = l(make_op(O_REPEAT, 2, $1, $4, Nullarg,0)); }
249         |       sexpr '+' '=' sexpr
250                         { $$ = l(make_op(O_ADD, 2, $1, $4, Nullarg,0)); }
251         |       sexpr '-' '=' sexpr
252                         { $$ = l(make_op(O_SUBTRACT, 2, $1, $4, Nullarg,0)); }
253         |       sexpr LS '=' sexpr
254                         { $$ = l(make_op(O_LEFT_SHIFT, 2, $1, $4, Nullarg,0)); }
255         |       sexpr RS '=' sexpr
256                         { $$ = l(make_op(O_RIGHT_SHIFT, 2, $1, $4, Nullarg,0)); }
257         |       sexpr '&' '=' sexpr
258                         { $$ = l(make_op(O_BIT_AND, 2, $1, $4, Nullarg,0)); }
259         |       sexpr '^' '=' sexpr
260                         { $$ = l(make_op(O_XOR, 2, $1, $4, Nullarg,0)); }
261         |       sexpr '|' '=' sexpr
262                         { $$ = l(make_op(O_BIT_OR, 2, $1, $4, Nullarg,0)); }
263         |       sexpr '.' '=' sexpr
264                         { $$ = l(make_op(O_CONCAT, 2, $1, $4, Nullarg,0)); }
265
266
267         |       sexpr '*' sexpr
268                         { $$ = make_op(O_MULTIPLY, 2, $1, $3, Nullarg,0); }
269         |       sexpr '/' sexpr
270                         { $$ = make_op(O_DIVIDE, 2, $1, $3, Nullarg,0); }
271         |       sexpr '%' sexpr
272                         { $$ = make_op(O_MODULO, 2, $1, $3, Nullarg,0); }
273         |       sexpr 'x' sexpr
274                         { $$ = make_op(O_REPEAT, 2, $1, $3, Nullarg,0); }
275         |       sexpr '+' sexpr
276                         { $$ = make_op(O_ADD, 2, $1, $3, Nullarg,0); }
277         |       sexpr '-' sexpr
278                         { $$ = make_op(O_SUBTRACT, 2, $1, $3, Nullarg,0); }
279         |       sexpr LS sexpr
280                         { $$ = make_op(O_LEFT_SHIFT, 2, $1, $3, Nullarg,0); }
281         |       sexpr RS sexpr
282                         { $$ = make_op(O_RIGHT_SHIFT, 2, $1, $3, Nullarg,0); }
283         |       sexpr '<' sexpr
284                         { $$ = make_op(O_LT, 2, $1, $3, Nullarg,0); }
285         |       sexpr '>' sexpr
286                         { $$ = make_op(O_GT, 2, $1, $3, Nullarg,0); }
287         |       sexpr LE sexpr
288                         { $$ = make_op(O_LE, 2, $1, $3, Nullarg,0); }
289         |       sexpr GE sexpr
290                         { $$ = make_op(O_GE, 2, $1, $3, Nullarg,0); }
291         |       sexpr EQ sexpr
292                         { $$ = make_op(O_EQ, 2, $1, $3, Nullarg,0); }
293         |       sexpr NE sexpr
294                         { $$ = make_op(O_NE, 2, $1, $3, Nullarg,0); }
295         |       sexpr SLT sexpr
296                         { $$ = make_op(O_SLT, 2, $1, $3, Nullarg,0); }
297         |       sexpr SGT sexpr
298                         { $$ = make_op(O_SGT, 2, $1, $3, Nullarg,0); }
299         |       sexpr SLE sexpr
300                         { $$ = make_op(O_SLE, 2, $1, $3, Nullarg,0); }
301         |       sexpr SGE sexpr
302                         { $$ = make_op(O_SGE, 2, $1, $3, Nullarg,0); }
303         |       sexpr SEQ sexpr
304                         { $$ = make_op(O_SEQ, 2, $1, $3, Nullarg,0); }
305         |       sexpr SNE sexpr
306                         { $$ = make_op(O_SNE, 2, $1, $3, Nullarg,0); }
307         |       sexpr '&' sexpr
308                         { $$ = make_op(O_BIT_AND, 2, $1, $3, Nullarg,0); }
309         |       sexpr '^' sexpr
310                         { $$ = make_op(O_XOR, 2, $1, $3, Nullarg,0); }
311         |       sexpr '|' sexpr
312                         { $$ = make_op(O_BIT_OR, 2, $1, $3, Nullarg,0); }
313         |       sexpr DOTDOT sexpr
314                         { $$ = make_op(O_FLIP, 4,
315                             flipflip($1),
316                             flipflip($3),
317                             Nullarg,0);}
318         |       sexpr ANDAND sexpr
319                         { $$ = make_op(O_AND, 2, $1, $3, Nullarg,0); }
320         |       sexpr OROR sexpr
321                         { $$ = make_op(O_OR, 2, $1, $3, Nullarg,0); }
322         |       sexpr '?' sexpr ':' sexpr
323                         { $$ = make_op(O_COND_EXPR, 3, $1, $3, $5,0); }
324         |       sexpr '.' sexpr
325                         { $$ = make_op(O_CONCAT, 2, $1, $3, Nullarg,0); }
326         |       sexpr MATCH sexpr
327                         { $$ = mod_match(O_MATCH, $1, $3); }
328         |       sexpr NMATCH sexpr
329                         { $$ = mod_match(O_NMATCH, $1, $3); }
330         |       term INC
331                         { $$ = addflags(1, AF_POST|AF_UP,
332                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg,0))); }
333         |       term DEC
334                         { $$ = addflags(1, AF_POST,
335                             l(make_op(O_ITEM,1,$1,Nullarg,Nullarg,0))); }
336         |       INC term
337                         { $$ = addflags(1, AF_PRE|AF_UP,
338                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg,0))); }
339         |       DEC term
340                         { $$ = addflags(1, AF_PRE,
341                             l(make_op(O_ITEM,1,$2,Nullarg,Nullarg,0))); }
342         |       term
343                         { $$ = $1; }
344         ;
345
346 term    :       '-' term %prec UMINUS
347                         { $$ = make_op(O_NEGATE, 1, $2, Nullarg, Nullarg,0); }
348         |       '!' term
349                         { $$ = make_op(O_NOT, 1, $2, Nullarg, Nullarg,0); }
350         |       '~' term
351                         { $$ = make_op(O_COMPLEMENT, 1, $2, Nullarg, Nullarg,0);}
352         |       '(' expr ')'
353                         { $$ = make_list(hide_ary($2)); }
354         |       '(' ')'
355                         { $$ = make_list(Nullarg); }
356         |       DO block        %prec '('
357                         { $$ = cmd_to_arg($2); }
358         |       REG     %prec '('
359                         { $$ = stab_to_arg(A_STAB,$1); }
360         |       REG '[' expr ']'        %prec '('
361                         { $$ = make_op(O_ARRAY, 2,
362                                 $3, stab_to_arg(A_STAB,aadd($1)), Nullarg,0); }
363         |       ARY     %prec '('
364                         { $$ = make_op(O_ARRAY, 1,
365                                 stab_to_arg(A_STAB,$1),
366                                 Nullarg, Nullarg, 1); }
367         |       REG '{' expr '}'        %prec '('
368                         { $$ = make_op(O_HASH, 2,
369                                 $3, stab_to_arg(A_STAB,hadd($1)), Nullarg,0); }
370         |       ARYLEN  %prec '('
371                         { $$ = stab_to_arg(A_ARYLEN,$1); }
372         |       RSTRING %prec '('
373                         { $$ = $1; }
374         |       PATTERN %prec '('
375                         { $$ = $1; }
376         |       SUBST   %prec '('
377                         { $$ = $1; }
378         |       TRANS   %prec '('
379                         { $$ = $1; }
380         |       DO WORD '(' expr ')'
381                         { $$ = make_op(O_SUBR, 2,
382                                 make_list($4),
383                                 stab_to_arg(A_STAB,stabent($2,TRUE)),
384                                 Nullarg,1); }
385         |       DO WORD '(' ')'
386                         { $$ = make_op(O_SUBR, 2,
387                                 make_list(Nullarg),
388                                 stab_to_arg(A_STAB,stabent($2,TRUE)),
389                                 Nullarg,1); }
390         |       LOOPEX
391                         { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg,0); }
392         |       LOOPEX WORD
393                         { $$ = make_op($1,1,cval_to_arg($2),
394                             Nullarg,Nullarg,0); }
395         |       UNIOP
396                         { $$ = make_op($1,1,Nullarg,Nullarg,Nullarg,0); }
397         |       UNIOP sexpr
398                         { $$ = make_op($1,1,$2,Nullarg,Nullarg,0); }
399         |       WRITE
400                         { $$ = make_op(O_WRITE, 0,
401                             Nullarg, Nullarg, Nullarg,0); }
402         |       WRITE '(' ')'
403                         { $$ = make_op(O_WRITE, 0,
404                             Nullarg, Nullarg, Nullarg,0); }
405         |       WRITE '(' WORD ')'
406                         { $$ = l(make_op(O_WRITE, 1,
407                             stab_to_arg(A_STAB,stabent($3,TRUE)),
408                             Nullarg, Nullarg,0)); safefree($3); }
409         |       WRITE '(' expr ')'
410                         { $$ = make_op(O_WRITE, 1, $3, Nullarg, Nullarg,0); }
411         |       SELECT '(' WORD ')'
412                         { $$ = l(make_op(O_SELECT, 1,
413                             stab_to_arg(A_STAB,stabent($3,TRUE)),
414                             Nullarg, Nullarg,0)); safefree($3); }
415         |       SELECT '(' expr ')'
416                         { $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg,0); }
417         |       OPEN WORD       %prec '('
418                         { $$ = make_op(O_OPEN, 2,
419                             stab_to_arg(A_STAB,stabent($2,TRUE)),
420                             stab_to_arg(A_STAB,stabent($2,TRUE)),
421                             Nullarg,0); }
422         |       OPEN '(' WORD ')'
423                         { $$ = make_op(O_OPEN, 2,
424                             stab_to_arg(A_STAB,stabent($3,TRUE)),
425                             stab_to_arg(A_STAB,stabent($3,TRUE)),
426                             Nullarg,0); }
427         |       OPEN '(' WORD ',' expr ')'
428                         { $$ = make_op(O_OPEN, 2,
429                             stab_to_arg(A_STAB,stabent($3,TRUE)),
430                             $5, Nullarg,0); }
431         |       CLOSE '(' WORD ')'
432                         { $$ = make_op(O_CLOSE, 1,
433                             stab_to_arg(A_STAB,stabent($3,TRUE)),
434                             Nullarg, Nullarg,0); }
435         |       CLOSE WORD      %prec '('
436                         { $$ = make_op(O_CLOSE, 1,
437                             stab_to_arg(A_STAB,stabent($2,TRUE)),
438                             Nullarg, Nullarg,0); }
439         |       FEOF '(' WORD ')'
440                         { $$ = make_op(O_EOF, 1,
441                             stab_to_arg(A_STAB,stabent($3,TRUE)),
442                             Nullarg, Nullarg,0); }
443         |       FEOF '(' ')'
444                         { $$ = make_op(O_EOF, 0,
445                             stab_to_arg(A_STAB,stabent("ARGV",TRUE)),
446                             Nullarg, Nullarg,0); }
447         |       FEOF
448                         { $$ = make_op(O_EOF, 0,
449                             Nullarg, Nullarg, Nullarg,0); }
450         |       TELL '(' WORD ')'
451                         { $$ = make_op(O_TELL, 1,
452                             stab_to_arg(A_STAB,stabent($3,TRUE)),
453                             Nullarg, Nullarg,0); }
454         |       TELL
455                         { $$ = make_op(O_TELL, 0,
456                             Nullarg, Nullarg, Nullarg,0); }
457         |       SEEK '(' WORD ',' sexpr ',' expr ')'
458                         { $$ = make_op(O_SEEK, 3,
459                             stab_to_arg(A_STAB,stabent($3,TRUE)),
460                             $5, $7,1); }
461         |       PUSH '(' WORD ',' expr ')'
462                         { $$ = make_op($1, 2,
463                             make_list($5),
464                             stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
465                             Nullarg,1); }
466         |       PUSH '(' ARY ',' expr ')'
467                         { $$ = make_op($1, 2,
468                             make_list($5),
469                             stab_to_arg(A_STAB,$3),
470                             Nullarg,1); }
471         |       POP WORD        %prec '('
472                         { $$ = make_op(O_POP, 1,
473                             stab_to_arg(A_STAB,aadd(stabent($2,TRUE))),
474                             Nullarg, Nullarg,0); }
475         |       POP '(' WORD ')'
476                         { $$ = make_op(O_POP, 1,
477                             stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
478                             Nullarg, Nullarg,0); }
479         |       POP ARY %prec '('
480                         { $$ = make_op(O_POP, 1,
481                             stab_to_arg(A_STAB,$2),
482                             Nullarg,
483                             Nullarg,
484                             0); }
485         |       POP '(' ARY ')'
486                         { $$ = make_op(O_POP, 1,
487                             stab_to_arg(A_STAB,$3),
488                             Nullarg,
489                             Nullarg,
490                             0); }
491         |       SHIFT WORD      %prec '('
492                         { $$ = make_op(O_SHIFT, 1,
493                             stab_to_arg(A_STAB,aadd(stabent($2,TRUE))),
494                             Nullarg, Nullarg,0); }
495         |       SHIFT '(' WORD ')'
496                         { $$ = make_op(O_SHIFT, 1,
497                             stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
498                             Nullarg, Nullarg,0); }
499         |       SHIFT ARY       %prec '('
500                         { $$ = make_op(O_SHIFT, 1,
501                             stab_to_arg(A_STAB,$2), Nullarg, Nullarg,0); }
502         |       SHIFT '(' ARY ')'
503                         { $$ = make_op(O_SHIFT, 1,
504                             stab_to_arg(A_STAB,$3), Nullarg, Nullarg,0); }
505         |       SHIFT   %prec '('
506                         { $$ = make_op(O_SHIFT, 1,
507                             stab_to_arg(A_STAB,aadd(stabent("ARGV",TRUE))),
508                             Nullarg, Nullarg,0); }
509         |       SPLIT   %prec '('
510                         { scanpat("/[ \t\n]+/");
511                             $$ = make_split(defstab,yylval.arg); }
512         |       SPLIT '(' WORD ')'
513                         { scanpat("/[ \t\n]+/");
514                             $$ = make_split(stabent($3,TRUE),yylval.arg); }
515         |       SPLIT '(' WORD ',' PATTERN ')'
516                         { $$ = make_split(stabent($3,TRUE),$5); }
517         |       SPLIT '(' WORD ',' PATTERN ',' sexpr ')'
518                         { $$ = mod_match(O_MATCH,
519                             $7,
520                             make_split(stabent($3,TRUE),$5) ); }
521         |       SPLIT '(' sexpr ',' sexpr ')'
522                         { $$ = mod_match(O_MATCH, $5, make_split(defstab,$3) ); }
523         |       SPLIT '(' sexpr ')'
524                         { $$ = mod_match(O_MATCH,
525                             stab_to_arg(A_STAB,defstab),
526                             make_split(defstab,$3) ); }
527         |       JOIN '(' WORD ',' expr ')'
528                         { $$ = make_op(O_JOIN, 2,
529                             $5,
530                             stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
531                             Nullarg,0); }
532         |       JOIN '(' sexpr ',' expr ')'
533                         { $$ = make_op(O_JOIN, 2,
534                             $3,
535                             make_list($5),
536                             Nullarg,2); }
537         |       SPRINTF '(' expr ')'
538                         { $$ = make_op(O_SPRINTF, 1,
539                             make_list($3),
540                             Nullarg,
541                             Nullarg,1); }
542         |       STAT '(' WORD ')'
543                         { $$ = l(make_op(O_STAT, 1,
544                             stab_to_arg(A_STAB,stabent($3,TRUE)),
545                             Nullarg, Nullarg,0)); }
546         |       STAT '(' expr ')'
547                         { $$ = make_op(O_STAT, 1, $3, Nullarg, Nullarg,0); }
548         |       CHOP
549                         { $$ = l(make_op(O_CHOP, 1,
550                             stab_to_arg(A_STAB,defstab),
551                             Nullarg, Nullarg,0)); }
552         |       CHOP '(' expr ')'
553                         { $$ = l(make_op(O_CHOP, 1, $3, Nullarg, Nullarg,0)); }
554         |       FUNC0
555                         { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg,0); }
556         |       FUNC1 '(' expr ')'
557                         { $$ = make_op($1, 1, $3, Nullarg, Nullarg,0); }
558         |       FUNC2 '(' sexpr ',' expr ')'
559                         { $$ = make_op($1, 2, $3, $5, Nullarg, 0); }
560         |       FUNC3 '(' sexpr ',' sexpr ',' expr ')'
561                         { $$ = make_op($1, 3, $3, $5, $7, 0); }
562         |       STABFUN '(' WORD ')'
563                         { $$ = make_op($1, 1,
564                                 stab_to_arg(A_STAB,hadd(stabent($3,TRUE))),
565                                 Nullarg,
566                                 Nullarg, 0); }
567         ;
568
569 print   :       PRINT
570                         { $$ = make_op($1,2,
571                                 stab_to_arg(A_STAB,defstab),
572                                 stab_to_arg(A_STAB,Nullstab),
573                                 Nullarg,0); }
574         |       PRINT expr
575                         { $$ = make_op($1,2,make_list($2),
576                                 stab_to_arg(A_STAB,Nullstab),
577                                 Nullarg,1); }
578         |       PRINT WORD
579                         { $$ = make_op($1,2,
580                                 stab_to_arg(A_STAB,defstab),
581                                 stab_to_arg(A_STAB,stabent($2,TRUE)),
582                                 Nullarg,1); }
583         |       PRINT WORD expr
584                         { $$ = make_op($1,2,make_list($3),
585                                 stab_to_arg(A_STAB,stabent($2,TRUE)),
586                                 Nullarg,1); }
587         ;
588
589 %% /* PROGRAM */
590 #include "perly.c"