Develop and Download Open Source Software

Browse CVS Repository

Contents of /netruby/netruby/parse.y

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1.1.1 - (show annotations) (download) (vendor branch)
Mon Apr 8 13:28:36 2002 UTC (22 years ago) by arton
Branch: MAIN, vendor
CVS Tags: start, HEAD
Changes since 1.1: +0 -0 lines
initial version 0.8

1 /**********************************************************************
2
3 parse.y -
4
5 $Author: matz $
6 $Date: 2001/12/25 15:09:05 $
7 created at: Fri May 28 18:02:42 JST 1993
8
9 Copyright (C) 1993-2001 Yukihiro Matsumoto
10
11 **********************************************************************/
12 /*
13 NetRuby (C# Parser for Jay)
14 Copyright(C) 2001-2002 arton
15
16 Permission is granted for use, copying, modification, distribution,
17 and distribution of modified versions of this work as long as the
18 above (include Yukihiro Matsumoto's) copyright notice is included.
19 */
20 %{
21
22 using System;
23 using System.Collections;
24 using System.IO;
25 using System.Text;
26 using System.Text.RegularExpressions;
27 using System.Reflection;
28
29 namespace arton.NETRuby
30 {
31 public class Parser
32 {
33 public interface Lexer
34 {
35 EXPR State
36 {
37 get;
38 set;
39 }
40 void COND_PUSH();
41 void COND_POP();
42 void CMDARG_PUSH();
43 void CMDARG_POP();
44 }
45
46 public Parser(NetRuby rb, RThread th, bool in_eval)
47 {
48 evalTree = null;
49 ruby = rb;
50 thread = th;
51 compile_for_eval = in_eval;
52 }
53
54 public Parser(NetRuby rb)
55 {
56 evalTree = null;
57 ruby = rb;
58 thread = rb.GetCurrentContext();
59 compile_for_eval = false;
60 }
61
62 public object Parse(Lexer lexer)
63 {
64 evalTree = null;
65 lex = lexer;
66 object n = yyparse((yyParser.yyInput)lex, new yydebug.yyDebugSimple());
67 if (n == null)
68 return evalTree;
69 return null;
70 }
71
72 private Lexer lex;
73 internal RNode evalTree;
74
75 internal enum ID
76 {
77 SCOPE_SHIFT = 3,
78 SCOPE_MASK = 7,
79 LOCAL = 1,
80 INSTANCE = 2,
81 GLOBAL = 3,
82 ATTRSET = 4,
83 CONST = 5,
84 CLASS = 6,
85 }
86
87 internal string sourcefile
88 {
89 get { return thread.file; }
90 }
91 internal int sourceline
92 {
93 get { return thread.line; }
94 set { thread.line = value; }
95 }
96
97 public NetRuby ruby;
98 internal RThread thread;
99 internal bool verbose
100 {
101 get { return ruby.verbose; }
102 }
103 internal void warn(string s)
104 {
105 ruby.warn(s);
106 }
107
108 internal uint[] Locals
109 {
110 get { return thread.Locals; }
111 }
112
113 private int class_nest = 0;
114 private int in_single = 0;
115 private int in_def = 0;
116 private bool compile_for_eval = false;
117 private uint cur_mid = 0;
118 private bool in_defined = false;
119
120 %}
121
122 %token kCLASS
123 kMODULE
124 kDEF
125 kUNDEF
126 kBEGIN
127 kRESCUE
128 kENSURE
129 kEND
130 kIF
131 kUNLESS
132 kTHEN
133 kELSIF
134 kELSE
135 kCASE
136 kWHEN
137 kWHILE
138 kUNTIL
139 kFOR
140 kBREAK
141 kNEXT
142 kREDO
143 kRETRY
144 kIN
145 kDO
146 kDO_COND
147 kDO_BLOCK
148 kRETURN
149 kYIELD
150 kSUPER
151 kSELF
152 kNIL
153 kTRUE
154 kFALSE
155 kAND
156 kOR
157 kNOT
158 kIF_MOD
159 kUNLESS_MOD
160 kWHILE_MOD
161 kUNTIL_MOD
162 kRESCUE_MOD
163 kALIAS
164 kDEFINED
165 klBEGIN
166 klEND
167 k__LINE__
168 k__FILE__
169
170 %token <uint> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR
171 %token <object> tINTEGER tFLOAT tSTRING tXSTRING tREGEXP
172 %token <RNode> tDSTRING tDXSTRING tDREGEXP tNTH_REF tBACK_REF tQWORDS
173
174 %type <RNode> singleton string
175 %type <object> literal numeric
176 %type <RNode> compstmt stmts stmt expr arg primary command command_call method_call
177 %type <RNode> if_tail opt_else case_body cases rescue exc_list exc_var ensure
178 %type <RNode> args ret_args when_args call_args paren_args opt_paren_args
179 %type <RNode> command_args aref_args opt_block_arg block_arg var_ref
180 %type <RNode> mrhs mrhs_basic superclass block_call block_command
181 %type <RNode> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
182 %type <RNode> assoc_list assocs assoc undef_list backref
183 %type <RNode> block_var opt_block_var brace_block do_block lhs none
184 %type <RNode> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
185 %type <uint> fitem variable sym symbol operation operation2 operation3
186 %type <uint> cname fname op f_rest_arg
187 %type <int> f_norm_arg f_arg
188 %token tUPLUS /* unary+ */
189 %token tUMINUS /* unary- */
190 %token tPOW /* ** */
191 %token tCMP /* <=> */
192 %token tEQ /* == */
193 %token tEQQ /* === */
194 %token tNEQ /* != */
195 %token tGEQ /* >= */
196 %token tLEQ /* <= */
197 %token tANDOP tOROP /* && and || */
198 %token tMATCH tNMATCH /* =~ and !~ */
199 %token tDOT2 tDOT3 /* .. and ... */
200 %token tAREF tASET /* [] and []= */
201 %token tLSHFT tRSHFT /* << and >> */
202 %token tCOLON2 /* :: */
203 %token tCOLON3 /* :: at EXPR.BEG */
204 %token <uint> tOP_ASGN /* +=, -= etc. */
205 %token tASSOC /* => */
206 %token tLPAREN /* ( */
207 %token tLBRACK /* [ */
208 %token tLBRACE /* { */
209 %token tSTAR /* * */
210 %token tAMPER /* & */
211 %token tSYMBEG
212
213 /*
214 * precedence table
215 */
216
217 %left kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD kRESCUE_MOD
218 %left kOR kAND
219 %right kNOT
220 %nonassoc kDEFINED
221 %right '=' tOP_ASGN
222 %right '?' ':'
223 %nonassoc tDOT2 tDOT3
224 %left tOROP
225 %left tANDOP
226 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
227 %left '>' tGEQ '<' tLEQ
228 %left '|' '^'
229 %left '&'
230 %left tLSHFT tRSHFT
231 %left '+' '-'
232 %left '*' '/' '%'
233 %right '!' '~' tUPLUS tUMINUS
234 %right tPOW
235
236 %token LAST_TOKEN
237
238 %%
239 program : {
240 $$ = thread.dyna_vars;
241 lex.State = EXPR.BEG;
242 thread.TopLocalInit();
243 /*
244 if ((VALUE)ruby_class == rb_cObject) class_nest = 0;
245 else class_nest = 1;
246 */
247 }
248 compstmt
249 {
250 if ($2 != null && !compile_for_eval) {
251 /* last expression should not be void */
252 if ($2 is RNBlock)
253 {
254 RNode node = $2;
255 while (node.next != null) {
256 node = node.next;
257 }
258 void_expr(node.head);
259 }
260 else
261 {
262 void_expr($2);
263 }
264 }
265 evalTree = block_append(evalTree, $2);
266 thread.TopLocalSetup();
267 class_nest = 0;
268 thread.dyna_vars = $<RVarmap>1;
269 }
270
271 compstmt : stmts opt_terms
272 {
273 void_stmts($1);
274 $$ = $1;
275 }
276
277 stmts : none
278 | stmt
279 {
280 $$ = new RNNewLine(thread, $1);
281 }
282 | stmts terms stmt
283 {
284 $$ = block_append($1, new RNNewLine(thread, $3));
285 }
286 | error stmt
287 {
288 $$ = $2;
289 }
290
291 stmt : kALIAS fitem {lex.State = EXPR.FNAME;} fitem
292 {
293 if (in_def != 0 || in_single != 0)
294 yyerror("alias within method");
295 $$ = new RNAlias(thread, $2, $4);
296 }
297 | kALIAS tGVAR tGVAR
298 {
299 if (in_def != 0 || in_single != 0)
300 yyerror("alias within method");
301 $$ = new RNVAlias(thread, $2, $3);
302 }
303 | kALIAS tGVAR tBACK_REF
304 {
305 if (in_def != 0 || in_single != 0)
306 yyerror("alias within method");
307 string buf = "$" + Convert.ToChar($3.nth);
308 $$ = new RNVAlias(thread, $2, intern(buf));
309 }
310 | kALIAS tGVAR tNTH_REF
311 {
312 yyerror("can't make alias for the number variables");
313 $$ = null;
314 }
315 | kUNDEF undef_list
316 {
317 if (in_def != 0 || in_single != 0)
318 yyerror("undef within method");
319 $$ = $2;
320 }
321 | stmt kIF_MOD expr
322 {
323 value_expr($3);
324 $$ = new RNIf(thread, cond($3), $1);
325 }
326 | stmt kUNLESS_MOD expr
327 {
328 value_expr($3);
329 $$ = new RNUnless(thread, cond($3), $1);
330 }
331 | stmt kWHILE_MOD expr
332 {
333 value_expr($3);
334 if ($1 != null && $1 is RNBegin) {
335 $$ = new RNWhile(thread, cond($3), $1.body, false);
336 }
337 else {
338 $$ = new RNWhile(thread, cond($3), $1, true);
339 }
340 }
341 | stmt kUNTIL_MOD expr
342 {
343 value_expr($3);
344 if ($1 != null && $1 is RNBegin) {
345 $$ = new RNUntil(thread, cond($3), $1.body, false);
346 }
347 else {
348 $$ = new RNUntil(thread, cond($3), $1, true);
349 }
350 }
351 | stmt kRESCUE_MOD stmt
352 {
353 $$ = new RNRescue(thread, $1, new RNResBody(thread, null, $3, null), null);
354 }
355 | klBEGIN
356 {
357 if (in_def != 0 || in_single != 0) {
358 yyerror("BEGIN in method");
359 }
360 thread.LocalPush();
361 }
362 '{' compstmt '}'
363 {
364 thread.evalTreeBegin = block_append(thread.evalTreeBegin,
365 new RNPreExe(thread, $4));
366 thread.LocalPop();
367 $$ = null;
368 }
369 | klEND '{' compstmt '}'
370 {
371 if (compile_for_eval && (in_def != 0|| in_single != 0)) {
372 yyerror("END in method; use at_exit");
373 }
374
375 $$ = new RNIter(thread, null, new RNPostExe(thread), $3);
376 }
377 | lhs '=' command_call
378 {
379 value_expr($3);
380 $$ = node_assign($1, $3);
381 }
382 | mlhs '=' command_call
383 {
384 value_expr($3);
385 $1.val = $3;
386 $$ = $1;
387 }
388 | lhs '=' mrhs_basic
389 {
390 $$ = node_assign($1, $3);
391 }
392 | expr
393
394 expr : mlhs '=' mrhs
395 {
396 // value_expr($3); // nakada ruby-dev:15905
397 $1.val = $3;
398 $$ = $1;
399 }
400 | kRETURN ret_args
401 {
402 if (!compile_for_eval && in_def != 0 && in_single != 0)
403 yyerror("return appeared outside of method");
404 $$ = new RNReturn(thread, $2);
405 }
406 | command_call
407 | expr kAND expr
408 {
409 $$ = logop(typeof(RNAnd), $1, $3);
410 }
411 | expr kOR expr
412 {
413 $$ = logop(typeof(RNOr), $1, $3);
414 }
415 | kNOT expr
416 {
417 value_expr($2);
418 $$ = new RNNot(thread, cond($2));
419 }
420 | '!' command_call
421 {
422 $$ = new RNNot(thread, cond($2));
423 }
424 | arg
425
426 command_call : command
427 | block_command
428
429 block_command : block_call
430 | block_call '.' operation2 command_args
431 {
432 value_expr($1);
433 $$ = new_call($1, $3, $4);
434 }
435 | block_call tCOLON2 operation2 command_args
436 {
437 value_expr($1);
438 $$ = new_call($1, $3, $4);
439 }
440
441 command : operation command_args
442 {
443 $$ = new_fcall($1, $2);
444 $<RNode>$.FixPos($2);
445 }
446 | primary '.' operation2 command_args
447 {
448 value_expr($1);
449 $$ = new_call($1, $3, $4);
450 $<RNode>$.FixPos($1);
451 }
452 | primary tCOLON2 operation2 command_args
453 {
454 value_expr($1);
455 $$ = new_call($1, $3, $4);
456 $<RNode>$.FixPos($1);
457 }
458 | kSUPER command_args
459 {
460 if (!compile_for_eval && in_def == 0 && in_single == 0)
461 yyerror("super called outside of method");
462 $$ = new_super($2);
463 $<RNode>$.FixPos($2);
464 }
465 | kYIELD ret_args
466 {
467 $$ = new RNYield(thread, $2);
468 $<RNode>$.FixPos($2);
469 }
470
471 mlhs : mlhs_basic
472 | tLPAREN mlhs_entry ')'
473 {
474 $$ = $2;
475 }
476
477 mlhs_entry : mlhs_basic
478 | tLPAREN mlhs_entry ')'
479 {
480 $$ = new RNMAsgn(thread, new RNArray(thread, $2));
481 }
482
483 mlhs_basic : mlhs_head
484 {
485 $$ = new RNMAsgn(thread, $1);
486 }
487 | mlhs_head mlhs_item
488 {
489 $$ = new RNMAsgn(thread, RNode.list_append(thread,$1,$2));
490 }
491 | mlhs_head tSTAR mlhs_node
492 {
493 $$ = new RNMAsgn(thread, $1, $3);
494 }
495 | mlhs_head tSTAR
496 {
497 $$ = new RNMAsgn(thread, $1, -1);
498 }
499 | tSTAR mlhs_node
500 {
501 $$ = new RNMAsgn(thread, null, $2);
502 }
503 | tSTAR
504 {
505 $$ = new RNMAsgn(thread, null, -1);
506 }
507
508 mlhs_item : mlhs_node
509 | tLPAREN mlhs_entry ')'
510 {
511 $$ = $2;
512 }
513
514 mlhs_head : mlhs_item ','
515 {
516 $$ = new RNArray(thread, $1);
517 }
518 | mlhs_head mlhs_item ','
519 {
520 $$ = RNode.list_append(thread, $1, $2);
521 }
522
523 mlhs_node : variable
524 {
525 $$ = assignable($1, null);
526 }
527 | primary '[' aref_args ']'
528 {
529 $$ = aryset($1, $3);
530 }
531 | primary '.' tIDENTIFIER
532 {
533 $$ = attrset($1, $3);
534 }
535 | primary tCOLON2 tIDENTIFIER
536 {
537 $$ = attrset($1, $3);
538 }
539 | primary '.' tCONSTANT
540 {
541 $$ = attrset($1, $3);
542 }
543 | backref
544 {
545 backref_error($1);
546 $$ = null;
547 }
548
549 lhs : variable
550 {
551 $$ = assignable($1, null);
552 }
553 | primary '[' aref_args ']'
554 {
555 $$ = aryset($1, $3);
556 }
557 | primary '.' tIDENTIFIER
558 {
559 $$ = attrset($1, $3);
560 }
561 | primary tCOLON2 tIDENTIFIER
562 {
563 $$ = attrset($1, $3);
564 }
565 | primary '.' tCONSTANT
566 {
567 $$ = attrset($1, $3);
568 }
569 | backref
570 {
571 backref_error($1);
572 $$ = null;
573 }
574
575 cname : tIDENTIFIER
576 {
577 yyerror("class/module name must be CONSTANT");
578 }
579 | tCONSTANT
580
581 fname : tIDENTIFIER
582 | tCONSTANT
583 | tFID
584 | op
585 {
586 lex.State = EXPR.END;
587 if ($<object>1 is int)
588 $$ = $<int>1;
589 else
590 $$ = $<char>1;
591 }
592 | reswords
593 {
594 lex.State = EXPR.END;
595 $$ = $<uint>1;
596 }
597
598 fitem : fname
599 | symbol
600
601 undef_list : fitem
602 {
603 $$ = new RNUndef(thread, $1);
604 }
605 | undef_list ',' {lex.State = EXPR.FNAME;} fitem
606 {
607 $$ = block_append($1, new RNUndef(thread, $4));
608 }
609
610 op : '|' { $$ = '|'; }
611 | '^' { $$ = '^'; }
612 | '&' { $$ = '&'; }
613 | tCMP { $$ = Token.tCMP; }
614 | tEQ { $$ = Token.tEQ; }
615 | tEQQ { $$ = Token.tEQQ; }
616 | tMATCH { $$ = Token.tMATCH; }
617 | '>' { $$ = '>'; }
618 | tGEQ { $$ = Token.tGEQ; }
619 | '<' { $$ = '<'; }
620 | tLEQ { $$ = Token.tLEQ; }
621 | tLSHFT { $$ = Token.tLSHFT; }
622 | tRSHFT { $$ = Token.tRSHFT; }
623 | '+' { $$ = '+'; }
624 | '-' { $$ = '-'; }
625 | '*' { $$ = '*'; }
626 | tSTAR { $$ = '*'; }
627 | '/' { $$ = '/'; }
628 | '%' { $$ = '%'; }
629 | tPOW { $$ = Token.tPOW; }
630 | '~' { $$ = '~'; }
631 | tUPLUS { $$ = Token.tUPLUS; }
632 | tUMINUS { $$ = Token.tUMINUS; }
633 | tAREF { $$ = Token.tAREF; }
634 | tASET { $$ = Token.tASET; }
635 | '`' { $$ = '`'; }
636
637 reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
638 | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
639 | kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
640 | kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
641 | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
642 | kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
643 | kWHILE_MOD | kYIELD | kRESCUE_MOD
644
645 arg : lhs '=' arg
646 {
647 value_expr($3);
648 $$ = node_assign($1, $3);
649 }
650 | variable tOP_ASGN {$$ = assignable($1, null);} arg
651 {
652 if ($<RNode>3 != null) {
653 if ($<char>2 == Token.tOROP) {
654 $<RNode>3.val = $4;
655 $$ = new RNOpAsgnOr(thread, gettable($1), $<RNode>3);
656 if (is_instance_id($1)) {
657 $<RNode>$.aid = $1;
658 }
659 }
660 else if ($<char>2 == Token.tANDOP) {
661 $<RNode>3.val = $4;
662 $$ = new RNOpAsgnAnd(thread, gettable($1), $<RNode>3);
663 }
664 else {
665 $$ = $<RNode>3;
666 $<RNode>$.val = call_op(gettable($1),$<char>2,1,$4);
667 }
668 $<RNode>$.FixPos($4);
669 }
670 else {
671 $$ = null;
672 }
673 }
674 | primary '[' aref_args ']' tOP_ASGN arg
675 {
676 RNode args = new RNArray(thread, $6);
677
678 RNode tail = RNode.list_append(thread, $3, new RNNil(thread));
679 RNode.list_concat(args, tail);
680 uint id = $<char>5;
681 if (id == Token.tOROP) {
682 id = 0;
683 }
684 else if (id == Token.tANDOP) {
685 id = 1;
686 }
687 $$ = new RNOpAsgn1(thread, $1, id, args);
688 $<RNode>$.FixPos($1);
689 }
690 | primary '.' tIDENTIFIER tOP_ASGN arg
691 {
692 uint id = $4;
693 if (id == Token.tOROP) {
694 id = 0;
695 }
696 else if (id == Token.tANDOP) {
697 id = 1;
698 }
699 $$ = new RNOpAsgn2(thread, $1, $3, id, $5);
700 $<RNode>$.FixPos($1);
701 }
702 | primary '.' tCONSTANT tOP_ASGN arg
703 {
704 uint id = $4;
705 if (id == Token.tOROP) {
706 id = 0;
707 }
708 else if (id == Token.tANDOP) {
709 id = 1;
710 }
711 $$ = new RNOpAsgn2(thread, $1, $3, id, $5);
712 $<RNode>$.FixPos($1);
713 }
714 | primary tCOLON2 tIDENTIFIER tOP_ASGN arg
715 {
716 uint id = $4;
717 if (id == Token.tOROP) {
718 id = 0;
719 }
720 else if (id == Token.tANDOP) {
721 id = 1;
722 }
723 $$ = new RNOpAsgn2(thread, $1, $3, id, $5);
724 $<RNode>$.FixPos($1);
725 }
726 | backref tOP_ASGN arg
727 {
728 backref_error($1);
729 $$ = null;
730 }
731 | arg tDOT2 arg
732 {
733 $$ = new RNDot2(thread, $1, $3);
734 }
735 | arg tDOT3 arg
736 {
737 $$ = new RNDot3(thread, $1, $3);
738 }
739 | arg '+' arg
740 {
741 $$ = call_op($1, '+', 1, $3);
742 }
743 | arg '-' arg
744 {
745 $$ = call_op($1, '-', 1, $3);
746 }
747 | arg '*' arg
748 {
749 $$ = call_op($1, '*', 1, $3);
750 }
751 | arg '/' arg
752 {
753 $$ = call_op($1, '/', 1, $3);
754 }
755 | arg '%' arg
756 {
757 $$ = call_op($1, '%', 1, $3);
758 }
759 | arg tPOW arg
760 {
761 bool need_negate = false;
762 #if UMINUS
763 if ($1 is RNLit) {
764 if ($1.lit is long ||
765 $1.lit is double ||
766 $1.lit is int /* ||
767 $1.lit is BIGNUM */
768 )
769 {
770 if (RTEST(rb_funcall($1.lit,'<',1,0))) {
771 $1.lit = rb_funcall($1.lit,intern("-@"),0,0);
772 need_negate = true;
773 }
774 }
775 }
776 #endif
777 $$ = call_op($<RNode>1, Token.tPOW, 1, $<RNode>3);
778 if (need_negate) {
779 $$ = call_op($<RNode>$, Token.tUMINUS, 0, null);
780 }
781 }
782 | tUPLUS arg
783 {
784 if ($2 != null && $2 is RNLit) {
785 $$ = $2;
786 }
787 else {
788 $$ = call_op($2, Token.tUPLUS, 0, null);
789 }
790 }
791 | tUMINUS arg
792 {
793 if ($2 != null && $2 is RNLit && ($2.lit is int ||
794 $2.lit is long)) {
795 if ($2.lit is int)
796 {
797 int i = (int)$2.lit;
798 $2.lit = -i;
799 }
800 else
801 {
802 long i = (long)$2.lit;
803 $2.lit = -i;
804 }
805 $$ = $2;
806 }
807 else {
808 $$ = call_op($2, Token.tUMINUS, 0, null);
809 }
810 }
811 | arg '|' arg
812 {
813 $$ = call_op($1, '|', 1, $3);
814 }
815 | arg '^' arg
816 {
817 $$ = call_op($1, '^', 1, $3);
818 }
819 | arg '&' arg
820 {
821 $$ = call_op($1, '&', 1, $3);
822 }
823 | arg tCMP arg
824 {
825 $$ = call_op($1, Token.tCMP, 1, $3);
826 }
827 | arg '>' arg
828 {
829 $$ = call_op($1, '>', 1, $3);
830 }
831 | arg tGEQ arg
832 {
833 $$ = call_op($1, Token.tGEQ, 1, $3);
834 }
835 | arg '<' arg
836 {
837 $$ = call_op($1, '<', 1, $3);
838 }
839 | arg tLEQ arg
840 {
841 $$ = call_op($1, Token.tLEQ, 1, $3);
842 }
843 | arg tEQ arg
844 {
845 $$ = call_op($1, Token.tEQ, 1, $3);
846 }
847 | arg tEQQ arg
848 {
849 $$ = call_op($1, Token.tEQQ, 1, $3);
850 }
851 | arg tNEQ arg
852 {
853 $$ = new RNNot(thread, call_op($1, Token.tEQ, 1, $3));
854 }
855 | arg tMATCH arg
856 {
857 $$ = match_gen($1, $3);
858 }
859 | arg tNMATCH arg
860 {
861 $$ = new RNNot(thread, match_gen($1, $3));
862 }
863 | '!' arg
864 {
865 value_expr($2);
866 $$ = new RNNot(thread, cond($2));
867 }
868 | '~' arg
869 {
870 $$ = call_op($2, '~', 0, null);
871 }
872 | arg tLSHFT arg
873 {
874 $$ = call_op($1, Token.tLSHFT, 1, $3);
875 }
876 | arg tRSHFT arg
877 {
878 $$ = call_op($1, Token.tRSHFT, 1, $3);
879 }
880 | arg tANDOP arg
881 {
882 $$ = logop(typeof(RNAnd), $1, $3);
883 }
884 | arg tOROP arg
885 {
886 $$ = logop(typeof(RNOr), $1, $3);
887 }
888 | kDEFINED opt_nl {in_defined = true;} arg
889 {
890 in_defined = false;
891 $$ = new RNDefined(thread, $4);
892 }
893 | arg '?' arg ':' arg
894 {
895 value_expr($1);
896 $$ = new RNIf(thread, cond($1), $3, $5);
897 }
898 | primary
899 {
900 $$ = $1;
901 }
902
903 aref_args : none
904 | command_call opt_nl
905 {
906 $$ = new RNArray(thread, $1);
907 }
908 | args ',' command_call opt_nl
909 {
910 $$ = RNode.list_append(thread, $1, $3);
911 }
912 | args trailer
913 {
914 $$ = $1;
915 }
916 | args ',' tSTAR arg opt_nl
917 {
918 value_expr($4);
919 $$ = arg_concat($1, $4);
920 }
921 | assocs trailer
922 {
923 $$ = new RNArray(thread, new RNHash(thread, $1));
924 }
925 | tSTAR arg opt_nl
926 {
927 value_expr($2);
928 $$ = new RNRestArgs(thread, $2);
929 }
930
931 paren_args : '(' none ')'
932 {
933 $$ = $2;
934 }
935 | '(' call_args opt_nl ')'
936 {
937 $$ = $2;
938 }
939 | '(' block_call opt_nl ')'
940 {
941 $$ = new RNArray(thread, $2);
942 }
943 | '(' args ',' block_call opt_nl ')'
944 {
945 $$ = RNode.list_append(thread, $2, $4);
946 }
947
948 opt_paren_args : none
949 | paren_args
950
951 call_args : command
952 {
953 $$ = new RNArray(thread, $1);
954 }
955 | args ',' command
956 {
957 $$ = RNode.list_append(thread, $1, $3);
958 }
959 | args opt_block_arg
960 {
961 $$ = arg_blk_pass($1, $2);
962 }
963 | args ',' tSTAR arg opt_block_arg
964 {
965 value_expr($4);
966 $$ = arg_concat($1, $4);
967 $$ = arg_blk_pass($<RNode>$, $5);
968 }
969 | assocs opt_block_arg
970 {
971 $$ = new RNArray(thread, new RNHash(thread, $1));
972 $$ = arg_blk_pass($<RNode>$, $2);
973 }
974 | assocs ',' tSTAR arg opt_block_arg
975 {
976 value_expr($4);
977 $$ = arg_concat(new RNArray(thread, new RNHash(thread, $1)), $4);
978 $$ = arg_blk_pass($<RNode>$, $5);
979 }
980 | args ',' assocs opt_block_arg
981 {
982 $$ = RNode.list_append(thread, $1, new RNHash(thread, $3));
983 $$ = arg_blk_pass($<RNode>$, $4);
984 }
985 | args ',' assocs ',' tSTAR arg opt_block_arg
986 {
987 value_expr($6);
988 $$ = arg_concat(RNode.list_append(thread, $1, new RNHash(thread, $3)), $6);
989 $$ = arg_blk_pass($<RNode>$, $7);
990 }
991 | tSTAR arg opt_block_arg
992 {
993 value_expr($2);
994 $$ = arg_blk_pass(new RNRestArgs(thread, $2), $3);
995 }
996 | block_arg
997
998 command_args : {lex.CMDARG_PUSH();} call_args
999 {
1000 lex.CMDARG_POP();
1001 $$ = $2;
1002 }
1003
1004 block_arg : tAMPER arg
1005 {
1006 value_expr($2);
1007 $$ = new RNBlockPass(thread, $2);
1008 }
1009
1010 opt_block_arg : ',' block_arg
1011 {
1012 $$ = $2;
1013 }
1014 | none
1015
1016 args : arg
1017 {
1018 value_expr($1);
1019 $$ = new RNArray(thread, $1);
1020 }
1021 | args ',' arg
1022 {
1023 value_expr($3);
1024 $$ = RNode.list_append(thread, $1, $3);
1025 }
1026
1027 mrhs : arg
1028 {
1029 value_expr($1);
1030 $$ = $1;
1031 }
1032 | mrhs_basic
1033
1034 mrhs_basic : args ',' arg
1035 {
1036 value_expr($3);
1037 $$ = RNode.list_append(thread, $1, $3);
1038 }
1039 | args ',' tSTAR arg
1040 {
1041 value_expr($4);
1042 $$ = arg_concat($1, $4);
1043 }
1044 | tSTAR arg
1045 {
1046 value_expr($2);
1047 $$ = $2;
1048 }
1049
1050 ret_args : call_args
1051 {
1052 $$ = $1;
1053 if ($1 != null) {
1054 if ($1 is RNArray && $1.next == null) {
1055 $$ = $1.head;
1056 }
1057 else if ($1 is RNBlockPass) {
1058 thread.CompileError("block argument should not be given");
1059 }
1060 }
1061 }
1062
1063 primary : literal
1064 {
1065 $$ = new RNLit(thread, $1);
1066 }
1067 | string
1068 | tXSTRING
1069 {
1070 $$ = new RNXStr(thread, ruby, $1);
1071 }
1072 | tQWORDS
1073 | tDXSTRING
1074 | tDREGEXP
1075 | var_ref
1076 | backref
1077 | tFID
1078 {
1079 $$ = new RNVCall(thread, $1);
1080 }
1081 | kBEGIN
1082 compstmt
1083 rescue
1084 opt_else
1085 ensure
1086 kEND
1087 {
1088 RNode nd = $2;
1089 if ($3 == null && $4 == null && $5 == null)
1090 $$ = new RNBegin(thread, $2);
1091 else {
1092 if ($3 != null) nd = new RNRescue(thread, $2, $3, $4);
1093 else if ($4 != null) {
1094 ruby.warn("else without rescue is useless");
1095 nd = block_append($2, $4);
1096 }
1097 if ($5 != null) nd = new RNEnsure(thread, $2, $5);
1098 $$ = nd;
1099 }
1100 $<RNode>$.FixPos(nd);
1101 }
1102 | tLPAREN compstmt ')'
1103 {
1104 $$ = $2;
1105 }
1106 | primary tCOLON2 tCONSTANT
1107 {
1108 value_expr($1);
1109 $$ = new RNColon2(thread, $1, $3);
1110 }
1111 | tCOLON3 cname
1112 {
1113 $$ = new RNColon3(thread, $2);
1114 }
1115 | primary '[' aref_args ']'
1116 {
1117 value_expr($1);
1118 $$ = new RNCall(thread, $1, Token.tAREF, $3);
1119 }
1120 | tLBRACK aref_args ']'
1121 {
1122 if ($2 == null)
1123 $$ = new RNZArray(thread); /* zero length array*/
1124 else {
1125 $$ = $2;
1126 }
1127 }
1128 | tLBRACE assoc_list '}'
1129 {
1130 $$ = new RNHash(thread, $2);
1131 }
1132 | kRETURN '(' ret_args ')'
1133 {
1134 if (!compile_for_eval && in_def == 0 && in_single == 0)
1135 yyerror("return appeared outside of method");
1136 value_expr($3);
1137 $$ = new RNReturn(thread, $3);
1138 }
1139 | kRETURN '(' ')'
1140 {
1141 if (!compile_for_eval && in_def == 0 && in_single == 0)
1142 yyerror("return appeared outside of method");
1143 $$ = new RNReturn(thread);
1144 }
1145 | kRETURN
1146 {
1147 if (!compile_for_eval && in_def == 0 && in_single == 0)
1148 yyerror("return appeared outside of method");
1149 $$ = new RNReturn(thread);
1150 }
1151 | kYIELD '(' ret_args ')'
1152 {
1153 value_expr($3);
1154 $$ = new RNYield(thread, $3);
1155 }
1156 | kYIELD '(' ')'
1157 {
1158 $$ = new RNYield(thread);
1159 }
1160 | kYIELD
1161 {
1162 $$ = new RNYield(thread);
1163 }
1164 | kDEFINED opt_nl '(' {in_defined = true;} expr ')'
1165 {
1166 in_defined = false;
1167 $$ = new RNDefined(thread, $5);
1168 }
1169 | operation brace_block
1170 {
1171 $2.iter = new RNFCall(thread, $1);
1172 $$ = $2;
1173 }
1174 | method_call
1175 | method_call brace_block
1176 {
1177 if ($1 != null && $1 is RNBlockPass) {
1178 thread.CompileError("both block arg and actual block given");
1179 }
1180 $2.iter = $1;
1181 $$ = $2;
1182 $<RNode>$.FixPos($1);
1183 }
1184 | kIF expr then
1185 compstmt
1186 if_tail
1187 kEND
1188 {
1189 value_expr($2);
1190 $$ = new RNIf(thread, cond($2), $4, $5);
1191 $<RNode>$.FixPos($2);
1192 }
1193 | kUNLESS expr then
1194 compstmt
1195 opt_else
1196 kEND
1197 {
1198 value_expr($2);
1199 $$ = new RNUnless(thread, cond($2), $4, $5);
1200 $<RNode>$.FixPos($2);
1201 }
1202 | kWHILE {lex.COND_PUSH();} expr do {lex.COND_POP();}
1203 compstmt
1204 kEND
1205 {
1206 value_expr($3);
1207 $$ = new RNWhile(thread, cond($3), $6, true);
1208 $<RNode>$.FixPos($3);
1209 }
1210 | kUNTIL {lex.COND_PUSH();} expr do {lex.COND_POP();}
1211 compstmt
1212 kEND
1213 {
1214 value_expr($3);
1215 $$ = new RNUntil(thread, cond($3), $6, true);
1216 $<RNode>$.FixPos($3);
1217 }
1218 | kCASE expr opt_terms
1219 case_body
1220 kEND
1221 {
1222 value_expr($2);
1223 $$ = new RNCase(thread, $2, $4);
1224 $<RNode>$.FixPos($2);
1225 }
1226 | kCASE opt_terms case_body kEND
1227 {
1228 $$ = $3;
1229 }
1230 | kFOR block_var kIN {lex.COND_PUSH();} expr do {lex.COND_POP();}
1231 compstmt
1232 kEND
1233 {
1234 value_expr($5);
1235 $$ = new RNFor(thread, $2, $5, $8);
1236 }
1237 | kCLASS cname superclass
1238 {
1239 if (in_def != 0|| in_single != 0)
1240 yyerror("class definition in method body");
1241 class_nest++;
1242 thread.LocalPush();
1243 $$ = sourceline;
1244 }
1245 compstmt
1246 kEND
1247 {
1248 $$ = new RNClass(thread, $2, $5, $3);
1249 $<RNode>$.SetLine($<int>4);
1250 thread.LocalPop();
1251 class_nest--;
1252 }
1253 | kCLASS tLSHFT expr
1254 {
1255 $$ = in_def;
1256 in_def = 0;
1257 }
1258 term
1259 {
1260 $$ = in_single;
1261 in_single = 0;
1262 class_nest++;
1263 thread.LocalPush();
1264 }
1265 compstmt
1266 kEND
1267 {
1268 $$ = new RNSClass(thread, $3, $7);
1269 thread.LocalPop();
1270 class_nest--;
1271 in_def = $<int>4;
1272 in_single = $<int>6;
1273 }
1274 | kMODULE cname
1275 {
1276 if (in_def != 0|| in_single != 0)
1277 yyerror("module definition in method body");
1278 class_nest++;
1279 thread.LocalPush();
1280 $$ = sourceline;
1281 }
1282 compstmt
1283 kEND
1284 {
1285 $$ = new RNModule(thread, $2, $4);
1286 $<RNode>$.SetLine($<int>3);
1287 thread.LocalPop();
1288 class_nest--;
1289 }
1290 | kDEF fname
1291 {
1292 if (in_def != 0|| in_single != 0)
1293 yyerror("nested method definition");
1294 $$ = cur_mid;
1295 if ($<object>2 is uint)
1296 cur_mid = $2;
1297 else
1298 cur_mid = (uint)$<int>2;
1299 in_def++;
1300 thread.LocalPush();
1301 }
1302 f_arglist
1303 compstmt
1304 rescue
1305 opt_else
1306 ensure
1307 kEND
1308 {
1309 RNode nd = $5;
1310 if ($6 != null) nd = new RNRescue(thread, $5, $6, $7);
1311 else if ($7 != null) {
1312 ruby.warn("else without rescue is useless");
1313 nd = block_append($5, $7);
1314 }
1315 if ($8 != null) nd = new RNEnsure(thread, $5, $8);
1316
1317 /* NOEX_PRIVATE for toplevel */
1318 uint id;
1319 if ($<object>2 is uint)
1320 {
1321 id = $2;
1322 }
1323 else
1324 {
1325 id = (uint)$<int>2;
1326 }
1327 $$ = new RNDefn(thread, id, $4, nd, (class_nest > 0) ? NOEX.PUBLIC : NOEX.PRIVATE);
1328 if (is_attrset_id(id)) $<RNode>$.noex = NOEX.PUBLIC;
1329 $<RNode>$.FixPos($4);
1330 thread.LocalPop();
1331 in_def--;
1332 cur_mid = $<uint>3;
1333 }
1334 | kDEF singleton dot_or_colon {lex.State = EXPR.FNAME;} fname
1335 {
1336 value_expr($2);
1337 in_single++;
1338 thread.LocalPush();
1339 lex.State = EXPR.END; /* force for args */
1340 }
1341 f_arglist
1342 compstmt
1343 rescue
1344 opt_else
1345 ensure
1346 kEND
1347 {
1348 RNode nd = $8;
1349 if ($9 != null) nd = new RNRescue(thread, $8, $9, $10);
1350 else if ($10 != null) {
1351 ruby.warn("else without rescue is useless");
1352 nd = block_append($8, $10);
1353 }
1354 if ($11 != null) nd = new RNEnsure(thread, $8, $11);
1355
1356 $$ = new RNDefs(thread, $2, $5, $7, nd);
1357 $<RNode>$.FixPos($2);
1358 thread.LocalPop();
1359 in_single--;
1360 }
1361 | kBREAK
1362 {
1363 $$ = new RNBreak(thread);
1364 }
1365 | kNEXT
1366 {
1367 $$ = new RNNext(thread);
1368 }
1369 | kREDO
1370 {
1371 $$ = new RNRedo(thread);
1372 }
1373 | kRETRY
1374 {
1375 $$ = new RNRetry(thread);
1376 }
1377
1378 then : term
1379 | kTHEN
1380 | term kTHEN
1381
1382 do : term
1383 | kDO_COND
1384
1385 if_tail : opt_else
1386 | kELSIF expr then
1387 compstmt
1388 if_tail
1389 {
1390 value_expr($2);
1391 $$ = new RNIf(thread, cond($2), $4, $5);
1392 }
1393
1394 opt_else : none
1395 | kELSE compstmt
1396 {
1397 $$ = $2;
1398 }
1399
1400 block_var : lhs
1401 | mlhs
1402
1403 opt_block_var : none
1404 | '|' /* none */ '|'
1405 {
1406 $$ = new RNBlockNoArg(thread);
1407 }
1408 | tOROP
1409 {
1410 $$ = new RNBlockNoArg(thread);
1411 }
1412 | '|' block_var '|'
1413 {
1414 $$ = $2;
1415 }
1416
1417
1418 do_block : kDO_BLOCK
1419 {
1420 $$ = thread.DynaPush();
1421 }
1422 opt_block_var
1423 compstmt
1424 kEND
1425 {
1426 $$ = new RNIter(thread, $3, null, $4);
1427 $<RNode>$.FixPos(($3 != null) ? $3 : $4);
1428 thread.DynaPop($<RVarmap>2);
1429 }
1430
1431 block_call : command do_block
1432 {
1433 if ($1 != null && $1 is RNBlockPass) {
1434 thread.CompileError("both block arg and actual block given");
1435 }
1436 $2.iter = $1;
1437 $$ = $2;
1438 $<RNode>$.FixPos($2);
1439 }
1440 | block_call '.' operation2 opt_paren_args
1441 {
1442 value_expr($1);
1443 $$ = new_call($1, $3, $4);
1444 }
1445 | block_call tCOLON2 operation2 opt_paren_args
1446 {
1447 value_expr($1);
1448 $$ = new_call($1, $3, $4);
1449 }
1450
1451 method_call : operation paren_args
1452 {
1453 $$ = new_fcall($1, $2);
1454 $<RNode>$.FixPos($2);
1455 }
1456 | primary '.' operation2 opt_paren_args
1457 {
1458 value_expr($1);
1459 $$ = new_call($1, $3, $4);
1460 $<RNode>$.FixPos($1);
1461 }
1462 | primary tCOLON2 operation2 paren_args
1463 {
1464 value_expr($1);
1465 $$ = new_call($1, $3, $4);
1466 $<RNode>$.FixPos($1);
1467 }
1468 | primary tCOLON2 operation3
1469 {
1470 value_expr($1);
1471 $$ = new_call($1, $3, null);
1472 }
1473 | kSUPER paren_args
1474 {
1475 if (!compile_for_eval && in_def == 0 &&
1476 in_single == 0 && !in_defined)
1477 yyerror("super called outside of method");
1478 $$ = new_super($2);
1479 }
1480 | kSUPER
1481 {
1482 if (!compile_for_eval && in_def == 0 &&
1483 in_single == 0 && !in_defined)
1484 yyerror("super called outside of method");
1485 $$ = new RNZSuper(thread, ruby);
1486 }
1487
1488 brace_block : '{'
1489 {
1490 $$ = thread.DynaPush();
1491 }
1492 opt_block_var
1493 compstmt '}'
1494 {
1495 $$ = new RNIter(thread, $3, null, $4);
1496 $<RNode>$.FixPos($4);
1497 thread.DynaPop($<RVarmap>2);
1498 }
1499 | kDO
1500 {
1501 $$ = thread.DynaPush();
1502 }
1503 opt_block_var
1504 compstmt kEND
1505 {
1506 $$ = new RNIter(thread, $3, null, $4);
1507 $<RNode>$.FixPos($4);
1508 thread.DynaPop($<RVarmap>2);
1509 }
1510
1511 case_body : kWHEN when_args then
1512 compstmt
1513 cases
1514 {
1515 $$ = new RNWhen(thread, $2, $4, $5);
1516 }
1517
1518 when_args : args
1519 | args ',' tSTAR arg
1520 {
1521 value_expr($4);
1522 $$ = RNode.list_append(thread, $1, new RNWhen(thread, $4));
1523 }
1524 | tSTAR arg
1525 {
1526 value_expr($2);
1527 $$ = new RNArray(thread, new RNWhen(thread, $2));
1528 }
1529
1530 cases : opt_else
1531 | case_body
1532
1533 exc_list : none
1534 | args
1535
1536 exc_var : tASSOC lhs
1537 {
1538 $$ = $2;
1539 }
1540 | none
1541
1542 rescue : kRESCUE exc_list exc_var then
1543 compstmt
1544 rescue
1545 {
1546 RNode nd = $3;
1547 RNode nd2 = $5;
1548 if (nd != null) {
1549 nd = node_assign($3, new RNGVar(thread, ruby, intern("$!")));
1550 nd2 = block_append(nd, $5);
1551 }
1552 $$ = new RNResBody(thread, $2, nd2, $6);
1553 $<RNode>$.FixPos(($2 != null) ? $2 : nd2);
1554 }
1555 | none
1556
1557 ensure : none
1558 | kENSURE compstmt
1559 {
1560 if ($2 != null)
1561 $$ = $2;
1562 else
1563 /* place holder */
1564 $$ = new RNNil(thread);
1565 }
1566
1567 literal : numeric
1568 | symbol
1569 {
1570 if ($<object>1 is uint)
1571 $$ = Symbol.ID2SYM($1);
1572 else
1573 $$ = Symbol.ID2SYM($<char>1);
1574 }
1575 | tREGEXP
1576
1577 string : tSTRING
1578 {
1579 $$ = new RNStr(thread, ruby, $1);
1580 }
1581 | tDSTRING
1582 | string tSTRING
1583 {
1584 if ($1 is RNDStr) {
1585 RNode.list_append(thread, $1, new RNStr(thread, ruby, $<string>2));
1586 }
1587 else {
1588 #if STRCONCAT
1589 rb_str_concat($1.lit, $2);
1590 #else
1591 $1.lit = (string)($<RNode>1.lit) + $<string>2;
1592 #endif
1593 }
1594 $$ = $1;
1595 }
1596 | string tDSTRING
1597 {
1598 if ($1 is RNStr) {
1599 $$ = new RNDStr(thread, ruby, $1.lit);
1600 }
1601 else {
1602 $$ = $1;
1603 }
1604 $2.head = new RNStr(thread, ruby, $2.lit);
1605 RNode.list_concat($<RNode>$, new RNArray(thread, $2));
1606 }
1607
1608 symbol : tSYMBEG sym
1609 {
1610 lex.State = EXPR.END;
1611 if ($<object>2 is uint)
1612 $$ = $<uint>2;
1613 else
1614 $$ = $<char>2;
1615 }
1616
1617 sym : fname
1618 | tIVAR
1619 | tGVAR
1620 | tCVAR
1621
1622 numeric : tINTEGER
1623 | tFLOAT
1624
1625 variable : tIDENTIFIER
1626 | tIVAR
1627 | tGVAR
1628 | tCONSTANT
1629 | tCVAR
1630 | kNIL {$$ = (uint)Token.kNIL;}
1631 | kSELF {$$ = (uint)Token.kSELF;}
1632 | kTRUE {$$ = (uint)Token.kTRUE;}
1633 | kFALSE {$$ = (uint)Token.kFALSE;}
1634 | k__FILE__ {$$ = (uint)Token.k__FILE__;}
1635 | k__LINE__ {$$ = (uint)Token.k__LINE__;}
1636
1637 var_ref : variable
1638 {
1639 $$ = gettable($1);
1640 }
1641
1642 backref : tNTH_REF
1643 | tBACK_REF
1644
1645 superclass : term
1646 {
1647 $$ = null;
1648 }
1649 | '<'
1650 {
1651 lex.State = EXPR.BEG;
1652 }
1653 expr term
1654 {
1655 $$ = $3;
1656 }
1657 | error term {yyErrorFlag = 0; $$ = null;}
1658
1659 f_arglist : '(' f_args opt_nl ')'
1660 {
1661 $$ = $2;
1662 lex.State = EXPR.BEG;
1663 }
1664 | f_args term
1665 {
1666 $$ = $1;
1667 }
1668
1669 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
1670 {
1671 $$ = block_append(new RNArgs(thread, $1, $3, $5), $6);
1672 }
1673 | f_arg ',' f_optarg opt_f_block_arg
1674 {
1675 $$ = block_append(new RNArgs(thread, $1, $3, -1), $4);
1676 }
1677 | f_arg ',' f_rest_arg opt_f_block_arg
1678 {
1679 $$ = block_append(new RNArgs(thread, $1, null, $<int>3), $4);
1680 }
1681 | f_arg opt_f_block_arg
1682 {
1683 $$ = block_append(new RNArgs(thread, $1, null, -1), $2);
1684 }
1685 | f_optarg ',' f_rest_arg opt_f_block_arg
1686 {
1687 $$ = block_append(new RNArgs(thread, 0, $1, $3), $4);
1688 }
1689 | f_optarg opt_f_block_arg
1690 {
1691 $$ = block_append(new RNArgs(thread, 0, $1, -1), $2);
1692 }
1693 | f_rest_arg opt_f_block_arg
1694 {
1695 $$ = block_append(new RNArgs(thread, 0, null, $<int>1), $2);
1696 }
1697 | f_block_arg
1698 {
1699 $$ = block_append(new RNArgs(thread, 0, null, -1), $1);
1700 }
1701 | /* none */
1702 {
1703 $$ = new RNArgs(thread, 0, null, -1);
1704 }
1705
1706 f_norm_arg : tCONSTANT
1707 {
1708 yyerror("formal argument cannot be a constant");
1709 }
1710 | tIVAR
1711 {
1712 yyerror("formal argument cannot be an instance variable");
1713 }
1714 | tGVAR
1715 {
1716 yyerror("formal argument cannot be a global variable");
1717 }
1718 | tCVAR
1719 {
1720 yyerror("formal argument cannot be a class variable");
1721 }
1722 | tIDENTIFIER
1723 {
1724 if (!is_local_id($1))
1725 yyerror("formal argument must be local variable");
1726 else if (thread.LocalID($1))
1727 yyerror("duplicate argument name");
1728 thread.LocalCnt($1);
1729 $$ = 1;
1730 }
1731
1732 f_arg : f_norm_arg
1733 | f_arg ',' f_norm_arg
1734 {
1735 $$ = $<int>$ + 1;
1736 }
1737
1738 f_opt : tIDENTIFIER '=' arg
1739 {
1740 if (!is_local_id($1))
1741 yyerror("formal argument must be local variable");
1742 else if (thread.LocalID($1))
1743 yyerror("duplicate optional argument name");
1744 $$ = assignable($1, $3);
1745 }
1746
1747 f_optarg : f_opt
1748 {
1749 $$ = new RNBlock(thread, $1);
1750 $<RNode>$.end = $<RNode>$;
1751 }
1752 | f_optarg ',' f_opt
1753 {
1754 $$ = block_append($1, $3);
1755 }
1756
1757 f_rest_arg : tSTAR tIDENTIFIER
1758 {
1759 if (!is_local_id($2))
1760 yyerror("rest argument must be local variable");
1761 else if (thread.LocalID($2))
1762 yyerror("duplicate rest argument name");
1763 $$ = thread.LocalCnt($2);
1764 }
1765 | tSTAR
1766 {
1767 $$ = -2;
1768 }
1769
1770 f_block_arg : tAMPER tIDENTIFIER
1771 {
1772 if (!is_local_id($2))
1773 yyerror("block argument must be local variable");
1774 else if (thread.LocalID($2))
1775 yyerror("duplicate block argument name");
1776 $$ = new RNBlockArg(thread, $2, thread.LocalCnt($2));
1777 }
1778
1779 opt_f_block_arg : ',' f_block_arg
1780 {
1781 $$ = $2;
1782 }
1783 | none
1784
1785 singleton : var_ref
1786 {
1787 if ($1 is RNSelf) {
1788 $$ = new RNSelf(thread);
1789 }
1790 else {
1791 $$ = $1;
1792 }
1793 }
1794 | '(' {lex.State = EXPR.BEG;} expr opt_nl ')'
1795 {
1796 if ($3 is RNStr ||
1797 $3 is RNDStr ||
1798 $3 is RNXStr ||
1799 $3 is RNDXStr ||
1800 $3 is RNDRegx ||
1801 $3 is RNLit ||
1802 $3 is RNArray ||
1803 $3 is RNZArray)
1804 {
1805 yyerror("can't define single method for literals.");
1806 }
1807 $$ = $3;
1808 }
1809
1810 assoc_list : none
1811 | assocs trailer
1812 {
1813 $$ = $1;
1814 }
1815 | args trailer
1816 {
1817 if ($1.alen % 2 != 0) {
1818 yyerror("odd number list for Hash");
1819 }
1820 $$ = $1;
1821 }
1822
1823 assocs : assoc
1824 | assocs ',' assoc
1825 {
1826 $$ = RNode.list_concat($1, $3);
1827 }
1828
1829 assoc : arg tASSOC arg
1830 {
1831 $$ = RNode.list_append(thread, new RNArray(thread, $1), $3);
1832 }
1833
1834 operation : tIDENTIFIER
1835 | tCONSTANT
1836 | tFID
1837
1838 operation2 : tIDENTIFIER
1839 | tCONSTANT
1840 | tFID
1841 | op
1842
1843 operation3 : tIDENTIFIER
1844 | tFID
1845 | op
1846
1847 dot_or_colon : '.'
1848 | tCOLON2
1849
1850 opt_terms : /* none */
1851 | terms
1852
1853 opt_nl : /* none */
1854 | '\n'
1855
1856 trailer : /* none */
1857 | '\n'
1858 | ','
1859
1860 term : ';' {yyErrorFlag = 0;}
1861 | '\n'
1862
1863 terms : term
1864 | terms ';' {yyErrorFlag = 0;}
1865
1866 none : /* none */
1867 {
1868 $$ = null;
1869 }
1870 %%
1871 RNode block_append(RNode head, RNode tail)
1872 {
1873 return RNode.block_append(thread, head, tail);
1874 }
1875
1876 RNode node_assign(RNode lhs, RNode rhs)
1877 {
1878 if (lhs == null) return null;
1879
1880 value_expr(rhs);
1881 if (lhs is RNGAsgn ||
1882 lhs is RNIAsgn ||
1883 lhs is RNLAsgn ||
1884 lhs is RNDAsgn ||
1885 lhs is RNDAsgnCurr ||
1886 lhs is RNMAsgn ||
1887 lhs is RNCDecl ||
1888 lhs is RNCVDecl ||
1889 lhs is RNCVAsgn)
1890 {
1891 lhs.val = rhs;
1892 }
1893 else if (lhs is RNCall)
1894 {
1895 lhs.args = arg_add(lhs.args, rhs);
1896 }
1897 if (rhs != null)
1898 {
1899 lhs.FixPos(rhs);
1900 }
1901 return lhs;
1902 }
1903
1904 bool value_expr(RNode node)
1905 {
1906 if (node == null) return true;
1907
1908 if (node is RNReturn ||
1909 node is RNBreak ||
1910 node is RNNext ||
1911 node is RNRedo ||
1912 node is RNRetry ||
1913 node is RNWhile ||
1914 node is RNUntil ||
1915 node is RNClass ||
1916 node is RNModule ||
1917 node is RNDefn ||
1918 node is RNDefs)
1919 {
1920 yyerror("void value expression");
1921 return false;
1922 }
1923 else if (node is RNBlock)
1924 {
1925 while (node.next != null) {
1926 node = node.next;
1927 }
1928 return value_expr(node.head);
1929 }
1930 else if (node is RNBegin)
1931 {
1932 return value_expr(node.body);
1933 }
1934 else if (node is RNIf)
1935 {
1936 return value_expr(node.body) && value_expr(node.nd_else);
1937 }
1938 else if (node is RNNewLine)
1939 {
1940 return value_expr(node.next);
1941 }
1942 return true;
1943 }
1944
1945 void void_expr(RNode node)
1946 {
1947 string useless = "";
1948 if (!ruby.verbose) return;
1949 if (node == null) return;
1950 again:
1951 if (node is RNNewLine)
1952 {
1953 node = node.next;
1954 goto again;
1955 }
1956 else if (node is RNCall)
1957 {
1958 switch (node.mid) {
1959 case '+':
1960 case '-':
1961 case '*':
1962 case '/':
1963 case '%':
1964 case Token.tPOW:
1965 case Token.tUPLUS:
1966 case Token.tUMINUS:
1967 case '|':
1968 case '^':
1969 case '&':
1970 case Token.tCMP:
1971 case '>':
1972 case Token.tGEQ:
1973 case '<':
1974 case Token.tLEQ:
1975 case Token.tEQ:
1976 case Token.tNEQ:
1977 useless = id2name(node.mid);
1978 break;
1979 }
1980 }
1981 else if (node is RNLVar ||
1982 node is RNDVar ||
1983 node is RNIVar ||
1984 node is RNCVar ||
1985 node is RNNthRef ||
1986 node is RNBackRef)
1987 {
1988 useless = "a variable";
1989 }
1990 else if (node is RNConst ||
1991 node is RNCRef)
1992 {
1993 useless = "a constant";
1994 }
1995 else if (node is RNLit ||
1996 node is RNStr ||
1997 node is RNDStr ||
1998 node is RNDRegx ||
1999 node is RNDRegxOnce)
2000 {
2001 useless = "a literal";
2002 }
2003 else if (node is RNColon2 ||
2004 node is RNColon3)
2005 {
2006 useless = "::";
2007 }
2008 else if (node is RNDot2)
2009 {
2010 useless = "..";
2011 }
2012 else if (node is RNDot3)
2013 {
2014 useless = "...";
2015 }
2016 else if (node is RNSelf)
2017 {
2018 useless = "self";
2019 }
2020 else if (node is RNNil)
2021 {
2022 useless = "nil";
2023 }
2024 else if (node is RNTrue)
2025 {
2026 useless = "true";
2027 }
2028 else if (node is RNFalse)
2029 {
2030 useless = "false";
2031 }
2032 else if (node is RNDefined)
2033 {
2034 useless = "defined?";
2035 }
2036
2037 if (useless.Length > 0) {
2038 int line = sourceline;
2039 sourceline = node.Line;
2040 ruby.warn("useless use of {0} in void context", useless);
2041 sourceline = line;
2042 }
2043 }
2044
2045 bool assign_in_cond(RNode node)
2046 {
2047 if (node is RNMAsgn)
2048 {
2049 yyerror("multiple assignment in conditional");
2050 return true;
2051 }
2052 else if (node is RNLAsgn ||
2053 node is RNDAsgn ||
2054 node is RNGAsgn ||
2055 node is RNIAsgn)
2056 {
2057 }
2058 else if (node is RNNewLine)
2059 {
2060 return false;
2061 }
2062 else
2063 {
2064 return false;
2065 }
2066
2067 RNode rn = node.val;
2068 if (rn is RNLit ||
2069 rn is RNStr ||
2070 rn is RNNil ||
2071 rn is RNTrue ||
2072 rn is RNFalse)
2073 {
2074 /* reports always */
2075 ruby.warn("found = in conditional, should be ==");
2076 return true;
2077 }
2078 else if (rn is RNDStr ||
2079 rn is RNXStr ||
2080 rn is RNDXStr ||
2081 rn is RNEvStr ||
2082 rn is RNDRegx)
2083 {
2084 }
2085 return true;
2086 }
2087
2088 void void_stmts(RNode node)
2089 {
2090 if (!ruby.verbose) return;
2091 if (node == null) return;
2092 if (node is RNBlock == false) return;
2093
2094 for (;;) {
2095 if (node.next == null) return;
2096 void_expr(node.head);
2097 node = node.next;
2098 }
2099 }
2100
2101 RNode call_op(RNode recv, uint id, int narg, RNode arg1)
2102 {
2103 value_expr(recv);
2104 if (narg == 1) {
2105 value_expr(arg1);
2106 }
2107 return new RNCall(thread, recv, id, narg==1?new RNArray(thread, arg1):null);
2108 }
2109
2110 RNode cond0(RNode node)
2111 {
2112 // check bad assignment
2113 assign_in_cond(node);
2114
2115 if (node is RNDRegx ||
2116 node is RNDRegxOnce)
2117 {
2118 thread.LocalCnt('_');
2119 thread.LocalCnt('~');
2120 return new RNMatch2(thread, node, new RNGVar(thread, ruby, intern("$_")));
2121 }
2122 else if (node is RNDot2 || node is RNDot3)
2123 {
2124 node.beg = cond2(node.beg);
2125 node.end = cond2(node.end);
2126 if (node is RNDot2)
2127 {
2128 node = new RNFlip2(node);
2129 }
2130 else
2131 {
2132 node = new RNFlip3(node);
2133 }
2134 node.cnt = (int)thread.LocalAppend(0);
2135 return node;
2136 }
2137 else if (node is RNLit)
2138 {
2139 if (node.lit is RRegexp) {
2140 thread.LocalCnt('_');
2141 thread.LocalCnt('~');
2142 return new RNMatch(thread, node);
2143 }
2144 if (node.lit is string || node.lit is RString) {
2145 thread.LocalCnt('_');
2146 thread.LocalCnt('~');
2147 return new RNMatch(thread, RRegexpClass.s_new(ruby.cRegexp, node.lit));
2148 }
2149 }
2150 return node;
2151 }
2152
2153 RNode cond(RNode node)
2154 {
2155 if (node == null) return null;
2156 if (node is RNNewLine)
2157 {
2158 node = cond0(node.next);
2159 return node;
2160 }
2161 return cond0(node);
2162 }
2163
2164 RNode cond2(RNode node)
2165 {
2166 node = cond(node);
2167 if (node is RNNewLine)
2168 {
2169 node = node.next;
2170 }
2171 else if (node is RNLit && (node.lit is int || node.lit is Decimal))
2172 {
2173 return call_op(node,Token.tEQ,1,new RNGVar(thread, ruby, intern("$.")));
2174 }
2175 return node;
2176 }
2177
2178 RNode logop(Type tp, RNode left, RNode right)
2179 {
2180 value_expr(left);
2181 BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic
2182 | BindingFlags.InvokeMethod;
2183 ConstructorInfo ctr = tp.GetConstructor(bf, null,
2184 new Type[] {typeof(RThread), typeof(RNode), typeof(RNode)}, null);
2185 return (RNode)ctr.Invoke(new object[] {thread, cond(left), cond(right)});
2186 }
2187
2188 RNode arg_blk_pass(RNode node1, RNode node2)
2189 {
2190 if (node2 != null)
2191 {
2192 node2.head = node1;
2193 return node2;
2194 }
2195 return node1;
2196 }
2197
2198 RNode new_call(RNode r, uint m, RNode a)
2199 {
2200 if (a != null && a is RNBlockPass) {
2201 a.iter = new RNCall(thread, r, m, a.head);
2202 return a;
2203 }
2204 return new RNCall(thread, r, m, a);
2205 }
2206
2207 RNode new_fcall(uint m, RNode a)
2208 {
2209 if (a != null && a is RNBlockPass) {
2210 a.iter = new RNFCall(thread, m, a.head);
2211 return a;
2212 }
2213 return new RNFCall(thread, m, a);
2214 }
2215
2216 RNode new_super(RNode a)
2217 {
2218 if (a != null && a is RNBlockPass) {
2219 a.iter = new RNSuper(thread, a.head);
2220 return a;
2221 }
2222 return new RNSuper(thread, a);
2223 }
2224
2225 RNode aryset(RNode recv, RNode idx)
2226 {
2227 value_expr(recv);
2228 return new RNCall(thread, recv, Token.tASET, idx);
2229 }
2230
2231 static internal uint id_attrset(uint id)
2232 {
2233 id &= ~(uint)ID.SCOPE_MASK;
2234 id |= (uint)ID.ATTRSET;
2235 return id;
2236 }
2237
2238 RNode attrset(RNode recv, uint id)
2239 {
2240 value_expr(recv);
2241
2242 return new RNCall(thread, recv, id_attrset(id), null);
2243 }
2244
2245 void backref_error(RNode node)
2246 {
2247 if (node is RNNthRef)
2248 {
2249 thread.CompileError("Can't set variable $" + node.nth.ToString());
2250 }
2251 else if (node is RNBackRef)
2252 {
2253 thread.CompileError("Can't set variable $" + node.nth.ToString());
2254 }
2255 }
2256
2257 RNode arg_concat(RNode node1, RNode node2)
2258 {
2259 if (node2 == null) return node1;
2260 return new RNArgsCat(thread, node1, node2);
2261 }
2262
2263 RNode arg_add(RNode node1, RNode node2)
2264 {
2265 if (node1 == null) return new RNArray(thread, node2);
2266 if (node1 is RNArray)
2267 {
2268 return ((RNArray)node1).append(thread, node2);
2269 }
2270 else {
2271 return new RNArgsPush(thread, node1, node2);
2272 }
2273 }
2274
2275 static public bool is_notop_id(uint id)
2276 {
2277 return (id > Token.LAST_TOKEN);
2278 }
2279 static public bool is_local_id(uint id)
2280 {
2281 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.LOCAL));
2282 }
2283 static public uint make_const_id(uint id)
2284 {
2285 return (id & ~(uint)ID.SCOPE_MASK) | (uint)ID.CONST;
2286 }
2287 static public bool is_global_id(uint id)
2288 {
2289 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.GLOBAL));
2290 }
2291 static public bool is_instance_id(uint id)
2292 {
2293 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.INSTANCE));
2294 }
2295 static public bool is_attrset_id(uint id)
2296 {
2297 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.ATTRSET));
2298 }
2299 static public uint make_local_id(uint id)
2300 {
2301 return (id & ~(uint)ID.SCOPE_MASK) | (uint)ID.LOCAL;
2302 }
2303 static public bool is_const_id(uint id)
2304 {
2305 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.CONST));
2306 }
2307 static public bool is_class_id(uint id)
2308 {
2309 return (id > Token.LAST_TOKEN && ((id & (uint)ID.SCOPE_MASK) == (uint)ID.CLASS));
2310 }
2311
2312 RNode match_gen(RNode node1, RNode node2)
2313 {
2314 thread.LocalCnt('~');
2315
2316 if (node1 is RNDRegx || node1 is RNDRegxOnce)
2317 {
2318 return new RNMatch2(thread, node1, node2);
2319 }
2320 else if (node1 is RNLit)
2321 {
2322 if (node1.lit is Regex)
2323 {
2324 return new RNMatch2(thread, node1, node2);
2325 }
2326 }
2327
2328 if (node2 is RNDRegx || node2 is RNDRegxOnce)
2329 {
2330 return new RNMatch3(thread, node2, node1);
2331 }
2332 else if (node2 is RNLit)
2333 {
2334 if (node2.lit is Regex) {
2335 return new RNMatch3(thread, node2, node1);
2336 }
2337 }
2338
2339 return new RNCall(thread,node1, Token.tMATCH, new RNArray(thread, node2));
2340 }
2341
2342 RNode gettable(uint id)
2343 {
2344 if (id == Token.kSELF) {
2345 return new RNSelf(thread);
2346 }
2347 else if (id == Token.kNIL) {
2348 return new RNNil(thread);
2349 }
2350 else if (id == Token.kTRUE) {
2351 return new RNTrue(thread);
2352 }
2353 else if (id == Token.kFALSE) {
2354 return new RNFalse(thread);
2355 }
2356 else if (id == Token.k__FILE__) {
2357 RString f = new RString(ruby, sourcefile);
2358 f.Freeze();
2359 return new RNStr(thread, ruby, f);
2360 }
2361 else if (id == Token.k__LINE__) {
2362 return new RNLit(thread, sourceline);
2363 }
2364 else if (is_local_id(id)) {
2365 if (thread.IsDynaInBlock && thread.dvar_defined(id))
2366 return new RNDVar(thread, id);
2367 if (thread.LocalID(id)) return new RNLVar(thread, id);
2368 /* method call without arguments */
2369 return new RNVCall(thread, id);
2370 }
2371 else if (is_global_id(id)) {
2372 return new RNGVar(thread, ruby, id);
2373 }
2374 else if (is_instance_id(id)) {
2375 return new RNIVar(thread, id);
2376 }
2377 else if (is_const_id(id)) {
2378 return new RNConst(thread, id);
2379 }
2380 else if (is_class_id(id)) {
2381 if (in_single > 0) return new RNCVar2(thread, id);
2382 return new RNCVar(thread, id);
2383 }
2384 ruby.bug("invalid id for gettable");
2385 return null;
2386 }
2387
2388
2389 RNode assignable(uint id, RNode val)
2390 {
2391 value_expr(val);
2392 if (id == Token.kSELF) {
2393 yyerror("Can't change the value of self");
2394 }
2395 else if (id == Token.kNIL) {
2396 yyerror("Can't assign to nil");
2397 }
2398 else if (id == Token.kTRUE) {
2399 yyerror("Can't assign to true");
2400 }
2401 else if (id == Token.kFALSE) {
2402 yyerror("Can't assign to false");
2403 }
2404 else if (id == Token.k__FILE__) {
2405 yyerror("Can't assign to __FILE__");
2406 }
2407 else if (id == Token.k__LINE__) {
2408 yyerror("Can't assign to __LINE__");
2409 }
2410 else if (is_local_id(id)) {
2411 if (thread.dvar_curr(id)) {
2412 return new RNDAsgnCurr(thread, id, val);
2413 }
2414 else if (thread.dvar_defined(id)) {
2415 return new RNDAsgn(thread, id, val);
2416 }
2417 else if (thread.LocalID(id) || !thread.IsDynaInBlock) {
2418 return new RNLAsgn(thread, id, val);
2419 }
2420 else{
2421 thread.dvar_push(id, null);
2422 return new RNDAsgn(thread, id, val);
2423 }
2424 }
2425 else if (is_global_id(id)) {
2426 return new RNGAsgn(thread, ruby, id, val);
2427 }
2428 else if (is_instance_id(id)) {
2429 return new RNIAsgn(thread, id, val);
2430 }
2431 else if (is_const_id(id)) {
2432 if (in_def > 0 || in_single > 0)
2433 yyerror("dynamic constant assignment");
2434 return new RNCDecl(thread, id, val);
2435 }
2436 else if (is_class_id(id)) {
2437 if (in_single > 0) return new RNCVAsgn(thread, id, val);
2438 return new RNCVDecl(thread, id, val);
2439 }
2440 else {
2441 ruby.bug("bad id for variable");
2442 }
2443 return null;
2444 }
2445
2446 private uint intern(string name)
2447 {
2448 return ruby.intern(name);
2449 }
2450
2451 private string id2name(uint id)
2452 {
2453 if (id < Token.LAST_TOKEN) {
2454 int i = 0;
2455
2456 for (i=0; i < NetRuby.op_tbl.Length; i++) {
2457 if (NetRuby.op_tbl[i].token == id)
2458 return NetRuby.op_tbl[i].name;
2459 }
2460 }
2461 string name = null;
2462
2463 if (ruby.sym_rev_tbl.lookup(id, out name))
2464 return name;
2465
2466 if (is_attrset_id(id)) {
2467 uint id2 = make_local_id(id);
2468
2469 again:
2470 name = id2name(id2);
2471 if (name != null) {
2472 string buf = name + "=";
2473 intern(name + "=");
2474 return id2name(id);
2475 }
2476 if (is_local_id(id2)) {
2477 id2 = make_const_id(id);
2478 goto again;
2479 }
2480 }
2481 return null;
2482 }
2483
2484
2485 }
2486

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26