ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/perly.y
Revision: 1.1
Committed: Thu Jun 30 14:26:42 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /* perly.y
2     *
3     * Copyright (c) 1991-2002, 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     */
9    
10     /*
11     * 'I see,' laughed Strider. 'I look foul and feel fair. Is that it?
12     * All that is gold does not glitter, not all those who wander are lost.'
13     */
14    
15     /* This file holds the grammar for the Perl language. If edited, you need
16     * to run regen_perly.pl, which re-creates the files perly.h, perly.tab
17     * and perly.act which are derived from this.
18     *
19     * The main job of of this grammar is to call the various newFOO()
20     * functions in op.c to build a syntax tree of OP structs.
21     * It relies on the lexer in toke.c to do the tokenizing.
22     */
23    
24     %{
25     #include "EXTERN.h"
26     #define PERL_IN_PERLY_C
27     #include "perl.h"
28     #ifdef EBCDIC
29     #undef YYDEBUG
30     #endif
31     #define dep() deprecate("\"do\" to call subroutines")
32    
33     /* stuff included here to make perly_c.diff apply better */
34    
35     #define yydebug PL_yydebug
36     #define yynerrs PL_yynerrs
37     #define yyerrflag PL_yyerrflag
38     #define yychar PL_yychar
39     #define yyval PL_yyval
40     #define yylval PL_yylval
41    
42     struct ysv {
43     short* yyss;
44     YYSTYPE* yyvs;
45     int oldyydebug;
46     int oldyynerrs;
47     int oldyyerrflag;
48     int oldyychar;
49     YYSTYPE oldyyval;
50     YYSTYPE oldyylval;
51     };
52    
53     static void yydestruct(pTHX_ void *ptr);
54    
55     %}
56    
57     %start prog
58    
59     %{
60     #if 0 /* get this from perly.h instead */
61     %}
62    
63     %union {
64     I32 ival;
65     char *pval;
66     OP *opval;
67     GV *gvval;
68     }
69    
70     %{
71     #endif /* 0 */
72    
73     #ifdef USE_PURE_BISON
74     #define YYLEX_PARAM (&yychar)
75     #define yylex yylex_r
76     #endif
77    
78     %}
79    
80     %token <ival> '{'
81    
82     %token <opval> WORD METHOD FUNCMETH THING PMFUNC PRIVATEREF
83     %token <opval> FUNC0SUB UNIOPSUB LSTOPSUB
84     %token <pval> LABEL
85     %token <ival> FORMAT SUB ANONSUB PACKAGE USE
86     %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE FOR
87     %token <ival> LOOPEX DOTDOT
88     %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP
89     %token <ival> RELOP EQOP MULOP ADDOP
90     %token <ival> DOLSHARP DO HASHBRACK NOAMP
91     %token <ival> LOCAL MY MYSUB
92     %token COLONATTR
93    
94     %type <ival> prog decl format startsub startanonsub startformsub
95     %type <ival> progstart remember mremember '&'
96     %type <opval> block mblock lineseq line loop cond else
97     %type <opval> expr term subscripted scalar ary hsh arylen star amper sideff
98     %type <opval> argexpr nexpr texpr iexpr mexpr mnexpr mtexpr miexpr
99     %type <opval> listexpr listexprcom indirob listop method
100     %type <opval> formname subname proto subbody cont my_scalar
101     %type <opval> subattrlist myattrlist mysubrout myattrterm myterm
102     %type <opval> termbinop termunop anonymous termdo
103     %type <pval> label
104    
105     %nonassoc PREC_LOW
106     %nonassoc LOOPEX
107    
108     %left <ival> OROP
109     %left ANDOP
110     %right NOTOP
111     %nonassoc LSTOP LSTOPSUB
112     %left ','
113     %right <ival> ASSIGNOP
114     %right '?' ':'
115     %nonassoc DOTDOT
116     %left OROR
117     %left ANDAND
118     %left <ival> BITOROP
119     %left <ival> BITANDOP
120     %nonassoc EQOP
121     %nonassoc RELOP
122     %nonassoc UNIOP UNIOPSUB
123     %left <ival> SHIFTOP
124     %left ADDOP
125     %left MULOP
126     %left <ival> MATCHOP
127     %right '!' '~' UMINUS REFGEN
128     %right <ival> POWOP
129     %nonassoc PREINC PREDEC POSTINC POSTDEC
130     %left ARROW
131     %nonassoc <ival> ')'
132     %left '('
133     %left '[' '{'
134    
135     %% /* RULES */
136    
137     /* The whole program */
138     prog : progstart
139     /*CONTINUED*/ lineseq
140     { $$ = $1; newPROG(block_end($1,$2)); }
141     ;
142    
143     /* An ordinary block */
144     block : '{' remember lineseq '}'
145     { if (PL_copline > (line_t)$1)
146     PL_copline = (line_t)$1;
147     $$ = block_end($2, $3); }
148     ;
149    
150     remember: /* NULL */ /* start a full lexical scope */
151     { $$ = block_start(TRUE); }
152     ;
153    
154     progstart:
155     {
156     #if defined(YYDEBUG) && defined(DEBUGGING)
157     yydebug = (DEBUG_p_TEST);
158     #endif
159     PL_expect = XSTATE; $$ = block_start(TRUE);
160     }
161     ;
162    
163    
164     mblock : '{' mremember lineseq '}'
165     { if (PL_copline > (line_t)$1)
166     PL_copline = (line_t)$1;
167     $$ = block_end($2, $3); }
168     ;
169    
170     mremember: /* NULL */ /* start a partial lexical scope */
171     { $$ = block_start(FALSE); }
172     ;
173    
174     /* A collection of "lines" in the program */
175     lineseq : /* NULL */
176     { $$ = Nullop; }
177     | lineseq decl
178     { $$ = $1; }
179     | lineseq line
180     { $$ = append_list(OP_LINESEQ,
181     (LISTOP*)$1, (LISTOP*)$2);
182     PL_pad_reset_pending = TRUE;
183     if ($1 && $2) PL_hints |= HINT_BLOCK_SCOPE; }
184     ;
185    
186     /* A "line" in the program */
187     line : label cond
188     { $$ = newSTATEOP(0, $1, $2); }
189     | loop /* loops add their own labels */
190     | label ';'
191     { if ($1 != Nullch) {
192     $$ = newSTATEOP(0, $1, newOP(OP_NULL, 0));
193     }
194     else {
195     $$ = Nullop;
196     PL_copline = NOLINE;
197     }
198     PL_expect = XSTATE; }
199     | label sideff ';'
200     { $$ = newSTATEOP(0, $1, $2);
201     PL_expect = XSTATE; }
202     ;
203    
204     /* An expression which may have a side-effect */
205     sideff : error
206     { $$ = Nullop; }
207     | expr
208     { $$ = $1; }
209     | expr IF expr
210     { $$ = newLOGOP(OP_AND, 0, $3, $1); }
211     | expr UNLESS expr
212     { $$ = newLOGOP(OP_OR, 0, $3, $1); }
213     | expr WHILE expr
214     { $$ = newLOOPOP(OPf_PARENS, 1, scalar($3), $1); }
215     | expr UNTIL iexpr
216     { $$ = newLOOPOP(OPf_PARENS, 1, $3, $1);}
217     | expr FOR expr
218     { $$ = newFOROP(0, Nullch, (line_t)$2,
219     Nullop, $3, $1, Nullop); }
220     ;
221    
222     /* else and elsif blocks */
223     else : /* NULL */
224     { $$ = Nullop; }
225     | ELSE mblock
226     { ($2)->op_flags |= OPf_PARENS; $$ = scope($2); }
227     | ELSIF '(' mexpr ')' mblock else
228     { PL_copline = (line_t)$1;
229     $$ = newCONDOP(0, $3, scope($5), $6);
230     PL_hints |= HINT_BLOCK_SCOPE; }
231     ;
232    
233     /* Real conditional expressions */
234     cond : IF '(' remember mexpr ')' mblock else
235     { PL_copline = (line_t)$1;
236     $$ = block_end($3,
237     newCONDOP(0, $4, scope($6), $7)); }
238     | UNLESS '(' remember miexpr ')' mblock else
239     { PL_copline = (line_t)$1;
240     $$ = block_end($3,
241     newCONDOP(0, $4, scope($6), $7)); }
242     ;
243    
244     /* Continue blocks */
245     cont : /* NULL */
246     { $$ = Nullop; }
247     | CONTINUE block
248     { $$ = scope($2); }
249     ;
250    
251     /* Loops: while, until, for, and a bare block */
252     loop : label WHILE '(' remember mtexpr ')' mblock cont
253     { PL_copline = (line_t)$2;
254     $$ = block_end($4,
255     newSTATEOP(0, $1,
256     newWHILEOP(0, 1, (LOOP*)Nullop,
257     $2, $5, $7, $8))); }
258     | label UNTIL '(' remember miexpr ')' mblock cont
259     { PL_copline = (line_t)$2;
260     $$ = block_end($4,
261     newSTATEOP(0, $1,
262     newWHILEOP(0, 1, (LOOP*)Nullop,
263     $2, $5, $7, $8))); }
264     | label FOR MY remember my_scalar '(' mexpr ')' mblock cont
265     { $$ = block_end($4,
266     newFOROP(0, $1, (line_t)$2, $5, $7, $9, $10)); }
267     | label FOR scalar '(' remember mexpr ')' mblock cont
268     { $$ = block_end($5,
269     newFOROP(0, $1, (line_t)$2, mod($3, OP_ENTERLOOP),
270     $6, $8, $9)); }
271     | label FOR '(' remember mexpr ')' mblock cont
272     { $$ = block_end($4,
273     newFOROP(0, $1, (line_t)$2, Nullop, $5, $7, $8)); }
274     | label FOR '(' remember mnexpr ';' mtexpr ';' mnexpr ')' mblock
275     /* basically fake up an initialize-while lineseq */
276     { OP *forop;
277     PL_copline = (line_t)$2;
278     forop = newSTATEOP(0, $1,
279     newWHILEOP(0, 1, (LOOP*)Nullop,
280     $2, scalar($7),
281     $11, $9));
282     if ($5) {
283     forop = append_elem(OP_LINESEQ,
284     newSTATEOP(0, ($1?savepv($1):Nullch),
285     $5),
286     forop);
287     }
288    
289     $$ = block_end($4, forop); }
290     | label block cont /* a block is a loop that happens once */
291     { $$ = newSTATEOP(0, $1,
292     newWHILEOP(0, 1, (LOOP*)Nullop,
293     NOLINE, Nullop, $2, $3)); }
294     ;
295    
296     /* Normal expression */
297     nexpr : /* NULL */
298     { $$ = Nullop; }
299     | sideff
300     ;
301    
302     /* Boolean expression */
303     texpr : /* NULL means true */
304     { (void)scan_num("1", &yylval); $$ = yylval.opval; }
305     | expr
306     ;
307    
308     /* Inverted boolean expression */
309     iexpr : expr
310     { $$ = invert(scalar($1)); }
311     ;
312    
313     /* Expression with its own lexical scope */
314     mexpr : expr
315     { $$ = $1; intro_my(); }
316     ;
317    
318     mnexpr : nexpr
319     { $$ = $1; intro_my(); }
320     ;
321    
322     mtexpr : texpr
323     { $$ = $1; intro_my(); }
324     ;
325    
326     miexpr : iexpr
327     { $$ = $1; intro_my(); }
328     ;
329    
330     /* Optional "MAIN:"-style loop labels */
331     label : /* empty */
332     { $$ = Nullch; }
333     | LABEL
334     ;
335    
336     /* Some kind of declaration - does not take part in the parse tree */
337     decl : format
338     { $$ = 0; }
339     | subrout
340     { $$ = 0; }
341     | mysubrout
342     { $$ = 0; }
343     | package
344     { $$ = 0; }
345     | use
346     { $$ = 0; }
347     ;
348    
349     format : FORMAT startformsub formname block
350     { newFORM($2, $3, $4); }
351     ;
352    
353     formname: WORD { $$ = $1; }
354     | /* NULL */ { $$ = Nullop; }
355     ;
356    
357     /* Unimplemented "my sub foo { }" */
358     mysubrout: MYSUB startsub subname proto subattrlist subbody
359     { newMYSUB($2, $3, $4, $5, $6); }
360     ;
361    
362     /* Subroutine definition */
363     subrout : SUB startsub subname proto subattrlist subbody
364     { newATTRSUB($2, $3, $4, $5, $6); }
365     ;
366    
367     startsub: /* NULL */ /* start a regular subroutine scope */
368     { $$ = start_subparse(FALSE, 0); }
369     ;
370    
371     startanonsub: /* NULL */ /* start an anonymous subroutine scope */
372     { $$ = start_subparse(FALSE, CVf_ANON); }
373     ;
374    
375     startformsub: /* NULL */ /* start a format subroutine scope */
376     { $$ = start_subparse(TRUE, 0); }
377     ;
378    
379     /* Name of a subroutine - must be a bareword, could be special */
380     subname : WORD { STRLEN n_a; char *name = SvPV(((SVOP*)$1)->op_sv,n_a);
381     if (strEQ(name, "BEGIN") || strEQ(name, "END")
382     || strEQ(name, "INIT") || strEQ(name, "CHECK"))
383     CvSPECIAL_on(PL_compcv);
384     $$ = $1; }
385     ;
386    
387     /* Subroutine prototype */
388     proto : /* NULL */
389     { $$ = Nullop; }
390     | THING
391     ;
392    
393     /* Optional list of subroutine attributes */
394     subattrlist: /* NULL */
395     { $$ = Nullop; }
396     | COLONATTR THING
397     { $$ = $2; }
398     | COLONATTR
399     { $$ = Nullop; }
400     ;
401    
402     /* List of attributes for a "my" variable declaration */
403     myattrlist: COLONATTR THING
404     { $$ = $2; }
405     | COLONATTR
406     { $$ = Nullop; }
407     ;
408    
409     /* Subroutine body - either null or a block */
410     subbody : block { $$ = $1; }
411     | ';' { $$ = Nullop; PL_expect = XSTATE; }
412     ;
413    
414     package : PACKAGE WORD ';'
415     { package($2); }
416     | PACKAGE ';'
417     { package(Nullop); }
418     ;
419    
420     use : USE startsub
421     { CvSPECIAL_on(PL_compcv); /* It's a BEGIN {} */ }
422     WORD WORD listexpr ';'
423     { utilize($1, $2, $4, $5, $6); }
424     ;
425    
426     /* Ordinary expressions; logical combinations */
427     expr : expr ANDOP expr
428     { $$ = newLOGOP(OP_AND, 0, $1, $3); }
429     | expr OROP expr
430     { $$ = newLOGOP($2, 0, $1, $3); }
431     | argexpr %prec PREC_LOW
432     ;
433    
434     /* Expressions are a list of terms joined by commas */
435     argexpr : argexpr ','
436     { $$ = $1; }
437     | argexpr ',' term
438     { $$ = append_elem(OP_LIST, $1, $3); }
439     | term %prec PREC_LOW
440     ;
441    
442     /* List operators */
443     listop : LSTOP indirob argexpr /* map {...} @args or print $fh @args */
444     { $$ = convert($1, OPf_STACKED,
445     prepend_elem(OP_LIST, newGVREF($1,$2), $3) ); }
446     | FUNC '(' indirob expr ')' /* print ($fh @args */
447     { $$ = convert($1, OPf_STACKED,
448     prepend_elem(OP_LIST, newGVREF($1,$3), $4) ); }
449     | term ARROW method '(' listexprcom ')' /* $foo->bar(list) */
450     { $$ = convert(OP_ENTERSUB, OPf_STACKED,
451     append_elem(OP_LIST,
452     prepend_elem(OP_LIST, scalar($1), $5),
453     newUNOP(OP_METHOD, 0, $3))); }
454     | term ARROW method /* $foo->bar */
455     { $$ = convert(OP_ENTERSUB, OPf_STACKED,
456     append_elem(OP_LIST, scalar($1),
457     newUNOP(OP_METHOD, 0, $3))); }
458     | METHOD indirob listexpr /* new Class @args */
459     { $$ = convert(OP_ENTERSUB, OPf_STACKED,
460     append_elem(OP_LIST,
461     prepend_elem(OP_LIST, $2, $3),
462     newUNOP(OP_METHOD, 0, $1))); }
463     | FUNCMETH indirob '(' listexprcom ')' /* method $object (@args) */
464     { $$ = convert(OP_ENTERSUB, OPf_STACKED,
465     append_elem(OP_LIST,
466     prepend_elem(OP_LIST, $2, $4),
467     newUNOP(OP_METHOD, 0, $1))); }
468     | LSTOP listexpr /* print @args */
469     { $$ = convert($1, 0, $2); }
470     | FUNC '(' listexprcom ')' /* print (@args) */
471     { $$ = convert($1, 0, $3); }
472     | LSTOPSUB startanonsub block /* sub f(&@); f { foo } ... */
473     { $3 = newANONATTRSUB($2, 0, Nullop, $3); }
474     listexpr %prec LSTOP /* ... @bar */
475     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
476     append_elem(OP_LIST,
477     prepend_elem(OP_LIST, $3, $5), $1)); }
478     ;
479    
480     /* Names of methods. May use $object->$methodname */
481     method : METHOD
482     | scalar
483     ;
484    
485     /* Some kind of subscripted expression */
486     subscripted: star '{' expr ';' '}' /* *main::{something} */
487     /* In this and all the hash accessors, ';' is
488     * provided by the tokeniser */
489     { $$ = newBINOP(OP_GELEM, 0, $1, scalar($3));
490     PL_expect = XOPERATOR; }
491     | scalar '[' expr ']' /* $array[$element] */
492     { $$ = newBINOP(OP_AELEM, 0, oopsAV($1), scalar($3)); }
493     | term ARROW '[' expr ']' /* somearef->[$element] */
494     { $$ = newBINOP(OP_AELEM, 0,
495     ref(newAVREF($1),OP_RV2AV),
496     scalar($4));}
497     | subscripted '[' expr ']' /* $foo->[$bar]->[$baz] */
498     { $$ = newBINOP(OP_AELEM, 0,
499     ref(newAVREF($1),OP_RV2AV),
500     scalar($3));}
501     | scalar '{' expr ';' '}' /* $foo->{bar();} */
502     { $$ = newBINOP(OP_HELEM, 0, oopsHV($1), jmaybe($3));
503     PL_expect = XOPERATOR; }
504     | term ARROW '{' expr ';' '}' /* somehref->{bar();} */
505     { $$ = newBINOP(OP_HELEM, 0,
506     ref(newHVREF($1),OP_RV2HV),
507     jmaybe($4));
508     PL_expect = XOPERATOR; }
509     | subscripted '{' expr ';' '}' /* $foo->[bar]->{baz;} */
510     { $$ = newBINOP(OP_HELEM, 0,
511     ref(newHVREF($1),OP_RV2HV),
512     jmaybe($3));
513     PL_expect = XOPERATOR; }
514     | term ARROW '(' ')' /* $subref->() */
515     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
516     newCVREF(0, scalar($1))); }
517     | term ARROW '(' expr ')' /* $subref->(@args) */
518     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
519     append_elem(OP_LIST, $4,
520     newCVREF(0, scalar($1)))); }
521    
522     | subscripted '(' expr ')' /* $foo->{bar}->(@args) */
523     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
524     append_elem(OP_LIST, $3,
525     newCVREF(0, scalar($1)))); }
526     | subscripted '(' ')' /* $foo->{bar}->() */
527     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
528     newCVREF(0, scalar($1))); }
529     ;
530    
531     /* Binary operators between terms */
532     termbinop : term ASSIGNOP term /* $x = $y */
533     { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }
534     | term POWOP term /* $x ** $y */
535     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
536     | term MULOP term /* $x * $y, $x x $y */
537     { if ($2 != OP_REPEAT)
538     scalar($1);
539     $$ = newBINOP($2, 0, $1, scalar($3)); }
540     | term ADDOP term /* $x + $y */
541     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
542     | term SHIFTOP term /* $x >> $y, $x << $y */
543     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
544     | term RELOP term /* $x > $y, etc. */
545     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
546     | term EQOP term /* $x == $y, $x eq $y */
547     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
548     | term BITANDOP term /* $x & $y */
549     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
550     | term BITOROP term /* $x | $y */
551     { $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
552     | term DOTDOT term /* $x..$y, $x...$y */
553     { $$ = newRANGE($2, scalar($1), scalar($3));}
554     | term ANDAND term /* $x && $y */
555     { $$ = newLOGOP(OP_AND, 0, $1, $3); }
556     | term OROR term /* $x || $y */
557     { $$ = newLOGOP(OP_OR, 0, $1, $3); }
558     | term MATCHOP term /* $x =~ /$y/ */
559     { $$ = bind_match($2, $1, $3); }
560     ;
561    
562     /* Unary operators and terms */
563     termunop : '-' term %prec UMINUS /* -$x */
564     { $$ = newUNOP(OP_NEGATE, 0, scalar($2)); }
565     | '+' term %prec UMINUS /* +$x */
566     { $$ = $2; }
567     | '!' term /* !$x */
568     { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
569     | '~' term /* ~$x */
570     { $$ = newUNOP(OP_COMPLEMENT, 0, scalar($2));}
571     | term POSTINC /* $x++ */
572     { $$ = newUNOP(OP_POSTINC, 0,
573     mod(scalar($1), OP_POSTINC)); }
574     | term POSTDEC /* $x-- */
575     { $$ = newUNOP(OP_POSTDEC, 0,
576     mod(scalar($1), OP_POSTDEC)); }
577     | PREINC term /* ++$x */
578     { $$ = newUNOP(OP_PREINC, 0,
579     mod(scalar($2), OP_PREINC)); }
580     | PREDEC term /* --$x */
581     { $$ = newUNOP(OP_PREDEC, 0,
582     mod(scalar($2), OP_PREDEC)); }
583    
584     ;
585    
586     /* Constructors for anonymous data */
587     anonymous: '[' expr ']'
588     { $$ = newANONLIST($2); }
589     | '[' ']'
590     { $$ = newANONLIST(Nullop); }
591     | HASHBRACK expr ';' '}' %prec '(' /* { foo => "Bar" } */
592     { $$ = newANONHASH($2); }
593     | HASHBRACK ';' '}' %prec '(' /* { } (';' by tokener) */
594     { $$ = newANONHASH(Nullop); }
595     | ANONSUB startanonsub proto subattrlist block %prec '('
596     { $$ = newANONATTRSUB($2, $3, $4, $5); }
597    
598     ;
599    
600     /* Things called with "do" */
601     termdo : DO term %prec UNIOP /* do $filename */
602     { $$ = dofile($2); }
603     | DO block %prec '(' /* do { code */
604     { $$ = newUNOP(OP_NULL, OPf_SPECIAL, scope($2)); }
605     | DO WORD '(' ')' /* do somesub() */
606     { $$ = newUNOP(OP_ENTERSUB,
607     OPf_SPECIAL|OPf_STACKED,
608     prepend_elem(OP_LIST,
609     scalar(newCVREF(
610     (OPpENTERSUB_AMPER<<8),
611     scalar($2)
612     )),Nullop)); dep();}
613     | DO WORD '(' expr ')' /* do somesub(@args) */
614     { $$ = newUNOP(OP_ENTERSUB,
615     OPf_SPECIAL|OPf_STACKED,
616     append_elem(OP_LIST,
617     $4,
618     scalar(newCVREF(
619     (OPpENTERSUB_AMPER<<8),
620     scalar($2)
621     )))); dep();}
622     | DO scalar '(' ')' /* do $subref () */
623     { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
624     prepend_elem(OP_LIST,
625     scalar(newCVREF(0,scalar($2))), Nullop)); dep();}
626     | DO scalar '(' expr ')' /* do $subref (@args) */
627     { $$ = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
628     prepend_elem(OP_LIST,
629     $4,
630     scalar(newCVREF(0,scalar($2))))); dep();}
631    
632     ;
633    
634     term : termbinop
635     | termunop
636     | anonymous
637     | termdo
638     | term '?' term ':' term
639     { $$ = newCONDOP(0, $1, $3, $5); }
640     | REFGEN term /* \$x, \@y, \%z */
641     { $$ = newUNOP(OP_REFGEN, 0, mod($2,OP_REFGEN)); }
642     | myattrterm %prec UNIOP
643     { $$ = $1; }
644     | LOCAL term %prec UNIOP
645     { $$ = localize($2,$1); }
646     | '(' expr ')'
647     { $$ = sawparens($2); }
648     | '(' ')'
649     { $$ = sawparens(newNULLLIST()); }
650     | scalar %prec '('
651     { $$ = $1; }
652     | star %prec '('
653     { $$ = $1; }
654     | hsh %prec '('
655     { $$ = $1; }
656     | ary %prec '('
657     { $$ = $1; }
658     | arylen %prec '(' /* $#x, $#{ something } */
659     { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
660     | subscripted
661     { $$ = $1; }
662     | '(' expr ')' '[' expr ']' /* list slice */
663     { $$ = newSLICEOP(0, $5, $2); }
664     | '(' ')' '[' expr ']' /* empty list slice! */
665     { $$ = newSLICEOP(0, $4, Nullop); }
666     | ary '[' expr ']' /* array slice */
667     { $$ = prepend_elem(OP_ASLICE,
668     newOP(OP_PUSHMARK, 0),
669     newLISTOP(OP_ASLICE, 0,
670     list($3),
671     ref($1, OP_ASLICE))); }
672     | ary '{' expr ';' '}' /* @hash{@keys} */
673     { $$ = prepend_elem(OP_HSLICE,
674     newOP(OP_PUSHMARK, 0),
675     newLISTOP(OP_HSLICE, 0,
676     list($3),
677     ref(oopsHV($1), OP_HSLICE)));
678     PL_expect = XOPERATOR; }
679     | THING %prec '('
680     { $$ = $1; }
681     | amper /* &foo; */
682     { $$ = newUNOP(OP_ENTERSUB, 0, scalar($1)); }
683     | amper '(' ')' /* &foo() */
684     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar($1)); }
685     | amper '(' expr ')' /* &foo(@args) */
686     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
687     append_elem(OP_LIST, $3, scalar($1))); }
688     | NOAMP WORD listexpr /* foo(@args) */
689     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
690     append_elem(OP_LIST, $3, scalar($2))); }
691     | LOOPEX /* loop exiting command (goto, last, dump, etc) */
692     { $$ = newOP($1, OPf_SPECIAL);
693     PL_hints |= HINT_BLOCK_SCOPE; }
694     | LOOPEX term
695     { $$ = newLOOPEX($1,$2); }
696     | NOTOP argexpr /* not $foo */
697     { $$ = newUNOP(OP_NOT, 0, scalar($2)); }
698     | UNIOP /* Unary op, $_ implied */
699     { $$ = newOP($1, 0); }
700     | UNIOP block /* eval { foo }, I *think* */
701     { $$ = newUNOP($1, 0, $2); }
702     | UNIOP term /* Unary op */
703     { $$ = newUNOP($1, 0, $2); }
704     | UNIOPSUB term /* Sub treated as unop */
705     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
706     append_elem(OP_LIST, $2, scalar($1))); }
707     | FUNC0 /* Nullary operator */
708     { $$ = newOP($1, 0); }
709     | FUNC0 '(' ')'
710     { $$ = newOP($1, 0); }
711     | FUNC0SUB /* Sub treated as nullop */
712     { $$ = newUNOP(OP_ENTERSUB, OPf_STACKED,
713     scalar($1)); }
714     | FUNC1 '(' ')' /* not () */
715     { $$ = $1 == OP_NOT ? newUNOP($1, 0, newSVOP(OP_CONST, 0, newSViv(0)))
716     : newOP($1, OPf_SPECIAL); }
717     | FUNC1 '(' expr ')' /* not($foo) */
718     { $$ = newUNOP($1, 0, $3); }
719     | PMFUNC '(' term ')' /* split (/foo/) */
720     { $$ = pmruntime($1, $3, Nullop); }
721     | PMFUNC '(' term ',' term ')' /* split (/foo/,$bar) */
722     { $$ = pmruntime($1, $3, $5); }
723     | WORD
724     | listop
725     ;
726    
727     /* "my" declarations, with optional attributes */
728     myattrterm: MY myterm myattrlist
729     { $$ = my_attrs($2,$3); }
730     | MY myterm
731     { $$ = localize($2,$1); }
732     ;
733    
734     /* Things that can be "my"'d */
735     myterm : '(' expr ')'
736     { $$ = sawparens($2); }
737     | '(' ')'
738     { $$ = sawparens(newNULLLIST()); }
739     | scalar %prec '('
740     { $$ = $1; }
741     | hsh %prec '('
742     { $$ = $1; }
743     | ary %prec '('
744     { $$ = $1; }
745     ;
746    
747     /* Basic list expressions */
748     listexpr: /* NULL */ %prec PREC_LOW
749     { $$ = Nullop; }
750     | argexpr %prec PREC_LOW
751     { $$ = $1; }
752     ;
753    
754     listexprcom: /* NULL */
755     { $$ = Nullop; }
756     | expr
757     { $$ = $1; }
758     | expr ','
759     { $$ = $1; }
760     ;
761    
762     /* A little bit of trickery to make "for my $foo (@bar)" actually be
763     lexical */
764     my_scalar: scalar
765     { PL_in_my = 0; $$ = my($1); }
766     ;
767    
768     amper : '&' indirob
769     { $$ = newCVREF($1,$2); }
770     ;
771    
772     scalar : '$' indirob
773     { $$ = newSVREF($2); }
774     ;
775    
776     ary : '@' indirob
777     { $$ = newAVREF($2); }
778     ;
779    
780     hsh : '%' indirob
781     { $$ = newHVREF($2); }
782     ;
783    
784     arylen : DOLSHARP indirob
785     { $$ = newAVREF($2); }
786     ;
787    
788     star : '*' indirob
789     { $$ = newGVREF(0,$2); }
790     ;
791    
792     /* Indirect objects */
793     indirob : WORD
794     { $$ = scalar($1); }
795     | scalar %prec PREC_LOW
796     { $$ = scalar($1); }
797     | block
798     { $$ = scope($1); }
799    
800     | PRIVATEREF
801     { $$ = $1; }
802     ;
803    
804     %% /* PROGRAM */
805    
806     /* more stuff added to make perly_c.diff easier to apply */
807    
808     #ifdef yyparse
809     #undef yyparse
810     #endif
811     #define yyparse() Perl_yyparse(pTHX)
812