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 |
|
---|