parse.y
DEFINITIONS
This source file includes following functions.
- yyparse
- SIGN_EXTEND_CHAR
- SIGN_EXTEND_CHAR
- yyerror
- yycompile
- lex_get_str
- lex_getline
- rb_compile_string
- rb_compile_cstr
- rb_compile_file
- nextc
- pushback
- newtok
- tokadd
- read_escape
- tokadd_escape
- regx_options
- tokadd_string
- parse_string
- heredoc_identifier
- heredoc_restore
- whole_match_p
- here_document
- arg_ambiguous
- yylex
- rb_node_newnode
- nodetype
- nodeline
- newline_node
- fixpos
- block_append
- list_append
- list_concat
- literal_concat_string
- literal_concat_dstr
- literal_concat_list
- literal_append
- literal_concat
- call_op
- match_gen
- gettable
- assignable
- aryset
- rb_id_attrset
- attrset
- rb_backref_error
- arg_concat
- arg_add
- node_assign
- value_expr
- void_expr
- void_stmts
- assign_in_cond
- e_option_supplied
- warn_unless_e_option
- warning_unless_e_option
- range_op
- cond0
- cond
- logop
- ret_args
- arg_blk_pass
- arg_prepend
- new_call
- new_fcall
- new_super
- local_push
- local_pop
- local_tbl
- local_append
- local_cnt
- local_id
- top_local_init
- top_local_setup
- dyna_push
- dyna_pop
- dyna_in_block
- ruby_parser_stack_on_heap
- rb_gc_mark_parser
- rb_parser_append_print
- rb_parser_while_loop
- Init_sym
- internal_id
- rb_intern
- rb_id2name
- symbols_i
- rb_sym_all_symbols
- rb_is_const_id
- rb_is_class_id
- rb_is_instance_id
- rb_is_local_id
- special_local_set
- rb_backref_get
- rb_backref_set
- rb_lastline_get
- rb_lastline_set
1
2
3
4
5
6
7
8
9
10
11
12
13 %{
14
15 #define YYDEBUG 1
16
17 #include "ruby.h"
18 #include "env.h"
19 #include "intern.h"
20 #include "node.h"
21 #include "st.h"
22 #include <stdio.h>
23 #include <errno.h>
24 #include <ctype.h>
25
26 #define yyparse ruby_yyparse
27 #define yylex ruby_yylex
28 #define yyerror ruby_yyerror
29 #define yylval ruby_yylval
30 #define yychar ruby_yychar
31 #define yydebug ruby_yydebug
32
33 #define ID_SCOPE_SHIFT 3
34 #define ID_SCOPE_MASK 0x07
35 #define ID_LOCAL 0x01
36 #define ID_INSTANCE 0x02
37 #define ID_GLOBAL 0x03
38 #define ID_ATTRSET 0x04
39 #define ID_CONST 0x05
40 #define ID_CLASS 0x06
41 #define ID_JUNK 0x07
42 #define ID_INTERNAL ID_JUNK
43
44 #define is_notop_id(id) ((id)>LAST_TOKEN)
45 #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
46 #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
47 #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
48 #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
49 #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
50 #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
51
52 NODE *ruby_eval_tree_begin = 0;
53 NODE *ruby_eval_tree = 0;
54
55 char *ruby_sourcefile;
56 int ruby_sourceline;
57
58 static int yylex();
59 static int yyerror();
60
61 static enum lex_state {
62 EXPR_BEG,
63 EXPR_END,
64 EXPR_ARG,
65 EXPR_CMDARG,
66 EXPR_ENDARG,
67 EXPR_MID,
68 EXPR_FNAME,
69 EXPR_DOT,
70 EXPR_CLASS,
71 } lex_state;
72 static NODE *lex_strterm;
73 static int lex_strnest;
74
75 #ifdef HAVE_LONG_LONG
76 typedef unsigned LONG_LONG stack_type;
77 #else
78 typedef unsigned long stack_type;
79 #endif
80
81 static stack_type cond_stack = 0;
82 #define COND_PUSH(n) (cond_stack = (cond_stack<<1)|((n)&1))
83 #define COND_POP() (cond_stack >>= 1)
84 #define COND_LEXPOP() do {\
85 int last = COND_P();\
86 cond_stack >>= 1;\
87 if (last) cond_stack |= 1;\
88 } while (0)
89 #define COND_P() (cond_stack&1)
90
91 static stack_type cmdarg_stack = 0;
92 #define CMDARG_PUSH(n) (cmdarg_stack = (cmdarg_stack<<1)|((n)&1))
93 #define CMDARG_POP() (cmdarg_stack >>= 1)
94 #define CMDARG_LEXPOP() do {\
95 int last = CMDARG_P();\
96 cmdarg_stack >>= 1;\
97 if (last) cmdarg_stack |= 1;\
98 } while (0)
99 #define CMDARG_P() (cmdarg_stack&1)
100
101 static int class_nest = 0;
102 static int in_single = 0;
103 static int in_def = 0;
104 static int compile_for_eval = 0;
105 static ID cur_mid = 0;
106 static int quoted_term;
107 #define quoted_term_char ((unsigned char)quoted_term)
108 #define WHEN_QUOTED_TERM(x) ((quoted_term >= 0) && (x))
109 #define QUOTED_TERM_P(c) WHEN_QUOTED_TERM((c) == quoted_term_char)
110
111 static NODE *cond();
112 static NODE *logop();
113
114 static NODE *newline_node();
115 static void fixpos();
116
117 static int value_expr();
118 static void void_expr();
119 static void void_stmts();
120
121 static NODE *block_append();
122 static NODE *list_append();
123 static NODE *list_concat();
124 static NODE *arg_concat();
125 static NODE *arg_prepend();
126 static NODE *literal_concat();
127 static NODE *literal_append();
128 static NODE *call_op();
129 static int in_defined = 0;
130
131 static NODE *ret_args();
132 static NODE *arg_blk_pass();
133 static NODE *new_call();
134 static NODE *new_fcall();
135 static NODE *new_super();
136
137 static NODE *gettable();
138 static NODE *assignable();
139 static NODE *aryset();
140 static NODE *attrset();
141 static void rb_backref_error();
142 static NODE *node_assign();
143
144 static NODE *match_gen();
145 static void local_push();
146 static void local_pop();
147 static int local_append();
148 static int local_cnt();
149 static int local_id();
150 static ID *local_tbl();
151 static ID internal_id();
152
153 static struct RVarmap *dyna_push();
154 static void dyna_pop();
155 static int dyna_in_block();
156
157 static void top_local_init();
158 static void top_local_setup();
159
160 #define RE_OPTION_ONCE 0x80
161
162 #define NODE_STRTERM NODE_ZARRAY
163 #define NODE_HEREDOC NODE_ARRAY
164 #define nd_func u1.id
165 #define nd_term u2.id
166 #define nd_paren u3.id
167
168 %}
169
170 %union {
171 NODE *node;
172 ID id;
173 int num;
174 struct RVarmap *vars;
175 }
176
177 %token kCLASS
178 kMODULE
179 kDEF
180 kUNDEF
181 kBEGIN
182 kRESCUE
183 kENSURE
184 kEND
185 kIF
186 kUNLESS
187 kTHEN
188 kELSIF
189 kELSE
190 kCASE
191 kWHEN
192 kWHILE
193 kUNTIL
194 kFOR
195 kBREAK
196 kNEXT
197 kREDO
198 kRETRY
199 kIN
200 kDO
201 kDO_COND
202 kDO_BLOCK
203 kRETURN
204 kYIELD
205 kSUPER
206 kSELF
207 kNIL
208 kTRUE
209 kFALSE
210 kAND
211 kOR
212 kNOT
213 kIF_MOD
214 kUNLESS_MOD
215 kWHILE_MOD
216 kUNTIL_MOD
217 kRESCUE_MOD
218 kALIAS
219 kDEFINED
220 klBEGIN
221 klEND
222 k__LINE__
223 k__FILE__
224
225 %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR
226 %token <node> tINTEGER tFLOAT tSTRING_CONTENT
227 %token <node> tNTH_REF tBACK_REF
228 %token <num> tREGEXP_END
229
230 %type <node> singleton strings string string1 xstring regexp
231 %type <node> string_contents xstring_contents string_content
232 %type <node> words qwords word_list qword_list word
233 %type <node> literal numeric
234 %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
235 %type <node> expr_value arg_value primary_value
236 %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
237 %type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
238 %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
239 %type <node> mrhs mrhs_basic superclass block_call block_command
240 %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
241 %type <node> assoc_list assocs assoc undef_list backref string_dvar
242 %type <node> block_var opt_block_var brace_block do_block lhs none
243 %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
244 %type <id> fitem variable sym symbol operation operation2 operation3
245 %type <id> cname fname op f_rest_arg
246 %type <num> f_norm_arg f_arg term_push
247 %token tUPLUS
248 %token tUMINUS
249 %token tPOW
250 %token tCMP
251 %token tEQ
252 %token tEQQ
253 %token tNEQ
254 %token tGEQ
255 %token tLEQ
256 %token tANDOP tOROP
257 %token tMATCH tNMATCH
258 %token tDOT2 tDOT3
259 %token tAREF tASET
260 %token tLSHFT tRSHFT
261 %token tCOLON2
262 %token tCOLON3
263 %token <id> tOP_ASGN
264 %token tASSOC
265 %token tLPAREN
266 %token tLPAREN_ARG
267 %token tRPAREN
268 %token tLBRACK
269 %token tLBRACE
270 %token tLBRACE_ARG
271 %token tSTAR
272 %token tAMPER
273 %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
274 %token tSTRING_DBEG tSTRING_DVAR tSTRING_END
275
276
277
278
279
280 %left kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD kRESCUE_MOD
281 %left kOR kAND
282 %right kNOT
283 %nonassoc kDEFINED
284 %right '=' tOP_ASGN
285 %right '?' ':'
286 %nonassoc tDOT2 tDOT3
287 %left tOROP
288 %left tANDOP
289 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
290 %left '>' tGEQ '<' tLEQ
291 %left '|' '^'
292 %left '&'
293 %left tLSHFT tRSHFT
294 %left '+' '-'
295 %left '*' '/' '%'
296 %right '!' '~' tUPLUS tUMINUS
297 %right tPOW
298
299 %token LAST_TOKEN
300
301 %%
302 program : {
303 lex_state = EXPR_BEG;
304 top_local_init();
305 if ((VALUE)ruby_class == rb_cObject) class_nest = 0;
306 else class_nest = 1;
307 }
308 compstmt
309 {
310 if ($2 && !compile_for_eval) {
311
312 if (nd_type($2) != NODE_BLOCK) void_expr($2);
313 else {
314 NODE *node = $2;
315 while (node->nd_next) {
316 node = node->nd_next;
317 }
318 void_expr(node->nd_head);
319 }
320 }
321 ruby_eval_tree = block_append(ruby_eval_tree, $2);
322 top_local_setup();
323 class_nest = 0;
324 }
325 ;
326
327 bodystmt : compstmt
328 opt_rescue
329 opt_else
330 opt_ensure
331 {
332 $$ = $1;
333 if ($2) {
334 $$ = NEW_RESCUE($1, $2, $3);
335 }
336 else if ($3) {
337 rb_warn("else without rescue is useless");
338 $$ = block_append($$, $3);
339 }
340 if ($4) {
341 $$ = NEW_ENSURE($$, $4);
342 }
343 fixpos($$, $1);
344 }
345 ;
346
347 compstmt : stmts opt_terms
348 {
349 void_stmts($1);
350 $$ = $1;
351 }
352 ;
353
354 stmts : none
355 | stmt
356 {
357 $$ = newline_node($1);
358 }
359 | stmts terms stmt
360 {
361 $$ = block_append($1, newline_node($3));
362 }
363 | error stmt
364 {
365 $$ = $2;
366 }
367 ;
368
369 stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
370 {
371 $$ = NEW_ALIAS($2, $4);
372 }
373 | kALIAS tGVAR tGVAR
374 {
375 $$ = NEW_VALIAS($2, $3);
376 }
377 | kALIAS tGVAR tBACK_REF
378 {
379 char buf[3];
380
381 sprintf(buf, "$%c", $3->nd_nth);
382 $$ = NEW_VALIAS($2, rb_intern(buf));
383 }
384 | kALIAS tGVAR tNTH_REF
385 {
386 yyerror("can't make alias for the number variables");
387 $$ = 0;
388 }
389 | kUNDEF undef_list
390 {
391 $$ = $2;
392 }
393 | stmt kIF_MOD expr_value
394 {
395 $$ = NEW_IF(cond($3), $1, 0);
396 fixpos($$, $3);
397 }
398 | stmt kUNLESS_MOD expr_value
399 {
400 $$ = NEW_UNLESS(cond($3), $1, 0);
401 fixpos($$, $3);
402 }
403 | stmt kWHILE_MOD expr_value
404 {
405 if ($1 && nd_type($1) == NODE_BEGIN) {
406 $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
407 }
408 else {
409 $$ = NEW_WHILE(cond($3), $1, 1);
410 }
411 }
412 | stmt kUNTIL_MOD expr_value
413 {
414 if ($1 && nd_type($1) == NODE_BEGIN) {
415 $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
416 }
417 else {
418 $$ = NEW_UNTIL(cond($3), $1, 1);
419 }
420 }
421 | stmt kRESCUE_MOD stmt
422 {
423 $$ = NEW_RESCUE($1, NEW_RESBODY(0,$3,0), 0);
424 }
425 | klBEGIN
426 {
427 if (in_def || in_single) {
428 yyerror("BEGIN in method");
429 }
430 local_push(0);
431 }
432 '{' compstmt '}'
433 {
434 ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
435 NEW_PREEXE($4));
436 local_pop();
437 $$ = 0;
438 }
439 | klEND '{' compstmt '}'
440 {
441 if (compile_for_eval && (in_def || in_single)) {
442 yyerror("END in method; use at_exit");
443 }
444
445 $$ = NEW_ITER(0, NEW_POSTEXE(), $3);
446 }
447 | lhs '=' command_call
448 {
449 $$ = node_assign($1, $3);
450 }
451 | mlhs '=' command_call
452 {
453 value_expr($3);
454 $1->nd_value = $3;
455 $$ = $1;
456 }
457 | var_lhs tOP_ASGN command_call
458 {
459 value_expr($3);
460 if ($1) {
461 ID vid = $1->nd_vid;
462 if ($2 == tOROP) {
463 $1->nd_value = $3;
464 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
465 if (is_instance_id(vid)) {
466 $$->nd_aid = vid;
467 }
468 }
469 else if ($2 == tANDOP) {
470 $1->nd_value = $3;
471 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
472 }
473 else {
474 $$ = $1;
475 $$->nd_value = call_op(gettable(vid),$2,1,$3);
476 }
477 }
478 else {
479 $$ = 0;
480 }
481 }
482 | primary_value '[' aref_args ']' tOP_ASGN command_call
483 {
484 NODE *args;
485
486 value_expr($6);
487 args = NEW_LIST($6);
488 $3 = list_append($3, NEW_NIL());
489 list_concat(args, $3);
490 if ($5 == tOROP) {
491 $5 = 0;
492 }
493 else if ($5 == tANDOP) {
494 $5 = 1;
495 }
496 $$ = NEW_OP_ASGN1($1, $5, args);
497 fixpos($$, $1);
498 }
499 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
500 {
501 value_expr($5);
502 if ($4 == tOROP) {
503 $4 = 0;
504 }
505 else if ($4 == tANDOP) {
506 $4 = 1;
507 }
508 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
509 fixpos($$, $1);
510 }
511 | primary_value '.' tCONSTANT tOP_ASGN command_call
512 {
513 value_expr($5);
514 if ($4 == tOROP) {
515 $4 = 0;
516 }
517 else if ($4 == tANDOP) {
518 $4 = 1;
519 }
520 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
521 fixpos($$, $1);
522 }
523 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
524 {
525 value_expr($5);
526 if ($4 == tOROP) {
527 $4 = 0;
528 }
529 else if ($4 == tANDOP) {
530 $4 = 1;
531 }
532 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
533 fixpos($$, $1);
534 }
535 | backref tOP_ASGN command_call
536 {
537 rb_backref_error($1);
538 $$ = 0;
539 }
540 | lhs '=' mrhs_basic
541 {
542 $$ = node_assign($1, NEW_REXPAND($3));
543 }
544 | mlhs '=' mrhs
545 {
546 $1->nd_value = $3;
547 $$ = $1;
548 }
549 | expr
550 ;
551
552 expr : kRETURN call_args
553 {
554 if (!compile_for_eval && !in_def && !in_single)
555 yyerror("return appeared outside of method");
556 $$ = NEW_RETURN(ret_args($2));
557 }
558 | kBREAK call_args
559 {
560 $$ = NEW_BREAK(ret_args($2));
561 }
562 | kNEXT call_args
563 {
564 $$ = NEW_NEXT(ret_args($2));
565 }
566 | command_call
567 | expr kAND expr
568 {
569 $$ = logop(NODE_AND, $1, $3);
570 }
571 | expr kOR expr
572 {
573 $$ = logop(NODE_OR, $1, $3);
574 }
575 | kNOT expr
576 {
577 $$ = NEW_NOT(cond($2));
578 }
579 | '!' command_call
580 {
581 $$ = NEW_NOT(cond($2));
582 }
583 | arg
584 ;
585
586 expr_value : expr
587 {
588 value_expr($$);
589 $$ = $1;
590 }
591 ;
592
593 command_call : command
594 | block_command
595 ;
596
597 block_command : block_call
598 | block_call '.' operation2 command_args
599 {
600 $$ = new_call($1, $3, $4);
601 }
602 | block_call tCOLON2 operation2 command_args
603 {
604 $$ = new_call($1, $3, $4);
605 }
606 ;
607
608 command : operation command_args
609 {
610 $$ = new_fcall($1, $2);
611 fixpos($$, $2);
612 }
613 | primary_value '.' operation2 command_args
614 {
615 $$ = new_call($1, $3, $4);
616 fixpos($$, $1);
617 }
618 | primary_value tCOLON2 operation2 command_args
619 {
620 $$ = new_call($1, $3, $4);
621 fixpos($$, $1);
622 }
623 | kSUPER command_args
624 {
625 $$ = new_super($2);
626 fixpos($$, $2);
627 }
628 | kYIELD command_args
629 {
630 $$ = NEW_YIELD(ret_args($2));
631 fixpos($$, $2);
632 }
633 ;
634
635 mlhs : mlhs_basic
636 | tLPAREN mlhs_entry ')'
637 {
638 $$ = $2;
639 }
640 ;
641
642 mlhs_entry : mlhs_basic
643 | tLPAREN mlhs_entry ')'
644 {
645 $$ = NEW_MASGN(NEW_LIST($2), 0);
646 }
647 ;
648
649 mlhs_basic : mlhs_head
650 {
651 $$ = NEW_MASGN($1, 0);
652 }
653 | mlhs_head mlhs_item
654 {
655 $$ = NEW_MASGN(list_append($1,$2), 0);
656 }
657 | mlhs_head tSTAR mlhs_node
658 {
659 $$ = NEW_MASGN($1, $3);
660 }
661 | mlhs_head tSTAR
662 {
663 $$ = NEW_MASGN($1, -1);
664 }
665 | tSTAR mlhs_node
666 {
667 $$ = NEW_MASGN(0, $2);
668 }
669 | tSTAR
670 {
671 $$ = NEW_MASGN(0, -1);
672 }
673 ;
674
675 mlhs_item : mlhs_node
676 | tLPAREN mlhs_entry ')'
677 {
678 $$ = $2;
679 }
680 ;
681
682 mlhs_head : mlhs_item ','
683 {
684 $$ = NEW_LIST($1);
685 }
686 | mlhs_head mlhs_item ','
687 {
688 $$ = list_append($1, $2);
689 }
690 ;
691
692 mlhs_node : variable
693 {
694 $$ = assignable($1, 0);
695 }
696 | primary_value '[' aref_args ']'
697 {
698 $$ = aryset($1, $3);
699 }
700 | primary_value '.' tIDENTIFIER
701 {
702 $$ = attrset($1, $3);
703 }
704 | primary_value tCOLON2 tIDENTIFIER
705 {
706 $$ = attrset($1, $3);
707 }
708 | primary_value '.' tCONSTANT
709 {
710 $$ = attrset($1, $3);
711 }
712 | backref
713 {
714 rb_backref_error($1);
715 $$ = 0;
716 }
717 ;
718
719 lhs : variable
720 {
721 $$ = assignable($1, 0);
722 }
723 | primary_value '[' aref_args ']'
724 {
725 $$ = aryset($1, $3);
726 }
727 | primary_value '.' tIDENTIFIER
728 {
729 $$ = attrset($1, $3);
730 }
731 | primary_value tCOLON2 tIDENTIFIER
732 {
733 $$ = attrset($1, $3);
734 }
735 | primary_value '.' tCONSTANT
736 {
737 $$ = attrset($1, $3);
738 }
739 | backref
740 {
741 rb_backref_error($1);
742 $$ = 0;
743 }
744 ;
745
746 cname : tIDENTIFIER
747 {
748 yyerror("class/module name must be CONSTANT");
749 }
750 | tCONSTANT
751 ;
752
753 fname : tIDENTIFIER
754 | tCONSTANT
755 | tFID
756 | op
757 {
758 lex_state = EXPR_END;
759 $$ = $1;
760 }
761 | reswords
762 {
763 lex_state = EXPR_END;
764 $$ = $<id>1;
765 }
766 ;
767
768 fitem : fname
769 | symbol
770 ;
771
772 undef_list : fitem
773 {
774 $$ = NEW_UNDEF($1);
775 }
776 | undef_list ',' {lex_state = EXPR_FNAME;} fitem
777 {
778 $$ = block_append($1, NEW_UNDEF($4));
779 }
780 ;
781
782 op : '|' { $$ = '|'; }
783 | '^' { $$ = '^'; }
784 | '&' { $$ = '&'; }
785 | tCMP { $$ = tCMP; }
786 | tEQ { $$ = tEQ; }
787 | tEQQ { $$ = tEQQ; }
788 | tMATCH { $$ = tMATCH; }
789 | '>' { $$ = '>'; }
790 | tGEQ { $$ = tGEQ; }
791 | '<' { $$ = '<'; }
792 | tLEQ { $$ = tLEQ; }
793 | tLSHFT { $$ = tLSHFT; }
794 | tRSHFT { $$ = tRSHFT; }
795 | '+' { $$ = '+'; }
796 | '-' { $$ = '-'; }
797 | '*' { $$ = '*'; }
798 | tSTAR { $$ = '*'; }
799 | '/' { $$ = '/'; }
800 | '%' { $$ = '%'; }
801 | tPOW { $$ = tPOW; }
802 | '~' { $$ = '~'; }
803 | tUPLUS { $$ = tUPLUS; }
804 | tUMINUS { $$ = tUMINUS; }
805 | tAREF { $$ = tAREF; }
806 | tASET { $$ = tASET; }
807 | '`' { $$ = '`'; }
808 ;
809
810 reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
811 | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
812 | kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
813 | kFOR | kIF_MOD | kIN | kMODULE | kNEXT | kNIL | kNOT
814 | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
815 | kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
816 | kWHILE_MOD | kYIELD | kRESCUE_MOD
817 ;
818
819 arg : lhs '=' arg
820 {
821 $$ = node_assign($1, $3);
822 }
823 | var_lhs tOP_ASGN arg
824 {
825 value_expr($3);
826 if ($1) {
827 ID vid = $1->nd_vid;
828 if ($2 == tOROP) {
829 $1->nd_value = $3;
830 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
831 if (is_instance_id(vid)) {
832 $$->nd_aid = vid;
833 }
834 }
835 else if ($2 == tANDOP) {
836 $1->nd_value = $3;
837 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
838 }
839 else {
840 $$ = $1;
841 $$->nd_value = call_op(gettable(vid),$2,1,$3);
842 }
843 }
844 else {
845 $$ = 0;
846 }
847 }
848 | primary_value '[' aref_args ']' tOP_ASGN arg
849 {
850 NODE *args;
851
852 value_expr($6);
853 args = NEW_LIST($6);
854 $3 = list_append($3, NEW_NIL());
855 list_concat(args, $3);
856 if ($5 == tOROP) {
857 $5 = 0;
858 }
859 else if ($5 == tANDOP) {
860 $5 = 1;
861 }
862 $$ = NEW_OP_ASGN1($1, $5, args);
863 fixpos($$, $1);
864 }
865 | primary_value '.' tIDENTIFIER tOP_ASGN arg
866 {
867 value_expr($5);
868 if ($4 == tOROP) {
869 $4 = 0;
870 }
871 else if ($4 == tANDOP) {
872 $4 = 1;
873 }
874 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
875 fixpos($$, $1);
876 }
877 | primary_value '.' tCONSTANT tOP_ASGN arg
878 {
879 value_expr($5);
880 if ($4 == tOROP) {
881 $4 = 0;
882 }
883 else if ($4 == tANDOP) {
884 $4 = 1;
885 }
886 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
887 fixpos($$, $1);
888 }
889 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
890 {
891 value_expr($5);
892 if ($4 == tOROP) {
893 $4 = 0;
894 }
895 else if ($4 == tANDOP) {
896 $4 = 1;
897 }
898 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
899 fixpos($$, $1);
900 }
901 | backref tOP_ASGN arg
902 {
903 rb_backref_error($1);
904 $$ = 0;
905 }
906 | arg tDOT2 arg
907 {
908 value_expr($1);
909 value_expr($3);
910 $$ = NEW_DOT2($1, $3);
911 }
912 | arg tDOT3 arg
913 {
914 value_expr($1);
915 value_expr($3);
916 $$ = NEW_DOT3($1, $3);
917 }
918 | arg '+' arg
919 {
920 $$ = call_op($1, '+', 1, $3);
921 }
922 | arg '-' arg
923 {
924 $$ = call_op($1, '-', 1, $3);
925 }
926 | arg '*' arg
927 {
928 $$ = call_op($1, '*', 1, $3);
929 }
930 | arg '/' arg
931 {
932 $$ = call_op($1, '/', 1, $3);
933 }
934 | arg '%' arg
935 {
936 $$ = call_op($1, '%', 1, $3);
937 }
938 | arg tPOW arg
939 {
940 $$ = call_op($1, tPOW, 1, $3);
941 }
942 | tUPLUS arg
943 {
944 if ($2 && nd_type($2) == NODE_LIT) {
945 $$ = $2;
946 }
947 else {
948 $$ = call_op($2, tUPLUS, 0, 0);
949 }
950 }
951 | tUMINUS arg
952 {
953 if ($2 && nd_type($2) == NODE_LIT && FIXNUM_P($2->nd_lit)) {
954 long i = FIX2LONG($2->nd_lit);
955
956 $2->nd_lit = LONG2NUM(-i);
957 $$ = $2;
958 }
959 else {
960 $$ = call_op($2, tUMINUS, 0, 0);
961 }
962 }
963 | arg '|' arg
964 {
965 $$ = call_op($1, '|', 1, $3);
966 }
967 | arg '^' arg
968 {
969 $$ = call_op($1, '^', 1, $3);
970 }
971 | arg '&' arg
972 {
973 $$ = call_op($1, '&', 1, $3);
974 }
975 | arg tCMP arg
976 {
977 $$ = call_op($1, tCMP, 1, $3);
978 }
979 | arg '>' arg
980 {
981 $$ = call_op($1, '>', 1, $3);
982 }
983 | arg tGEQ arg
984 {
985 $$ = call_op($1, tGEQ, 1, $3);
986 }
987 | arg '<' arg
988 {
989 $$ = call_op($1, '<', 1, $3);
990 }
991 | arg tLEQ arg
992 {
993 $$ = call_op($1, tLEQ, 1, $3);
994 }
995 | arg tEQ arg
996 {
997 $$ = call_op($1, tEQ, 1, $3);
998 }
999 | arg tEQQ arg
1000 {
1001 $$ = call_op($1, tEQQ, 1, $3);
1002 }
1003 | arg tNEQ arg
1004 {
1005 $$ = NEW_NOT(call_op($1, tEQ, 1, $3));
1006 }
1007 | arg tMATCH arg
1008 {
1009 $$ = match_gen($1, $3);
1010 }
1011 | arg tNMATCH arg
1012 {
1013 $$ = NEW_NOT(match_gen($1, $3));
1014 }
1015 | '!' arg
1016 {
1017 $$ = NEW_NOT(cond($2));
1018 }
1019 | '~' arg
1020 {
1021 $$ = call_op($2, '~', 0, 0);
1022 }
1023 | arg tLSHFT arg
1024 {
1025 $$ = call_op($1, tLSHFT, 1, $3);
1026 }
1027 | arg tRSHFT arg
1028 {
1029 $$ = call_op($1, tRSHFT, 1, $3);
1030 }
1031 | arg tANDOP arg
1032 {
1033 $$ = logop(NODE_AND, $1, $3);
1034 }
1035 | arg tOROP arg
1036 {
1037 $$ = logop(NODE_OR, $1, $3);
1038 }
1039 | kDEFINED opt_nl {in_defined = 1;} arg
1040 {
1041 in_defined = 0;
1042 $$ = NEW_DEFINED($4);
1043 }
1044 | arg '?' arg ':' arg
1045 {
1046 $$ = NEW_IF(cond($1), $3, $5);
1047 fixpos($$, $1);
1048 }
1049 | primary
1050 {
1051 $$ = $1;
1052 }
1053 ;
1054
1055 arg_value : arg
1056 {
1057 value_expr($1);
1058 $$ = $1;
1059 }
1060 ;
1061
1062 aref_args : none
1063 | command opt_nl
1064 {
1065 rb_warn("parenthesize argument(s) for future version");
1066 $$ = NEW_LIST($1);
1067 }
1068 | args trailer
1069 {
1070 $$ = $1;
1071 }
1072 | args ',' tSTAR arg opt_nl
1073 {
1074 value_expr($4);
1075 $$ = arg_concat($1, $4);
1076 }
1077 | assocs trailer
1078 {
1079 $$ = NEW_LIST(NEW_HASH($1));
1080 }
1081 | tSTAR arg opt_nl
1082 {
1083 value_expr($2);
1084 $$ = NEW_RESTARY($2);
1085 }
1086 ;
1087
1088 paren_args : '(' none ')'
1089 {
1090 $$ = $2;
1091 }
1092 | '(' call_args opt_nl ')'
1093 {
1094 $$ = $2;
1095 }
1096 | '(' block_call opt_nl ')'
1097 {
1098 rb_warn("parenthesize argument for future version");
1099 $$ = NEW_LIST($2);
1100 }
1101 | '(' args ',' block_call opt_nl ')'
1102 {
1103 rb_warn("parenthesize argument for future version");
1104 $$ = list_append($2, $4);
1105 }
1106 ;
1107
1108 opt_paren_args : none
1109 | paren_args
1110 ;
1111
1112 call_args : command
1113 {
1114 rb_warn("parenthesize argument(s) for future version");
1115 $$ = NEW_LIST($1);
1116 }
1117 | args opt_block_arg
1118 {
1119 $$ = arg_blk_pass($1, $2);
1120 }
1121 | args ',' tSTAR arg_value opt_block_arg
1122 {
1123 $$ = arg_concat($1, $4);
1124 $$ = arg_blk_pass($$, $5);
1125 }
1126 | assocs opt_block_arg
1127 {
1128 $$ = NEW_LIST(NEW_HASH($1));
1129 $$ = arg_blk_pass($$, $2);
1130 }
1131 | assocs ',' tSTAR arg_value opt_block_arg
1132 {
1133 $$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
1134 $$ = arg_blk_pass($$, $5);
1135 }
1136 | args ',' assocs opt_block_arg
1137 {
1138 $$ = list_append($1, NEW_HASH($3));
1139 $$ = arg_blk_pass($$, $4);
1140 }
1141 | args ',' assocs ',' tSTAR arg opt_block_arg
1142 {
1143 value_expr($6);
1144 $$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
1145 $$ = arg_blk_pass($$, $7);
1146 }
1147 | tSTAR arg_value opt_block_arg
1148 {
1149 $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
1150 }
1151 | block_arg
1152 ;
1153
1154 call_args2 : arg_value ',' args opt_block_arg
1155 {
1156 $$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
1157 }
1158 | arg_value ',' block_arg
1159 {
1160 $$ = arg_blk_pass($1, $3);
1161 }
1162 | arg_value ',' tSTAR arg_value opt_block_arg
1163 {
1164 $$ = arg_concat(NEW_LIST($1), $4);
1165 $$ = arg_blk_pass($$, $5);
1166 }
1167 | arg_value ',' args ',' tSTAR arg_value opt_block_arg
1168 {
1169 $$ = arg_concat(list_concat($1,$3), $6);
1170 $$ = arg_blk_pass($$, $7);
1171 }
1172 | assocs opt_block_arg
1173 {
1174 $$ = NEW_LIST(NEW_HASH($1));
1175 $$ = arg_blk_pass($$, $2);
1176 }
1177 | assocs ',' tSTAR arg_value opt_block_arg
1178 {
1179 $$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
1180 $$ = arg_blk_pass($$, $5);
1181 }
1182 | arg_value ',' assocs opt_block_arg
1183 {
1184 $$ = list_append(NEW_LIST($1), NEW_HASH($3));
1185 $$ = arg_blk_pass($$, $4);
1186 }
1187 | arg_value ',' args ',' assocs opt_block_arg
1188 {
1189 $$ = list_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
1190 $$ = arg_blk_pass($$, $6);
1191 }
1192 | arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
1193 {
1194 $$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
1195 $$ = arg_blk_pass($$, $7);
1196 }
1197 | arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
1198 {
1199 $$ = arg_concat(list_append(list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
1200 $$ = arg_blk_pass($$, $9);
1201 }
1202 | tSTAR arg_value opt_block_arg
1203 {
1204 $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
1205 }
1206 | block_arg
1207 ;
1208
1209 command_args : {
1210 $<num>$ = cmdarg_stack;
1211 CMDARG_PUSH(1);
1212 }
1213 open_args
1214 {
1215
1216 cmdarg_stack = $<num>1;
1217 $$ = $2;
1218 }
1219 ;
1220
1221 open_args : call_args
1222 | tLPAREN_ARG {lex_state = EXPR_ENDARG;} ')'
1223 {
1224 rb_warning("%s (...) interpreted as method call",
1225 rb_id2name($<id>1));
1226 $$ = 0;
1227 }
1228 | tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ')'
1229 {
1230 rb_warning("%s (...) interpreted as method call",
1231 rb_id2name($<id>1));
1232 $$ = $2;
1233 }
1234 ;
1235
1236 block_arg : tAMPER arg_value
1237 {
1238 $$ = NEW_BLOCK_PASS($2);
1239 }
1240 ;
1241
1242 opt_block_arg : ',' block_arg
1243 {
1244 $$ = $2;
1245 }
1246 | none
1247 ;
1248
1249 args : arg_value
1250 {
1251 $$ = NEW_LIST($1);
1252 }
1253 | args ',' arg_value
1254 {
1255 $$ = list_append($1, $3);
1256 }
1257 ;
1258
1259 mrhs : arg_value
1260 {
1261 $$ = $1;
1262 }
1263 | mrhs_basic
1264 {
1265 $$ = NEW_REXPAND($1);
1266 }
1267 ;
1268
1269 mrhs_basic : args ',' arg_value
1270 {
1271 $$ = list_append($1, $3);
1272 }
1273 | args ',' tSTAR arg_value
1274 {
1275 $$ = arg_concat($1, $4);
1276 }
1277 | tSTAR arg_value
1278 {
1279 $$ = $2;
1280 }
1281 ;
1282
1283 primary : literal
1284 | strings
1285 | xstring
1286 | regexp
1287 | words
1288 | qwords
1289 | var_ref
1290 | backref
1291 | tFID
1292 {
1293 $$ = NEW_VCALL($1);
1294 }
1295 | kBEGIN
1296 bodystmt
1297 kEND
1298 {
1299 $$ = NEW_BEGIN($2);
1300 }
1301 | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} ')'
1302 {
1303 rb_warning("(...) interpreted as grouped expression");
1304 $$ = $2;
1305 }
1306 | tLPAREN compstmt ')'
1307 {
1308 $$ = $2;
1309 }
1310 | primary_value tCOLON2 tCONSTANT
1311 {
1312 $$ = NEW_COLON2($1, $3);
1313 }
1314 | tCOLON3 cname
1315 {
1316 $$ = NEW_COLON3($2);
1317 }
1318 | primary_value '[' aref_args ']'
1319 {
1320 $$ = NEW_CALL($1, tAREF, $3);
1321 }
1322 | tLBRACK aref_args ']'
1323 {
1324 if ($2 == 0) {
1325 $$ = NEW_ZARRAY();
1326 }
1327 else {
1328 $$ = $2;
1329 }
1330 }
1331 | tLBRACE assoc_list '}'
1332 {
1333 $$ = NEW_HASH($2);
1334 }
1335 | kRETURN
1336 {
1337 if (!compile_for_eval && !in_def && !in_single)
1338 yyerror("return appeared outside of method");
1339 $$ = NEW_RETURN(0);
1340 }
1341 | kYIELD '(' call_args ')'
1342 {
1343 $$ = NEW_YIELD(ret_args($3));
1344 }
1345 | kYIELD '(' ')'
1346 {
1347 $$ = NEW_YIELD(0);
1348 }
1349 | kYIELD
1350 {
1351 $$ = NEW_YIELD(0);
1352 }
1353 | kDEFINED opt_nl '(' {in_defined = 1;} expr ')'
1354 {
1355 in_defined = 0;
1356 $$ = NEW_DEFINED($5);
1357 }
1358 | operation brace_block
1359 {
1360 $2->nd_iter = NEW_FCALL($1, 0);
1361 $$ = $2;
1362 }
1363 | method_call
1364 | method_call brace_block
1365 {
1366 if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
1367 rb_compile_error("both block arg and actual block given");
1368 }
1369 $2->nd_iter = $1;
1370 $$ = $2;
1371 fixpos($$, $1);
1372 }
1373 | kIF expr_value then
1374 compstmt
1375 if_tail
1376 kEND
1377 {
1378 $$ = NEW_IF(cond($2), $4, $5);
1379 fixpos($$, $2);
1380 }
1381 | kUNLESS expr_value then
1382 compstmt
1383 opt_else
1384 kEND
1385 {
1386 $$ = NEW_UNLESS(cond($2), $4, $5);
1387 fixpos($$, $2);
1388 }
1389 | kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
1390 compstmt
1391 kEND
1392 {
1393 $$ = NEW_WHILE(cond($3), $6, 1);
1394 fixpos($$, $3);
1395 }
1396 | kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();}
1397 compstmt
1398 kEND
1399 {
1400 $$ = NEW_UNTIL(cond($3), $6, 1);
1401 fixpos($$, $3);
1402 }
1403 | kCASE expr_value opt_terms
1404 case_body
1405 kEND
1406 {
1407 $$ = NEW_CASE($2, $4);
1408 fixpos($$, $2);
1409 }
1410 | kCASE opt_terms case_body kEND
1411 {
1412 $$ = $3;
1413 }
1414 | kFOR block_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
1415 compstmt
1416 kEND
1417 {
1418 $$ = NEW_FOR($2, $5, $8);
1419 fixpos($$, $2);
1420 }
1421 | kCLASS cname superclass
1422 {
1423 if (in_def || in_single)
1424 yyerror("class definition in method body");
1425 class_nest++;
1426 local_push(0);
1427 $<num>$ = ruby_sourceline;
1428 }
1429 bodystmt
1430 kEND
1431 {
1432 $$ = NEW_CLASS($2, $5, $3);
1433 nd_set_line($$, $<num>4);
1434 local_pop();
1435 class_nest--;
1436 }
1437 | kCLASS tLSHFT expr
1438 {
1439 $<num>$ = in_def;
1440 in_def = 0;
1441 }
1442 term
1443 {
1444 $<num>$ = in_single;
1445 in_single = 0;
1446 class_nest++;
1447 local_push(0);
1448 }
1449 bodystmt
1450 kEND
1451 {
1452 $$ = NEW_SCLASS($3, $7);
1453 fixpos($$, $3);
1454 local_pop();
1455 class_nest--;
1456 in_def = $<num>4;
1457 in_single = $<num>6;
1458 }
1459 | kMODULE cname
1460 {
1461 if (in_def || in_single)
1462 yyerror("module definition in method body");
1463 class_nest++;
1464 local_push(0);
1465 $<num>$ = ruby_sourceline;
1466 }
1467 bodystmt
1468 kEND
1469 {
1470 $$ = NEW_MODULE($2, $4);
1471 nd_set_line($$, $<num>3);
1472 local_pop();
1473 class_nest--;
1474 }
1475 | kDEF fname
1476 {
1477 $<id>$ = cur_mid;
1478 cur_mid = $2;
1479 in_def++;
1480 local_push(0);
1481 }
1482 f_arglist
1483 bodystmt
1484 kEND
1485 {
1486
1487 $$ = NEW_DEFN($2, $4, $5, class_nest?NOEX_PUBLIC:NOEX_PRIVATE);
1488 if (is_attrset_id($2)) $$->nd_noex = NOEX_PUBLIC;
1489 fixpos($$, $4);
1490 local_pop();
1491 in_def--;
1492 cur_mid = $<id>3;
1493 }
1494 | kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
1495 {
1496 in_single++;
1497 local_push(0);
1498 lex_state = EXPR_END;
1499 }
1500 f_arglist
1501 bodystmt
1502 kEND
1503 {
1504 $$ = NEW_DEFS($2, $5, $7, $8);
1505 fixpos($$, $2);
1506 local_pop();
1507 in_single--;
1508 }
1509 | kBREAK
1510 {
1511 $$ = NEW_BREAK(0);
1512 }
1513 | kNEXT
1514 {
1515 $$ = NEW_NEXT(0);
1516 }
1517 | kREDO
1518 {
1519 $$ = NEW_REDO();
1520 }
1521 | kRETRY
1522 {
1523 $$ = NEW_RETRY();
1524 }
1525 ;
1526
1527 primary_value : primary
1528 {
1529 value_expr($1);
1530 $$ = $1;
1531 }
1532 ;
1533
1534 then : term
1535 | kTHEN
1536 | term kTHEN
1537 ;
1538
1539 do : term
1540 | kDO_COND
1541 ;
1542
1543 if_tail : opt_else
1544 | kELSIF expr_value then
1545 compstmt
1546 if_tail
1547 {
1548 $$ = NEW_IF(cond($2), $4, $5);
1549 fixpos($$, $2);
1550 }
1551 ;
1552
1553 opt_else : none
1554 | kELSE compstmt
1555 {
1556 $$ = $2;
1557 }
1558 ;
1559
1560 block_var : lhs
1561 | mlhs
1562 ;
1563
1564 opt_block_var : none
1565 | '|' '|'
1566 {
1567 $$ = (NODE*)1;
1568 }
1569 | tOROP
1570 {
1571 $$ = (NODE*)1;
1572 }
1573 | '|' block_var '|'
1574 {
1575 $$ = $2;
1576 }
1577 ;
1578
1579 do_block : kDO_BLOCK
1580 {
1581 $<vars>$ = dyna_push();
1582 }
1583 opt_block_var
1584 compstmt
1585 kEND
1586 {
1587 $$ = NEW_ITER($3, 0, $4);
1588 fixpos($$, $3?$3:$4);
1589 dyna_pop($<vars>2);
1590 }
1591 | tLBRACE_ARG {$<vars>$ = dyna_push();}
1592 opt_block_var
1593 compstmt
1594 '}'
1595 {
1596 $$ = NEW_ITER($3, 0, $4);
1597 fixpos($$, $3?$3:$4);
1598 dyna_pop($<vars>2);
1599 }
1600
1601 ;
1602
1603 block_call : command do_block
1604 {
1605 if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
1606 rb_compile_error("both block arg and actual block given");
1607 }
1608 $2->nd_iter = $1;
1609 $$ = $2;
1610 fixpos($$, $2);
1611 }
1612 | block_call '.' operation2 opt_paren_args
1613 {
1614 $$ = new_call($1, $3, $4);
1615 }
1616 | block_call tCOLON2 operation2 opt_paren_args
1617 {
1618 $$ = new_call($1, $3, $4);
1619 }
1620 ;
1621
1622 method_call : operation paren_args
1623 {
1624 $$ = new_fcall($1, $2);
1625 fixpos($$, $2);
1626 }
1627 | primary_value '.' operation2 opt_paren_args
1628 {
1629 $$ = new_call($1, $3, $4);
1630 fixpos($$, $1);
1631 }
1632 | primary_value tCOLON2 operation2 paren_args
1633 {
1634 $$ = new_call($1, $3, $4);
1635 fixpos($$, $1);
1636 }
1637 | primary_value tCOLON2 operation3
1638 {
1639 $$ = new_call($1, $3, 0);
1640 }
1641 | kSUPER paren_args
1642 {
1643 $$ = new_super($2);
1644 }
1645 | kSUPER
1646 {
1647 $$ = NEW_ZSUPER();
1648 }
1649 ;
1650
1651 brace_block : '{'
1652 {
1653 $<vars>$ = dyna_push();
1654 }
1655 opt_block_var
1656 compstmt '}'
1657 {
1658 $$ = NEW_ITER($3, 0, $4);
1659 fixpos($$, $4);
1660 dyna_pop($<vars>2);
1661 }
1662 | kDO
1663 {
1664 $<vars>$ = dyna_push();
1665 }
1666 opt_block_var
1667 compstmt kEND
1668 {
1669 $$ = NEW_ITER($3, 0, $4);
1670 fixpos($$, $4);
1671 dyna_pop($<vars>2);
1672 }
1673 ;
1674
1675 case_body : kWHEN when_args then
1676 compstmt
1677 cases
1678 {
1679 $$ = NEW_WHEN($2, $4, $5);
1680 }
1681 ;
1682
1683 when_args : args
1684 | args ',' tSTAR arg_value
1685 {
1686 $$ = list_append($1, NEW_WHEN($4, 0, 0));
1687 }
1688 | tSTAR arg_value
1689 {
1690 $$ = NEW_LIST(NEW_WHEN($2, 0, 0));
1691 }
1692 ;
1693
1694 cases : opt_else
1695 | case_body
1696 ;
1697
1698 opt_rescue : kRESCUE exc_list exc_var then
1699 compstmt
1700 opt_rescue
1701 {
1702 if ($3) {
1703 $3 = node_assign($3, NEW_GVAR(rb_intern("$!")));
1704 $5 = block_append($3, $5);
1705 }
1706 $$ = NEW_RESBODY($2, $5, $6);
1707 fixpos($$, $2?$2:$5);
1708 }
1709 | none
1710 ;
1711
1712 exc_list : args
1713 | none
1714 ;
1715
1716 exc_var : tASSOC lhs
1717 {
1718 $$ = $2;
1719 }
1720 | none
1721 ;
1722
1723 opt_ensure : kENSURE compstmt
1724 {
1725 if ($2)
1726 $$ = $2;
1727 else
1728
1729 $$ = NEW_NIL();
1730 }
1731 | none
1732 ;
1733
1734 literal : numeric
1735 | symbol
1736 {
1737 $$ = NEW_LIT(ID2SYM($1));
1738 }
1739 ;
1740
1741 strings : string
1742 {
1743 NODE *node = $1;
1744 if (!node) {
1745 node = NEW_STR(rb_str_new(0, 0));
1746 }
1747 else {
1748 switch (nd_type(node)) {
1749 case NODE_STR: case NODE_DSTR:
1750 break;
1751 default:
1752 node = rb_node_newnode(NODE_DSTR, rb_str_new(0, 0),
1753 1, NEW_LIST(node));
1754 break;
1755 }
1756 }
1757 $$ = node;
1758 }
1759 ;
1760
1761 string : string1
1762 | string string1
1763 {
1764 $$ = literal_concat($1, $2);
1765 }
1766 ;
1767
1768 string1 : tSTRING_BEG string_contents tSTRING_END
1769 {
1770 $$ = $2;
1771 }
1772 ;
1773
1774 xstring : tXSTRING_BEG xstring_contents tSTRING_END
1775 {
1776 NODE *node = $2;
1777 if (!node) {
1778 node = NEW_XSTR(rb_str_new(0, 0));
1779 }
1780 else {
1781 switch (nd_type(node)) {
1782 case NODE_STR:
1783 nd_set_type(node, NODE_XSTR);
1784 break;
1785 case NODE_DSTR:
1786 nd_set_type(node, NODE_DXSTR);
1787 break;
1788 default:
1789 node = rb_node_newnode(NODE_DXSTR, rb_str_new(0, 0),
1790 1, NEW_LIST(node));
1791 break;
1792 }
1793 }
1794 $$ = node;
1795 }
1796 ;
1797
1798 regexp : tREGEXP_BEG xstring_contents tREGEXP_END
1799 {
1800 int options = $3;
1801 NODE *node = $2;
1802 if (!node) {
1803 node = NEW_LIT(rb_reg_new("", 0, options & ~RE_OPTION_ONCE));
1804 }
1805 else switch (nd_type(node)) {
1806 case NODE_STR:
1807 {
1808 VALUE src = node->nd_lit;
1809 nd_set_type(node, NODE_LIT);
1810 node->nd_lit = rb_reg_new(RSTRING(src)->ptr,
1811 RSTRING(src)->len,
1812 options & ~RE_OPTION_ONCE);
1813 }
1814 break;
1815 default:
1816 node = rb_node_newnode(NODE_DSTR, rb_str_new(0, 0),
1817 1, NEW_LIST(node));
1818 case NODE_DSTR:
1819 if (options & RE_OPTION_ONCE) {
1820 nd_set_type(node, NODE_DREGX_ONCE);
1821 }
1822 else {
1823 nd_set_type(node, NODE_DREGX);
1824 }
1825 node->nd_cflag = options & ~RE_OPTION_ONCE;
1826 break;
1827 }
1828 $$ = node;
1829 }
1830 ;
1831
1832 words : tWORDS_BEG ' ' tSTRING_END
1833 {
1834 $$ = NEW_ZARRAY();
1835 }
1836 | tWORDS_BEG word_list tSTRING_END
1837 {
1838 $$ = $2;
1839 }
1840 ;
1841
1842 word_list :
1843 {
1844 lex_strnest = 0;
1845 $$ = 0;
1846 }
1847 | word_list word ' '
1848 {
1849 $$ = list_append($1, $2);
1850 }
1851 ;
1852
1853 word : string_content
1854 | word string_content
1855 {
1856 $$ = literal_concat($1, $2);
1857 }
1858 ;
1859
1860 qwords : tQWORDS_BEG ' ' tSTRING_END
1861 {
1862 $$ = NEW_ZARRAY();
1863 }
1864 | tQWORDS_BEG qword_list tSTRING_END
1865 {
1866 $$ = $2;
1867 }
1868 ;
1869
1870 qword_list :
1871 {
1872 lex_strnest = 0;
1873 $$ = 0;
1874 }
1875 | qword_list tSTRING_CONTENT ' '
1876 {
1877 $$ = list_append($1, $2);
1878 }
1879 ;
1880
1881 string_contents :
1882 {
1883 lex_strnest = 0;
1884 $$ = 0;
1885 }
1886 | string_contents string_content
1887 {
1888 $$ = literal_concat($1, $2);
1889 }
1890 ;
1891
1892 xstring_contents:
1893 {
1894 lex_strnest = 0;
1895 $$ = 0;
1896 }
1897 | xstring_contents string_content
1898 {
1899 $$ = literal_append($1, $2);
1900 }
1901 ;
1902
1903 string_content : tSTRING_CONTENT
1904 | tSTRING_DVAR
1905 {
1906 $<num>1 = lex_strnest;
1907 $<node>$ = lex_strterm;
1908 lex_strterm = 0;
1909 lex_state = EXPR_BEG;
1910 }
1911 string_dvar
1912 {
1913 lex_strnest = $<num>1;
1914 lex_strterm = $<node>2;
1915 $$ = NEW_EVSTR($3);
1916 }
1917 | tSTRING_DBEG term_push
1918 {
1919 $<num>1 = lex_strnest;
1920 $<node>$ = lex_strterm;
1921 lex_strterm = 0;
1922 lex_state = EXPR_BEG;
1923 }
1924 compstmt '}'
1925 {
1926 lex_strnest = $<num>1;
1927 quoted_term = $2;
1928 lex_strterm = $<node>3;
1929 if (($$ = $4) && nd_type($$) == NODE_NEWLINE) {
1930 $$ = $$->nd_next;
1931 rb_gc_force_recycle((VALUE)$4);
1932 }
1933 $$ = NEW_EVSTR($$);
1934 }
1935 ;
1936
1937 string_dvar : tGVAR {$$ = NEW_GVAR($1);}
1938 | tIVAR {$$ = NEW_IVAR($1);}
1939 | tCVAR {$$ = NEW_CVAR($1);}
1940 | backref
1941 ;
1942
1943 term_push :
1944 {
1945 if (($$ = quoted_term) == -1 &&
1946 nd_type(lex_strterm) == NODE_STRTERM &&
1947 !lex_strterm->nd_paren) {
1948 quoted_term = lex_strterm->nd_term;
1949 }
1950 }
1951 ;
1952
1953 symbol : tSYMBEG sym
1954 {
1955 lex_state = EXPR_END;
1956 $$ = $2;
1957 }
1958 ;
1959
1960 sym : fname
1961 | tIVAR
1962 | tGVAR
1963 | tCVAR
1964 ;
1965
1966 numeric : tINTEGER
1967 | tFLOAT
1968 ;
1969
1970 variable : tIDENTIFIER
1971 | tIVAR
1972 | tGVAR
1973 | tCONSTANT
1974 | tCVAR
1975 | kNIL {$$ = kNIL;}
1976 | kSELF {$$ = kSELF;}
1977 | kTRUE {$$ = kTRUE;}
1978 | kFALSE {$$ = kFALSE;}
1979 | k__FILE__ {$$ = k__FILE__;}
1980 | k__LINE__ {$$ = k__LINE__;}
1981 ;
1982
1983 var_ref : variable
1984 {
1985 $$ = gettable($1);
1986 }
1987 ;
1988
1989 var_lhs : variable
1990 {
1991 $$ = assignable($1, 0);
1992 }
1993 ;
1994
1995 backref : tNTH_REF
1996 | tBACK_REF
1997 ;
1998
1999 superclass : term
2000 {
2001 $$ = 0;
2002 }
2003 | '<'
2004 {
2005 lex_state = EXPR_BEG;
2006 }
2007 expr_value term
2008 {
2009 $$ = $3;
2010 }
2011 | error term {yyerrok; $$ = 0;}
2012 ;
2013
2014 f_arglist : '(' f_args opt_nl ')'
2015 {
2016 $$ = $2;
2017 lex_state = EXPR_BEG;
2018 }
2019 | f_args term
2020 {
2021 $$ = $1;
2022 }
2023 ;
2024
2025 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
2026 {
2027 $$ = block_append(NEW_ARGS($1, $3, $5), $6);
2028 }
2029 | f_arg ',' f_optarg opt_f_block_arg
2030 {
2031 $$ = block_append(NEW_ARGS($1, $3, -1), $4);
2032 }
2033 | f_arg ',' f_rest_arg opt_f_block_arg
2034 {
2035 $$ = block_append(NEW_ARGS($1, 0, $3), $4);
2036 }
2037 | f_arg opt_f_block_arg
2038 {
2039 $$ = block_append(NEW_ARGS($1, 0, -1), $2);
2040 }
2041 | f_optarg ',' f_rest_arg opt_f_block_arg
2042 {
2043 $$ = block_append(NEW_ARGS(0, $1, $3), $4);
2044 }
2045 | f_optarg opt_f_block_arg
2046 {
2047 $$ = block_append(NEW_ARGS(0, $1, -1), $2);
2048 }
2049 | f_rest_arg opt_f_block_arg
2050 {
2051 $$ = block_append(NEW_ARGS(0, 0, $1), $2);
2052 }
2053 | f_block_arg
2054 {
2055 $$ = block_append(NEW_ARGS(0, 0, -1), $1);
2056 }
2057 |
2058 {
2059 $$ = NEW_ARGS(0, 0, -1);
2060 }
2061 ;
2062
2063 f_norm_arg : tCONSTANT
2064 {
2065 yyerror("formal argument cannot be a constant");
2066 }
2067 | tIVAR
2068 {
2069 yyerror("formal argument cannot be an instance variable");
2070 }
2071 | tGVAR
2072 {
2073 yyerror("formal argument cannot be a global variable");
2074 }
2075 | tCVAR
2076 {
2077 yyerror("formal argument cannot be a class variable");
2078 }
2079 | tIDENTIFIER
2080 {
2081 if (!is_local_id($1))
2082 yyerror("formal argument must be local variable");
2083 else if (local_id($1))
2084 yyerror("duplicate argument name");
2085 local_cnt($1);
2086 $$ = 1;
2087 }
2088 ;
2089
2090 f_arg : f_norm_arg
2091 | f_arg ',' f_norm_arg
2092 {
2093 $$ += 1;
2094 }
2095 ;
2096
2097 f_opt : tIDENTIFIER '=' arg_value
2098 {
2099 if (!is_local_id($1))
2100 yyerror("formal argument must be local variable");
2101 else if (local_id($1))
2102 yyerror("duplicate optional argument name");
2103 $$ = assignable($1, $3);
2104 }
2105 ;
2106
2107 f_optarg : f_opt
2108 {
2109 $$ = NEW_BLOCK($1);
2110 $$->nd_end = $$;
2111 }
2112 | f_optarg ',' f_opt
2113 {
2114 $$ = block_append($1, $3);
2115 }
2116 ;
2117
2118 f_rest_arg : tSTAR tIDENTIFIER
2119 {
2120 if (!is_local_id($2))
2121 yyerror("rest argument must be local variable");
2122 else if (local_id($2))
2123 yyerror("duplicate rest argument name");
2124 $$ = local_cnt($2);
2125 }
2126 | tSTAR
2127 {
2128 $$ = -2;
2129 }
2130 ;
2131
2132 f_block_arg : tAMPER tIDENTIFIER
2133 {
2134 if (!is_local_id($2))
2135 yyerror("block argument must be local variable");
2136 else if (local_id($2))
2137 yyerror("duplicate block argument name");
2138 $$ = NEW_BLOCK_ARG($2);
2139 }
2140 ;
2141
2142 opt_f_block_arg : ',' f_block_arg
2143 {
2144 $$ = $2;
2145 }
2146 | none
2147 ;
2148
2149 singleton : var_ref
2150 {
2151 if (nd_type($1) == NODE_SELF) {
2152 $$ = NEW_SELF();
2153 }
2154 else {
2155 $$ = $1;
2156 value_expr($$);
2157 }
2158 }
2159 | '(' {lex_state = EXPR_BEG;} expr opt_nl ')'
2160 {
2161 if ($3 == 0) {
2162 yyerror("can't define single method for ().");
2163 }
2164 else {
2165 switch (nd_type($3)) {
2166 case NODE_STR:
2167 case NODE_DSTR:
2168 case NODE_XSTR:
2169 case NODE_DXSTR:
2170 case NODE_DREGX:
2171 case NODE_LIT:
2172 case NODE_ARRAY:
2173 case NODE_ZARRAY:
2174 yyerror("can't define single method for literals");
2175 default:
2176 value_expr($3);
2177 break;
2178 }
2179 }
2180 $$ = $3;
2181 }
2182 ;
2183
2184 assoc_list : none
2185 | assocs trailer
2186 {
2187 $$ = $1;
2188 }
2189 | args trailer
2190 {
2191 if ($1->nd_alen%2 != 0) {
2192 yyerror("odd number list for Hash");
2193 }
2194 $$ = $1;
2195 }
2196 ;
2197
2198 assocs : assoc
2199 | assocs ',' assoc
2200 {
2201 $$ = list_concat($1, $3);
2202 }
2203 ;
2204
2205 assoc : arg_value tASSOC arg_value
2206 {
2207 $$ = list_append(NEW_LIST($1), $3);
2208 }
2209 ;
2210
2211 operation : tIDENTIFIER
2212 | tCONSTANT
2213 | tFID
2214 ;
2215
2216 operation2 : tIDENTIFIER
2217 | tCONSTANT
2218 | tFID
2219 | op
2220 ;
2221
2222 operation3 : tIDENTIFIER
2223 | tFID
2224 | op
2225 ;
2226
2227 dot_or_colon : '.'
2228 | tCOLON2
2229 ;
2230
2231 opt_terms :
2232 | terms
2233 ;
2234
2235 opt_nl :
2236 | '\n'
2237 ;
2238
2239 trailer :
2240 | '\n'
2241 | ','
2242 ;
2243
2244 term : ';' {yyerrok;}
2245 | '\n'
2246 ;
2247
2248 terms : term
2249 | terms ';' {yyerrok;}
2250 ;
2251
2252 none : {$$ = 0;}
2253 ;
2254 %%
2255 #include "regex.h"
2256 #include "util.h"
2257
2258
2259
2260
2261
2262 #undef SIGN_EXTEND_CHAR
2263 #if __STDC__
2264 # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
2265 #else
2266
2267 # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
2268 #endif
2269 #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
2270
2271 static char *tokenbuf = NULL;
2272 static int tokidx, toksiz = 0;
2273
2274 #define LEAVE_BS 1
2275
2276 static VALUE (*lex_gets)();
2277 static VALUE lex_input;
2278 static VALUE lex_lastline;
2279 static char *lex_pbeg;
2280 static char *lex_p;
2281 static char *lex_pend;
2282
2283 static int
2284 yyerror(msg)
2285 char *msg;
2286 {
2287 char *p, *pe, *buf;
2288 int len, i;
2289
2290 rb_compile_error("%s", msg);
2291 p = lex_p;
2292 while (lex_pbeg <= p) {
2293 if (*p == '\n') break;
2294 p--;
2295 }
2296 p++;
2297
2298 pe = lex_p;
2299 while (pe < lex_pend) {
2300 if (*pe == '\n') break;
2301 pe++;
2302 }
2303
2304 len = pe - p;
2305 if (len > 4) {
2306 buf = ALLOCA_N(char, len+2);
2307 MEMCPY(buf, p, char, len);
2308 buf[len] = '\0';
2309 rb_compile_error_append("%s", buf);
2310
2311 i = lex_p - p;
2312 p = buf; pe = p + len;
2313
2314 while (p < pe) {
2315 if (*p != '\t') *p = ' ';
2316 p++;
2317 }
2318 buf[i] = '^';
2319 buf[i+1] = '\0';
2320 rb_compile_error_append("%s", buf);
2321 }
2322
2323 return 0;
2324 }
2325
2326 static int heredoc_end;
2327 static int command_start = Qtrue;
2328
2329 int ruby_in_compile = 0;
2330 int ruby__end__seen;
2331
2332 static VALUE ruby_debug_lines;
2333
2334 static NODE*
2335 yycompile(f, line)
2336 char *f;
2337 int line;
2338 {
2339 int n;
2340 NODE *node = 0;
2341 struct RVarmap *vp, *vars = ruby_dyna_vars;
2342
2343 if (!compile_for_eval && rb_safe_level() == 0 &&
2344 rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
2345 VALUE hash, fname;
2346
2347 hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
2348 if (TYPE(hash) == T_HASH) {
2349 fname = rb_str_new2(f);
2350 ruby_debug_lines = rb_hash_aref(hash, fname);
2351 if (NIL_P(ruby_debug_lines)) {
2352 ruby_debug_lines = rb_ary_new();
2353 rb_hash_aset(hash, fname, ruby_debug_lines);
2354 }
2355 }
2356 if (line > 1) {
2357 VALUE str = rb_str_new(0,0);
2358 while (line > 1) {
2359 rb_ary_push(ruby_debug_lines, str);
2360 line--;
2361 }
2362 }
2363 }
2364
2365 ruby__end__seen = 0;
2366 ruby_eval_tree = 0;
2367 heredoc_end = 0;
2368 lex_strterm = 0;
2369 lex_strnest = 0;
2370 quoted_term = -1;
2371 ruby_current_node = 0;
2372 ruby_sourcefile = rb_source_filename(f);
2373 ruby_in_compile = 1;
2374 n = yyparse();
2375 ruby_debug_lines = 0;
2376 compile_for_eval = 0;
2377 ruby_in_compile = 0;
2378 cond_stack = 0;
2379 cmdarg_stack = 0;
2380 command_start = 1;
2381 class_nest = 0;
2382 in_single = 0;
2383 in_def = 0;
2384 cur_mid = 0;
2385
2386 vp = ruby_dyna_vars;
2387 ruby_dyna_vars = vars;
2388 lex_strterm = 0;
2389 while (vp && vp != vars) {
2390 struct RVarmap *tmp = vp;
2391 vp = vp->next;
2392 rb_gc_force_recycle((VALUE)tmp);
2393 }
2394 if (n == 0) node = ruby_eval_tree;
2395 return node;
2396 }
2397
2398 static int lex_gets_ptr;
2399
2400 static VALUE
2401 lex_get_str(s)
2402 VALUE s;
2403 {
2404 char *beg, *end, *pend;
2405
2406 beg = RSTRING(s)->ptr;
2407 if (lex_gets_ptr) {
2408 if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
2409 beg += lex_gets_ptr;
2410 }
2411 pend = RSTRING(s)->ptr + RSTRING(s)->len;
2412 end = beg;
2413 while (end < pend) {
2414 if (*end++ == '\n') break;
2415 }
2416 lex_gets_ptr = end - RSTRING(s)->ptr;
2417 return rb_str_new(beg, end - beg);
2418 }
2419
2420 static VALUE
2421 lex_getline()
2422 {
2423 VALUE line = (*lex_gets)(lex_input);
2424 if (ruby_debug_lines && !NIL_P(line)) {
2425 rb_ary_push(ruby_debug_lines, line);
2426 }
2427 return line;
2428 }
2429
2430 NODE*
2431 rb_compile_string(f, s, line)
2432 const char *f;
2433 VALUE s;
2434 int line;
2435 {
2436 lex_gets = lex_get_str;
2437 lex_gets_ptr = 0;
2438 lex_input = s;
2439 lex_pbeg = lex_p = lex_pend = 0;
2440 ruby_sourceline = line - 1;
2441 compile_for_eval = ruby_in_eval;
2442
2443 return yycompile(f, line);
2444 }
2445
2446 NODE*
2447 rb_compile_cstr(f, s, len, line)
2448 const char *f, *s;
2449 int len, line;
2450 {
2451 return rb_compile_string(f, rb_str_new(s, len), line);
2452 }
2453
2454 NODE*
2455 rb_compile_file(f, file, start)
2456 const char *f;
2457 VALUE file;
2458 int start;
2459 {
2460 lex_gets = rb_io_gets;
2461 lex_input = file;
2462 lex_pbeg = lex_p = lex_pend = 0;
2463 ruby_sourceline = start - 1;
2464
2465 return yycompile(f, start);
2466 }
2467
2468 static inline int
2469 nextc()
2470 {
2471 int c;
2472
2473 if (lex_p == lex_pend) {
2474 if (lex_input) {
2475 VALUE v = lex_getline();
2476
2477 if (NIL_P(v)) return -1;
2478 if (heredoc_end > 0) {
2479 ruby_sourceline = heredoc_end;
2480 heredoc_end = 0;
2481 }
2482 ruby_sourceline++;
2483 lex_pbeg = lex_p = RSTRING(v)->ptr;
2484 lex_pend = lex_p + RSTRING(v)->len;
2485 lex_lastline = v;
2486 }
2487 else {
2488 lex_lastline = 0;
2489 return -1;
2490 }
2491 }
2492 c = (unsigned char)*lex_p++;
2493 if (c == '\r' && lex_p <= lex_pend && *lex_p == '\n') {
2494 lex_p++;
2495 c = '\n';
2496 }
2497
2498 return c;
2499 }
2500
2501 static void
2502 pushback(c)
2503 int c;
2504 {
2505 if (c == -1) return;
2506 lex_p--;
2507 }
2508
2509 #define peek(c) (lex_p != lex_pend && (c) == *lex_p)
2510
2511 #define tokfix() (tokenbuf[tokidx]='\0')
2512 #define tok() tokenbuf
2513 #define toklen() tokidx
2514 #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
2515
2516 static char*
2517 newtok()
2518 {
2519 tokidx = 0;
2520 if (!tokenbuf) {
2521 toksiz = 60;
2522 tokenbuf = ALLOC_N(char, 60);
2523 }
2524 if (toksiz > 4096) {
2525 toksiz = 60;
2526 REALLOC_N(tokenbuf, char, 60);
2527 }
2528 return tokenbuf;
2529 }
2530
2531 static void
2532 tokadd(c)
2533 char c;
2534 {
2535 tokenbuf[tokidx++] = c;
2536 if (tokidx >= toksiz) {
2537 toksiz *= 2;
2538 REALLOC_N(tokenbuf, char, toksiz);
2539 }
2540 }
2541
2542 static int
2543 read_escape()
2544 {
2545 int c;
2546
2547 switch (c = nextc()) {
2548 case '\\':
2549 return c;
2550
2551 case 'n':
2552 return '\n';
2553
2554 case 't':
2555 return '\t';
2556
2557 case 'r':
2558 return '\r';
2559
2560 case 'f':
2561 return '\f';
2562
2563 case 'v':
2564 return '\13';
2565
2566 case 'a':
2567 return '\007';
2568
2569 case 'e':
2570 return 033;
2571
2572 case '0': case '1': case '2': case '3':
2573 case '4': case '5': case '6': case '7':
2574 {
2575 int numlen;
2576
2577 pushback(c);
2578 c = scan_oct(lex_p, 3, &numlen);
2579 lex_p += numlen;
2580 }
2581 return c;
2582
2583 case 'x':
2584 {
2585 int numlen;
2586
2587 c = scan_hex(lex_p, 2, &numlen);
2588 if (numlen == 0) {
2589 yyerror("Invalid escape character syntax");
2590 return 0;
2591 }
2592 lex_p += numlen;
2593 }
2594 return c;
2595
2596 case 'b':
2597 return '\010';
2598
2599 case 's':
2600 return ' ';
2601
2602 case 'M':
2603 if ((c = nextc()) != '-') {
2604 yyerror("Invalid escape character syntax");
2605 pushback(c);
2606 return '\0';
2607 }
2608 if ((c = nextc()) == '\\') {
2609 return read_escape() | 0x80;
2610 }
2611 else if (c == -1) goto eof;
2612 else {
2613 return ((c & 0xff) | 0x80);
2614 }
2615
2616 case 'C':
2617 if ((c = nextc()) != '-') {
2618 yyerror("Invalid escape character syntax");
2619 pushback(c);
2620 return '\0';
2621 }
2622 case 'c':
2623 if ((c = nextc())== '\\') {
2624 c = read_escape();
2625 }
2626 else if (c == '?')
2627 return 0177;
2628 else if (c == -1) goto eof;
2629 return c & 0x9f;
2630
2631 eof:
2632 case -1:
2633 yyerror("Invalid escape character syntax");
2634 return '\0';
2635
2636 default:
2637 return c;
2638 }
2639 }
2640
2641 static int
2642 tokadd_escape(term)
2643 int term;
2644 {
2645 int c;
2646
2647 switch (c = nextc()) {
2648 case '\n':
2649 return 0;
2650
2651 case '0': case '1': case '2': case '3':
2652 case '4': case '5': case '6': case '7':
2653 {
2654 int i;
2655
2656 tokadd('\\');
2657 tokadd(c);
2658 for (i=0; i<2; i++) {
2659 c = nextc();
2660 if (c == -1) goto eof;
2661 if (c < '0' || '7' < c) {
2662 pushback(c);
2663 break;
2664 }
2665 tokadd(c);
2666 }
2667 }
2668 return 0;
2669
2670 case 'x':
2671 {
2672 int numlen;
2673
2674 tokadd('\\');
2675 tokadd(c);
2676 scan_hex(lex_p, 2, &numlen);
2677 if (numlen == 0) {
2678 yyerror("Invalid escape character syntax");
2679 return -1;
2680 }
2681 while (numlen--)
2682 tokadd(nextc());
2683 }
2684 return 0;
2685
2686 case 'M':
2687 if ((c = nextc()) != '-') {
2688 yyerror("Invalid escape character syntax");
2689 pushback(c);
2690 return 0;
2691 }
2692 tokadd('\\'); tokadd('M'); tokadd('-');
2693 goto escaped;
2694
2695 case 'C':
2696 if ((c = nextc()) != '-') {
2697 yyerror("Invalid escape character syntax");
2698 pushback(c);
2699 return 0;
2700 }
2701 tokadd('\\'); tokadd('C'); tokadd('-');
2702 goto escaped;
2703
2704 case 'c':
2705 tokadd('\\'); tokadd('c');
2706 escaped:
2707 if ((c = nextc()) == '\\') {
2708 return tokadd_escape(term);
2709 }
2710 else if (c == -1) goto eof;
2711 tokadd(c);
2712 return 0;
2713
2714 eof:
2715 case -1:
2716 yyerror("Invalid escape character syntax");
2717 return -1;
2718
2719 default:
2720 if (c != '\\' || c != term)
2721 tokadd('\\');
2722 tokadd(c);
2723 }
2724 return 0;
2725 }
2726
2727 static int
2728 regx_options()
2729 {
2730 char kcode = 0;
2731 int options = 0;
2732 int c;
2733
2734 newtok();
2735 while (c = nextc(), ISALPHA(c)) {
2736 switch (c) {
2737 case 'i':
2738 options |= RE_OPTION_IGNORECASE;
2739 break;
2740 case 'x':
2741 options |= RE_OPTION_EXTENDED;
2742 break;
2743 case 'm':
2744 options |= RE_OPTION_MULTILINE;
2745 break;
2746 case 'o':
2747 options |= RE_OPTION_ONCE;
2748 break;
2749 case 'n':
2750 kcode = 16;
2751 break;
2752 case 'e':
2753 kcode = 32;
2754 break;
2755 case 's':
2756 kcode = 48;
2757 break;
2758 case 'u':
2759 kcode = 64;
2760 break;
2761 default:
2762 tokadd(c);
2763 break;
2764 }
2765 }
2766 pushback(c);
2767 if (toklen()) {
2768 tokfix();
2769 rb_compile_error("unknown regexp option%s - %s",
2770 toklen() > 1 ? "s" : "", tok());
2771 }
2772 return options | kcode;
2773 }
2774
2775 #define STR_FUNC_ESCAPE 0x01
2776 #define STR_FUNC_EXPAND 0x02
2777 #define STR_FUNC_REGEXP 0x04
2778 #define STR_FUNC_QWORDS 0x08
2779 #define STR_FUNC_INDENT 0x20
2780
2781 enum string_type {
2782 str_squote = (0),
2783 str_dquote = (STR_FUNC_EXPAND),
2784 str_xquote = (STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
2785 str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
2786 str_sword = (STR_FUNC_QWORDS),
2787 str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
2788 };
2789
2790 static int
2791 tokadd_string(func, term, paren)
2792 int func, term, paren;
2793 {
2794 int c;
2795
2796 while ((c = nextc()) != -1) {
2797 if (paren && c == paren) {
2798 lex_strnest++;
2799 }
2800 else if (c == term) {
2801 if (!lex_strnest) {
2802 pushback(c);
2803 break;
2804 }
2805 --lex_strnest;
2806 }
2807 else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
2808 int c2 = *lex_p;
2809 if (c2 == '$' || c2 == '@' || c2 == '{') {
2810 pushback(c);
2811 break;
2812 }
2813 }
2814 else if (c == '\\') {
2815 c = nextc();
2816 if (QUOTED_TERM_P(c)) {
2817 pushback(c);
2818 return c;
2819 }
2820 switch (c) {
2821 case '\n':
2822 continue;
2823
2824 case '\\':
2825 if (func & STR_FUNC_ESCAPE) tokadd(c);
2826 break;
2827
2828 default:
2829 if (func & STR_FUNC_REGEXP) {
2830 pushback(c);
2831 if (tokadd_escape(term) < 0)
2832 return -1;
2833 continue;
2834 }
2835 else if (func & STR_FUNC_EXPAND) {
2836 pushback(c);
2837 if (func & STR_FUNC_ESCAPE) tokadd('\\');
2838 c = read_escape();
2839 }
2840 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2841
2842 }
2843 else if (c != term && !(paren && c == paren)) {
2844 tokadd('\\');
2845 }
2846 }
2847 }
2848 else if (ismbchar(c)) {
2849 int i, len = mbclen(c)-1;
2850
2851 for (i = 0; i < len; i++) {
2852 tokadd(c);
2853 c = nextc();
2854 }
2855 }
2856 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2857 pushback(c);
2858 break;
2859 }
2860 tokadd(c);
2861 }
2862 return c;
2863 }
2864
2865 #define NEW_STRTERM(func, term, paren) \
2866 rb_node_newnode(NODE_STRTERM, (func), (term), (paren))
2867
2868 static int
2869 parse_string(quote)
2870 NODE *quote;
2871 {
2872 int func = quote->nd_func;
2873 int term = quote->nd_term;
2874 int paren = quote->nd_paren;
2875 int c, space = 0;
2876
2877 if (func == -1) return tSTRING_END;
2878 c = nextc();
2879 if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
2880 do {c = nextc();} while (ISSPACE(c));
2881 space = 1;
2882 }
2883 if (c == term) {
2884 if (!lex_strnest) {
2885 eos:
2886 if (func & STR_FUNC_QWORDS) {
2887 quote->nd_func = -1;
2888 return ' ';
2889 }
2890 if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
2891 yylval.num = regx_options();
2892 return tREGEXP_END;
2893 }
2894 }
2895 if (c == '\\' && WHEN_QUOTED_TERM(peek(quoted_term_char))) {
2896 if ((c = nextc()) == term) goto eos;
2897 }
2898 if (space) {
2899 pushback(c);
2900 return ' ';
2901 }
2902 newtok();
2903 if ((func & STR_FUNC_EXPAND) && c == '#') {
2904 switch (c = nextc()) {
2905 case '$':
2906 case '@':
2907 pushback(c);
2908 return tSTRING_DVAR;
2909 case '{':
2910 return tSTRING_DBEG;
2911 }
2912 tokadd('#');
2913 }
2914 pushback(c);
2915 if (tokadd_string(func, term, paren) == -1) {
2916 ruby_sourceline = nd_line(quote);
2917 rb_compile_error("unterminated string meets end of file");
2918 return tSTRING_END;
2919 }
2920
2921 tokfix();
2922 yylval.node = NEW_STR(rb_str_new(tok(), toklen()));
2923 return tSTRING_CONTENT;
2924 }
2925
2926 static int
2927 heredoc_identifier()
2928 {
2929 int c = nextc(), term, func = 0, len;
2930
2931 if (c == '-') {
2932 c = nextc();
2933 if (ISSPACE(c)) {
2934 pushback(c);
2935 pushback('-');
2936 return 0;
2937 }
2938 func = STR_FUNC_INDENT;
2939 }
2940 else if (ISSPACE(c)) {
2941 not_heredoc:
2942 pushback(c);
2943 return 0;
2944 }
2945 switch (c) {
2946 case '\'':
2947 func |= str_squote; goto quoted;
2948 case '"':
2949 func |= str_dquote; goto quoted;
2950 case '`':
2951 func |= str_xquote;
2952 quoted:
2953 newtok();
2954 tokadd(func);
2955 term = c;
2956 while ((c = nextc()) != -1 && c != term) {
2957 len = mbclen(c);
2958 do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
2959 }
2960 if (c == -1) {
2961 rb_compile_error("unterminated here document identifier");
2962 return 0;
2963 }
2964 break;
2965
2966 default:
2967 if (!is_identchar(c)) goto not_heredoc;
2968 newtok();
2969 term = '"';
2970 tokadd(func |= str_dquote);
2971 do {
2972 len = mbclen(c);
2973 do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
2974 } while ((c = nextc()) != -1 && is_identchar(c));
2975 pushback(c);
2976 break;
2977 }
2978
2979 tokfix();
2980 len = lex_p - lex_pbeg;
2981 lex_p = lex_pend;
2982 lex_strterm = rb_node_newnode(NODE_HEREDOC,
2983 rb_str_new(tok(), toklen()),
2984 len,
2985 lex_lastline);
2986 return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
2987 }
2988
2989 static void
2990 heredoc_restore(here)
2991 NODE *here;
2992 {
2993 VALUE line = here->nd_orig;
2994 lex_lastline = line;
2995 lex_pbeg = RSTRING(line)->ptr;
2996 lex_pend = lex_pbeg + RSTRING(line)->len;
2997 lex_p = lex_pbeg + here->nd_nth;
2998 heredoc_end = ruby_sourceline;
2999 ruby_sourceline = nd_line(here);
3000 rb_gc_force_recycle(here->nd_lit);
3001 rb_gc_force_recycle((VALUE)here);
3002 }
3003
3004 static int
3005 whole_match_p(eos, len, indent)
3006 char *eos;
3007 int len, indent;
3008 {
3009 char *p = lex_pbeg;
3010
3011 if (indent) {
3012 while (*p && ISSPACE(*p)) p++;
3013 }
3014 if (strncmp(eos, p, len) == 0) {
3015 if (p[len] == '\n' || p[len] == '\r') return Qtrue;
3016 if (p + len == lex_pend) return Qtrue;
3017 }
3018 return Qfalse;
3019 }
3020
3021 static int
3022 here_document(here)
3023 NODE *here;
3024 {
3025 int c, func, indent = 0;
3026 char *eos;
3027 long len;
3028 VALUE str = 0, line;
3029
3030 eos = RSTRING(here->nd_lit)->ptr;
3031 len = RSTRING(here->nd_lit)->len - 1;
3032 indent = (func = *eos++) & STR_FUNC_INDENT;
3033
3034 if ((c = nextc()) == -1) {
3035 error:
3036 rb_compile_error("can't find string \"%s\" anywhere before EOF", eos);
3037 heredoc_restore(lex_strterm);
3038 lex_strterm = 0;
3039 return 0;
3040 }
3041 if (lex_p - 1 == lex_pbeg && whole_match_p(eos, len, indent)) {
3042 heredoc_restore(lex_strterm);
3043 return tSTRING_END;
3044 }
3045
3046 if (!(func & STR_FUNC_EXPAND)) {
3047 do {
3048 line = lex_lastline;
3049 if (str)
3050 rb_str_cat(str, RSTRING(line)->ptr, RSTRING(line)->len);
3051 else
3052 str = rb_str_new(RSTRING(line)->ptr, RSTRING(line)->len);
3053 lex_p = lex_pend;
3054 if (nextc() == -1) {
3055 if (str) rb_gc_force_recycle(str);
3056 goto error;
3057 }
3058 } while (!whole_match_p(eos, len, indent));
3059 }
3060 else {
3061 newtok();
3062 if (c == '#') {
3063 switch (c = nextc()) {
3064 case '$':
3065 case '@':
3066 pushback(c);
3067 return tSTRING_DVAR;
3068 case '{':
3069 return tSTRING_DBEG;
3070 }
3071 tokadd('#');
3072 }
3073 do {
3074 pushback(c);
3075 if ((c = tokadd_string(func, '\n', 0)) == -1) goto error;
3076 if (c != '\n') {
3077 yylval.node = NEW_STR(rb_str_new(tok(), toklen()));
3078 return tSTRING_CONTENT;
3079 }
3080 tokadd(nextc());
3081 if ((c = nextc()) == -1) goto error;
3082 } while (!whole_match_p(eos, len, indent));
3083 str = rb_str_new(tok(), toklen());
3084 }
3085 heredoc_restore(lex_strterm);
3086 lex_strterm = NEW_STRTERM(-1, 0, 0);
3087 yylval.node = NEW_STR(str);
3088 return tSTRING_CONTENT;
3089 }
3090
3091 #include "lex.c"
3092
3093 static void
3094 arg_ambiguous()
3095 {
3096 rb_warning("ambiguous first argument; make sure");
3097 }
3098
3099 #if !defined(strtod) && !defined(HAVE_STDLIB_H)
3100 double strtod ();
3101 #endif
3102
3103 #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
3104
3105 static int
3106 yylex()
3107 {
3108 static ID last_id = 0;
3109 register int c;
3110 int space_seen = 0;
3111 int cmd_state;
3112
3113 if (lex_strterm) {
3114 int token;
3115 if (nd_type(lex_strterm) == NODE_HEREDOC) {
3116 token = here_document(lex_strterm);
3117 if (token == tSTRING_END) {
3118 lex_strterm = 0;
3119 lex_state = EXPR_END;
3120 }
3121 }
3122 else {
3123 token = parse_string(lex_strterm);
3124 if (token == tSTRING_END || token == tREGEXP_END) {
3125 rb_gc_force_recycle((VALUE)lex_strterm);
3126 lex_strterm = 0;
3127 lex_state = EXPR_END;
3128 }
3129 }
3130 return token;
3131 }
3132 cmd_state = command_start;
3133 command_start = Qfalse;
3134 retry:
3135 switch (c = nextc()) {
3136 case '\0':
3137 case '\004':
3138 case '\032':
3139 case -1:
3140 return 0;
3141
3142
3143 case ' ': case '\t': case '\f': case '\r':
3144 case '\13':
3145 space_seen++;
3146 goto retry;
3147
3148 case '#':
3149 while ((c = nextc()) != '\n') {
3150 if (c == -1)
3151 return 0;
3152 }
3153
3154 case '\n':
3155 switch (lex_state) {
3156 case EXPR_BEG:
3157 case EXPR_FNAME:
3158 case EXPR_DOT:
3159 case EXPR_CLASS:
3160 goto retry;
3161 default:
3162 break;
3163 }
3164 command_start = Qtrue;
3165 lex_state = EXPR_BEG;
3166 return '\n';
3167
3168 case '*':
3169 if ((c = nextc()) == '*') {
3170 if ((c = nextc()) == '=') {
3171 yylval.id = tPOW;
3172 lex_state = EXPR_BEG;
3173 return tOP_ASGN;
3174 }
3175 pushback(c);
3176 c = tPOW;
3177 }
3178 else {
3179 if (c == '=') {
3180 yylval.id = '*';
3181 lex_state = EXPR_BEG;
3182 return tOP_ASGN;
3183 }
3184 pushback(c);
3185 if (IS_ARG() && space_seen && !ISSPACE(c)){
3186 rb_warning("`*' interpreted as argument prefix");
3187 c = tSTAR;
3188 }
3189 else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3190 c = tSTAR;
3191 }
3192 else {
3193 c = '*';
3194 }
3195 }
3196 switch (lex_state) {
3197 case EXPR_FNAME: case EXPR_DOT:
3198 lex_state = EXPR_ARG; break;
3199 default:
3200 lex_state = EXPR_BEG; break;
3201 }
3202 return c;
3203
3204 case '!':
3205 lex_state = EXPR_BEG;
3206 if ((c = nextc()) == '=') {
3207 return tNEQ;
3208 }
3209 if (c == '~') {
3210 return tNMATCH;
3211 }
3212 pushback(c);
3213 return '!';
3214
3215 case '=':
3216 if (lex_p == lex_pbeg + 1) {
3217
3218 if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
3219 for (;;) {
3220 lex_p = lex_pend;
3221 c = nextc();
3222 if (c == -1) {
3223 rb_compile_error("embedded document meets end of file");
3224 return 0;
3225 }
3226 if (c != '=') continue;
3227 if (strncmp(lex_p, "end", 3) == 0 &&
3228 (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
3229 break;
3230 }
3231 }
3232 lex_p = lex_pend;
3233 goto retry;
3234 }
3235 }
3236
3237 switch (lex_state) {
3238 case EXPR_FNAME: case EXPR_DOT:
3239 lex_state = EXPR_ARG; break;
3240 default:
3241 lex_state = EXPR_BEG; break;
3242 }
3243 if ((c = nextc()) == '=') {
3244 if ((c = nextc()) == '=') {
3245 return tEQQ;
3246 }
3247 pushback(c);
3248 return tEQ;
3249 }
3250 if (c == '~') {
3251 return tMATCH;
3252 }
3253 else if (c == '>') {
3254 return tASSOC;
3255 }
3256 pushback(c);
3257 return '=';
3258
3259 case '<':
3260 c = nextc();
3261 if (c == '<' &&
3262 lex_state != EXPR_END &&
3263 lex_state != EXPR_DOT &&
3264 lex_state != EXPR_ENDARG &&
3265 lex_state != EXPR_CLASS &&
3266 (!IS_ARG() || space_seen)) {
3267 int token = heredoc_identifier();
3268 if (token) return token;
3269 }
3270 switch (lex_state) {
3271 case EXPR_FNAME: case EXPR_DOT:
3272 lex_state = EXPR_ARG; break;
3273 default:
3274 lex_state = EXPR_BEG; break;
3275 }
3276 if (c == '=') {
3277 if ((c = nextc()) == '>') {
3278 return tCMP;
3279 }
3280 pushback(c);
3281 return tLEQ;
3282 }
3283 if (c == '<') {
3284 if ((c = nextc()) == '=') {
3285 yylval.id = tLSHFT;
3286 lex_state = EXPR_BEG;
3287 return tOP_ASGN;
3288 }
3289 pushback(c);
3290 return tLSHFT;
3291 }
3292 pushback(c);
3293 return '<';
3294
3295 case '>':
3296 switch (lex_state) {
3297 case EXPR_FNAME: case EXPR_DOT:
3298 lex_state = EXPR_ARG; break;
3299 default:
3300 lex_state = EXPR_BEG; break;
3301 }
3302 if ((c = nextc()) == '=') {
3303 return tGEQ;
3304 }
3305 if (c == '>') {
3306 if ((c = nextc()) == '=') {
3307 yylval.id = tRSHFT;
3308 lex_state = EXPR_BEG;
3309 return tOP_ASGN;
3310 }
3311 pushback(c);
3312 return tRSHFT;
3313 }
3314 pushback(c);
3315 return '>';
3316
3317 case '"':
3318 lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
3319 return tSTRING_BEG;
3320
3321 case '`':
3322 if (lex_state == EXPR_FNAME) {
3323 lex_state = EXPR_END;
3324 return c;
3325 }
3326 if (lex_state == EXPR_DOT) {
3327 if (cmd_state)
3328 lex_state = EXPR_CMDARG;
3329 else
3330 lex_state = EXPR_ARG;
3331 return c;
3332 }
3333 lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
3334 return tXSTRING_BEG;
3335
3336 case '\'':
3337 lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
3338 return tSTRING_BEG;
3339
3340 case '?':
3341 if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
3342 lex_state = EXPR_BEG;
3343 return '?';
3344 }
3345 c = nextc();
3346 if (c == -1) {
3347 rb_compile_error("incomplete character syntax");
3348 return 0;
3349 }
3350 if (ISSPACE(c)){
3351 if (!IS_ARG()){
3352 int c2 = 0;
3353 switch (c) {
3354 case ' ':
3355 c2 = 's';
3356 break;
3357 case '\n':
3358 c2 = 'n';
3359 break;
3360 case '\t':
3361 c2 = 't';
3362 break;
3363 case '\v':
3364 c2 = 'v';
3365 break;
3366 case '\r':
3367 c2 = 'r';
3368 break;
3369 case '\f':
3370 c2 = 'f';
3371 break;
3372 }
3373 if (c2) {
3374 rb_warn("invalid character syntax; use ?\\%c", c2);
3375 }
3376 }
3377 ternary:
3378 pushback(c);
3379 lex_state = EXPR_BEG;
3380 return '?';
3381 }
3382 else if (ismbchar(c)) {
3383 rb_warn("multibyte character literal not supported yet; use ?\\%.3o", c);
3384 goto ternary;
3385 }
3386 else if ((ISALNUM(c) || c == '_') && lex_p < lex_pend && is_identchar(*lex_p)) {
3387 goto ternary;
3388 }
3389 else if (c == '\\') {
3390 c = read_escape();
3391 }
3392 c &= 0xff;
3393 lex_state = EXPR_END;
3394 yylval.node = NEW_LIT(INT2FIX(c));
3395 return tINTEGER;
3396
3397 case '&':
3398 if ((c = nextc()) == '&') {
3399 lex_state = EXPR_BEG;
3400 if ((c = nextc()) == '=') {
3401 yylval.id = tANDOP;
3402 lex_state = EXPR_BEG;
3403 return tOP_ASGN;
3404 }
3405 pushback(c);
3406 return tANDOP;
3407 }
3408 else if (c == '=') {
3409 yylval.id = '&';
3410 lex_state = EXPR_BEG;
3411 return tOP_ASGN;
3412 }
3413 pushback(c);
3414 if (IS_ARG() && space_seen && !ISSPACE(c)){
3415 rb_warning("`&' interpreted as argument prefix");
3416 c = tAMPER;
3417 }
3418 else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3419 c = tAMPER;
3420 }
3421 else {
3422 c = '&';
3423 }
3424 switch (lex_state) {
3425 case EXPR_FNAME: case EXPR_DOT:
3426 lex_state = EXPR_ARG; break;
3427 default:
3428 lex_state = EXPR_BEG;
3429 }
3430 return c;
3431
3432 case '|':
3433 if ((c = nextc()) == '|') {
3434 lex_state = EXPR_BEG;
3435 if ((c = nextc()) == '=') {
3436 yylval.id = tOROP;
3437 lex_state = EXPR_BEG;
3438 return tOP_ASGN;
3439 }
3440 pushback(c);
3441 return tOROP;
3442 }
3443 if (c == '=') {
3444 yylval.id = '|';
3445 lex_state = EXPR_BEG;
3446 return tOP_ASGN;
3447 }
3448 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3449 lex_state = EXPR_ARG;
3450 }
3451 else {
3452 lex_state = EXPR_BEG;
3453 }
3454 pushback(c);
3455 return '|';
3456
3457 case '+':
3458 c = nextc();
3459 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3460 lex_state = EXPR_ARG;
3461 if (c == '@') {
3462 return tUPLUS;
3463 }
3464 pushback(c);
3465 return '+';
3466 }
3467 if (c == '=') {
3468 yylval.id = '+';
3469 lex_state = EXPR_BEG;
3470 return tOP_ASGN;
3471 }
3472 if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
3473 (IS_ARG() && space_seen && !ISSPACE(c))) {
3474 if (IS_ARG()) arg_ambiguous();
3475 lex_state = EXPR_BEG;
3476 pushback(c);
3477 if (ISDIGIT(c)) {
3478 c = '+';
3479 goto start_num;
3480 }
3481 return tUPLUS;
3482 }
3483 lex_state = EXPR_BEG;
3484 pushback(c);
3485 return '+';
3486
3487 case '-':
3488 c = nextc();
3489 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3490 lex_state = EXPR_ARG;
3491 if (c == '@') {
3492 return tUMINUS;
3493 }
3494 pushback(c);
3495 return '-';
3496 }
3497 if (c == '=') {
3498 yylval.id = '-';
3499 lex_state = EXPR_BEG;
3500 return tOP_ASGN;
3501 }
3502 if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
3503 (IS_ARG() && space_seen && !ISSPACE(c))) {
3504 if (IS_ARG()) arg_ambiguous();
3505 lex_state = EXPR_BEG;
3506 pushback(c);
3507 if (ISDIGIT(c)) {
3508 c = '-';
3509 goto start_num;
3510 }
3511 return tUMINUS;
3512 }
3513 lex_state = EXPR_BEG;
3514 pushback(c);
3515 return '-';
3516
3517 case '.':
3518 lex_state = EXPR_BEG;
3519 if ((c = nextc()) == '.') {
3520 if ((c = nextc()) == '.') {
3521 return tDOT3;
3522 }
3523 pushback(c);
3524 return tDOT2;
3525 }
3526 pushback(c);
3527 if (!ISDIGIT(c)) {
3528 lex_state = EXPR_DOT;
3529 return '.';
3530 }
3531 c = '.';
3532
3533
3534 start_num:
3535 case '0': case '1': case '2': case '3': case '4':
3536 case '5': case '6': case '7': case '8': case '9':
3537 {
3538 int is_float, seen_point, seen_e, nondigit;
3539
3540 is_float = seen_point = seen_e = nondigit = 0;
3541 lex_state = EXPR_END;
3542 newtok();
3543 if (c == '-' || c == '+') {
3544 tokadd(c);
3545 c = nextc();
3546 }
3547 if (c == '0') {
3548 int start = toklen();
3549 c = nextc();
3550 if (c == 'x' || c == 'X') {
3551
3552 c = nextc();
3553 if (ISXDIGIT(c)) {
3554 do {
3555 if (c == '_') {
3556 if (nondigit) break;
3557 nondigit = c;
3558 continue;
3559 }
3560 if (!ISXDIGIT(c)) break;
3561 nondigit = 0;
3562 tokadd(c);
3563 } while (c = nextc());
3564 }
3565 pushback(c);
3566 tokfix();
3567 if (toklen() == start) {
3568 yyerror("numeric literal without digits");
3569 }
3570 else if (nondigit) goto trailing_uc;
3571 yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 16, Qfalse));
3572 return tINTEGER;
3573 }
3574 if (c == 'b' || c == 'B') {
3575
3576 c = nextc();
3577 if (c == '0' || c == '1') {
3578 do {
3579 if (c == '_') {
3580 if (nondigit) break;
3581 nondigit = c;
3582 continue;
3583 }
3584 if (c != '0' && c != '1') break;
3585 nondigit = 0;
3586 tokadd(c);
3587 } while (c = nextc());
3588 }
3589 pushback(c);
3590 tokfix();
3591 if (toklen() == start) {
3592 yyerror("numeric literal without digits");
3593 }
3594 else if (nondigit) goto trailing_uc;
3595 yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 2, Qfalse));
3596 return tINTEGER;
3597 }
3598 if (c == 'd' || c == 'D') {
3599
3600 c = nextc();
3601 if (ISDIGIT(c)) {
3602 do {
3603 if (c == '_') {
3604 if (nondigit) break;
3605 nondigit = c;
3606 continue;
3607 }
3608 if (!ISDIGIT(c)) break;
3609 nondigit = 0;
3610 tokadd(c);
3611 } while (c = nextc());
3612 }
3613 pushback(c);
3614 tokfix();
3615 if (toklen() == start) {
3616 yyerror("numeric literal without digits");
3617 }
3618 else if (nondigit) goto trailing_uc;
3619 yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
3620 return tINTEGER;
3621 }
3622 if (c == '_') {
3623
3624 goto octal_number;
3625 }
3626 if (c == 'o' || c == 'O') {
3627
3628 c = nextc();
3629 if (c == '_') {
3630 yyerror("numeric literal without digits");
3631 }
3632 }
3633 if (c >= '0' && c <= '7') {
3634
3635 octal_number:
3636 do {
3637 if (c == '_') {
3638 if (nondigit) break;
3639 nondigit = c;
3640 continue;
3641 }
3642 if (c < '0' || c > '7') break;
3643 nondigit = 0;
3644 tokadd(c);
3645 } while (c = nextc());
3646 if (toklen() > start) {
3647 pushback(c);
3648 tokfix();
3649 if (nondigit) goto trailing_uc;
3650 yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 8, Qfalse));
3651 return tINTEGER;
3652 }
3653 if (nondigit) {
3654 pushback(c);
3655 goto trailing_uc;
3656 }
3657 }
3658 if (c > '7' && c <= '9') {
3659 yyerror("Illegal octal digit");
3660 }
3661 else if (c == '.' || c == 'e' || c == 'E') {
3662 tokadd('0');
3663 }
3664 else {
3665 pushback(c);
3666 yylval.node = NEW_LIT(INT2FIX(0));
3667 return tINTEGER;
3668 }
3669 }
3670
3671 for (;;) {
3672 switch (c) {
3673 case '0': case '1': case '2': case '3': case '4':
3674 case '5': case '6': case '7': case '8': case '9':
3675 nondigit = 0;
3676 tokadd(c);
3677 break;
3678
3679 case '.':
3680 if (nondigit) goto trailing_uc;
3681 if (seen_point || seen_e) {
3682 goto decode_num;
3683 }
3684 else {
3685 int c0 = nextc();
3686 if (!ISDIGIT(c0)) {
3687 pushback(c0);
3688 goto decode_num;
3689 }
3690 c = c0;
3691 }
3692 tokadd('.');
3693 tokadd(c);
3694 is_float++;
3695 seen_point++;
3696 nondigit = 0;
3697 break;
3698
3699 case 'e':
3700 case 'E':
3701 if (nondigit) {
3702 pushback(c);
3703 c = nondigit;
3704 goto decode_num;
3705 }
3706 if (seen_e) {
3707 goto decode_num;
3708 }
3709 tokadd(c);
3710 seen_e++;
3711 is_float++;
3712 nondigit = c;
3713 c = nextc();
3714 if (c != '-' && c != '+') continue;
3715 tokadd(c);
3716 nondigit = c;
3717 break;
3718
3719 case '_':
3720 if (nondigit) goto decode_num;
3721 nondigit = c;
3722 break;
3723
3724 default:
3725 goto decode_num;
3726 }
3727 c = nextc();
3728 }
3729
3730 decode_num:
3731 pushback(c);
3732 tokfix();
3733 if (nondigit) {
3734 char tmp[30];
3735 trailing_uc:
3736 sprintf(tmp, "trailing `%c' in number", nondigit);
3737 yyerror(tmp);
3738 }
3739 if (is_float) {
3740 double d = strtod(tok(), 0);
3741 if (errno == ERANGE) {
3742 rb_warn("Float %s out of range", tok());
3743 errno = 0;
3744 }
3745 yylval.node = NEW_LIT(rb_float_new(d));
3746 return tFLOAT;
3747 }
3748 yylval.node = NEW_LIT(rb_cstr_to_inum(tok(), 10, Qfalse));
3749 return tINTEGER;
3750 }
3751
3752 case ']':
3753 case '}':
3754 case ')':
3755 COND_LEXPOP();
3756 CMDARG_LEXPOP();
3757 lex_state = EXPR_END;
3758 return c;
3759
3760 case ':':
3761 c = nextc();
3762 if (c == ':') {
3763 if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
3764 (IS_ARG() && space_seen)) {
3765 lex_state = EXPR_BEG;
3766 return tCOLON3;
3767 }
3768 lex_state = EXPR_DOT;
3769 return tCOLON2;
3770 }
3771 pushback(c);
3772 if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || ISSPACE(c)) {
3773 lex_state = EXPR_BEG;
3774 return ':';
3775 }
3776 lex_state = EXPR_FNAME;
3777 return tSYMBEG;
3778
3779 case '/':
3780 if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3781 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
3782 return tREGEXP_BEG;
3783 }
3784 if ((c = nextc()) == '=') {
3785 yylval.id = '/';
3786 lex_state = EXPR_BEG;
3787 return tOP_ASGN;
3788 }
3789 pushback(c);
3790 if (IS_ARG() && space_seen) {
3791 if (!ISSPACE(c)) {
3792 arg_ambiguous();
3793 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
3794 return tREGEXP_BEG;
3795 }
3796 }
3797 switch (lex_state) {
3798 case EXPR_FNAME: case EXPR_DOT:
3799 lex_state = EXPR_ARG; break;
3800 default:
3801 lex_state = EXPR_BEG; break;
3802 }
3803 return '/';
3804
3805 case '^':
3806 if ((c = nextc()) == '=') {
3807 yylval.id = '^';
3808 lex_state = EXPR_BEG;
3809 return tOP_ASGN;
3810 }
3811 switch (lex_state) {
3812 case EXPR_FNAME: case EXPR_DOT:
3813 lex_state = EXPR_ARG; break;
3814 default:
3815 lex_state = EXPR_BEG; break;
3816 }
3817 pushback(c);
3818 return '^';
3819
3820 case ';':
3821 command_start = Qtrue;
3822 case ',':
3823 lex_state = EXPR_BEG;
3824 return c;
3825
3826 case '~':
3827 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3828 if ((c = nextc()) != '@') {
3829 pushback(c);
3830 }
3831 }
3832 switch (lex_state) {
3833 case EXPR_FNAME: case EXPR_DOT:
3834 lex_state = EXPR_ARG; break;
3835 default:
3836 lex_state = EXPR_BEG; break;
3837 }
3838 return '~';
3839
3840 case '(':
3841 command_start = Qtrue;
3842 if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3843 c = tLPAREN;
3844 }
3845 else if (space_seen) {
3846 if (lex_state == EXPR_CMDARG) {
3847 c = tLPAREN_ARG;
3848 }
3849 else if (lex_state == EXPR_ARG) {
3850 c = tLPAREN_ARG;
3851 yylval.id = last_id;
3852 }
3853 }
3854 COND_PUSH(0);
3855 CMDARG_PUSH(0);
3856 lex_state = EXPR_BEG;
3857 return c;
3858
3859 case '[':
3860 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3861 lex_state = EXPR_ARG;
3862 if ((c = nextc()) == ']') {
3863 if ((c = nextc()) == '=') {
3864 return tASET;
3865 }
3866 pushback(c);
3867 return tAREF;
3868 }
3869 pushback(c);
3870 return '[';
3871 }
3872 else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3873 c = tLBRACK;
3874 }
3875 else if (IS_ARG() && space_seen) {
3876 c = tLBRACK;
3877 }
3878 lex_state = EXPR_BEG;
3879 COND_PUSH(0);
3880 CMDARG_PUSH(0);
3881 return c;
3882
3883 case '{':
3884 if (IS_ARG() || lex_state == EXPR_END)
3885 c = '{';
3886 else if (lex_state == EXPR_ENDARG)
3887 c = tLBRACE_ARG;
3888 else
3889 c = tLBRACE;
3890 COND_PUSH(0);
3891 CMDARG_PUSH(0);
3892 lex_state = EXPR_BEG;
3893 return c;
3894
3895 case '\\':
3896 c = nextc();
3897 if (c == '\n') {
3898 space_seen = 1;
3899 goto retry;
3900 }
3901 pushback(c);
3902 if (QUOTED_TERM_P(c)) {
3903 if (!(quoted_term & (1 << CHAR_BIT))) {
3904 rb_warn("escaped terminator '%c' inside string interpolation", c);
3905 quoted_term |= 1 << CHAR_BIT;
3906 }
3907 goto retry;
3908 }
3909 return '\\';
3910
3911 case '%':
3912 if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
3913 int term;
3914 int paren;
3915
3916 c = nextc();
3917 quotation:
3918 if (c == '\\' && WHEN_QUOTED_TERM(peek(quoted_term_char))) {
3919 c = nextc();
3920 if (!(quoted_term & (1 << CHAR_BIT))) {
3921 rb_warn("escaped terminator '%s%c' inside string interpolation",
3922 (c == '\'' ? "\\" : ""), c);
3923 quoted_term |= 1 << CHAR_BIT;
3924 }
3925 }
3926 if (!ISALNUM(c)) {
3927 term = c;
3928 c = 'Q';
3929 }
3930 else {
3931 term = nextc();
3932 if (ISALNUM(term) || ismbchar(term)) {
3933 yyerror("unknown type of %string");
3934 return 0;
3935 }
3936 }
3937 if (c == -1 || term == -1) {
3938 rb_compile_error("unterminated quoted string meets end of file");
3939 return 0;
3940 }
3941 paren = term;
3942 if (term == '(') term = ')';
3943 else if (term == '[') term = ']';
3944 else if (term == '{') term = '}';
3945 else if (term == '<') term = '>';
3946 else paren = 0;
3947
3948 switch (c) {
3949 case 'Q':
3950 lex_strterm = NEW_STRTERM(str_dquote, term, paren);
3951 return tSTRING_BEG;
3952
3953 case 'q':
3954 lex_strterm = NEW_STRTERM(str_squote, term, paren);
3955 return tSTRING_BEG;
3956
3957 case 'W':
3958 lex_strterm = NEW_STRTERM(str_dquote | STR_FUNC_QWORDS, term, paren);
3959 do {c = nextc();} while (ISSPACE(c));
3960 pushback(c);
3961 return tWORDS_BEG;
3962
3963 case 'w':
3964 lex_strterm = NEW_STRTERM(str_squote | STR_FUNC_QWORDS, term, paren);
3965 do {c = nextc();} while (ISSPACE(c));
3966 pushback(c);
3967 return tQWORDS_BEG;
3968
3969 case 'x':
3970 lex_strterm = NEW_STRTERM(str_xquote, term, paren);
3971 return tXSTRING_BEG;
3972
3973 case 'r':
3974 lex_strterm = NEW_STRTERM(str_regexp, term, paren);
3975 return tREGEXP_BEG;
3976
3977 default:
3978 yyerror("unknown type of %string");
3979 return 0;
3980 }
3981 }
3982 if ((c = nextc()) == '=') {
3983 yylval.id = '%';
3984 lex_state = EXPR_BEG;
3985 return tOP_ASGN;
3986 }
3987 if (IS_ARG() && space_seen && !ISSPACE(c)) {
3988 goto quotation;
3989 }
3990 switch (lex_state) {
3991 case EXPR_FNAME: case EXPR_DOT:
3992 lex_state = EXPR_ARG; break;
3993 default:
3994 lex_state = EXPR_BEG; break;
3995 }
3996 pushback(c);
3997 return '%';
3998
3999 case '$':
4000 lex_state = EXPR_END;
4001 newtok();
4002 c = nextc();
4003 switch (c) {
4004 case '_':
4005 c = nextc();
4006 if (is_identchar(c)) {
4007 tokadd('$');
4008 tokadd('_');
4009 break;
4010 }
4011 pushback(c);
4012 c = '_';
4013
4014 case '~':
4015 local_cnt(c);
4016
4017 case '*':
4018 case '$':
4019 case '?':
4020 case '!':
4021 case '@':
4022 case '/':
4023 case '\\':
4024 case ';':
4025 case ',':
4026 case '.':
4027 case '=':
4028 case ':':
4029 case '<':
4030 case '>':
4031 case '\"':
4032 tokadd('$');
4033 tokadd(c);
4034 tokfix();
4035 yylval.id = rb_intern(tok());
4036 return tGVAR;
4037
4038 case '-':
4039 tokadd('$');
4040 tokadd(c);
4041 c = nextc();
4042 tokadd(c);
4043 tokfix();
4044 yylval.id = rb_intern(tok());
4045
4046 return tGVAR;
4047
4048 case '&':
4049 case '`':
4050 case '\'':
4051 case '+':
4052 yylval.node = NEW_BACK_REF(c);
4053 return tBACK_REF;
4054
4055 case '1': case '2': case '3':
4056 case '4': case '5': case '6':
4057 case '7': case '8': case '9':
4058 tokadd('$');
4059 while (ISDIGIT(c)) {
4060 tokadd(c);
4061 c = nextc();
4062 }
4063 if (is_identchar(c))
4064 break;
4065 pushback(c);
4066 tokfix();
4067 yylval.node = NEW_NTH_REF(atoi(tok()+1));
4068 return tNTH_REF;
4069
4070 default:
4071 if (!is_identchar(c)) {
4072 pushback(c);
4073 return '$';
4074 }
4075 case '0':
4076 tokadd('$');
4077 }
4078 break;
4079
4080 case '@':
4081 c = nextc();
4082 newtok();
4083 tokadd('@');
4084 if (c == '@') {
4085 tokadd('@');
4086 c = nextc();
4087 }
4088 if (ISDIGIT(c)) {
4089 if (tokidx == 1) {
4090 rb_compile_error("`@%c' is not a valid instance variable name", c);
4091 }
4092 else {
4093 rb_compile_error("`@@%c' is not a valid class variable name", c);
4094 }
4095 }
4096 if (!is_identchar(c)) {
4097 pushback(c);
4098 return '@';
4099 }
4100 break;
4101
4102 default:
4103 if (!is_identchar(c) || ISDIGIT(c)) {
4104 rb_compile_error("Invalid char `\\%03o' in expression", c);
4105 goto retry;
4106 }
4107
4108 newtok();
4109 break;
4110 }
4111
4112 while (is_identchar(c)) {
4113 tokadd(c);
4114 if (ismbchar(c)) {
4115 int i, len = mbclen(c)-1;
4116
4117 for (i = 0; i < len; i++) {
4118 c = nextc();
4119 tokadd(c);
4120 }
4121 }
4122 c = nextc();
4123 }
4124 if ((c == '!' || c == '?') && is_identchar(tok()[0]) && !peek('=')) {
4125 tokadd(c);
4126 }
4127 else {
4128 pushback(c);
4129 }
4130 tokfix();
4131
4132 {
4133 int result = 0;
4134
4135 switch (tok()[0]) {
4136 case '$':
4137 lex_state = EXPR_END;
4138 result = tGVAR;
4139 break;
4140 case '@':
4141 lex_state = EXPR_END;
4142 if (tok()[1] == '@')
4143 result = tCVAR;
4144 else
4145 result = tIVAR;
4146 break;
4147
4148 default:
4149 if (toklast() == '!' || toklast() == '?') {
4150 result = tFID;
4151 }
4152 else {
4153 if (lex_state == EXPR_FNAME) {
4154 if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
4155 (!peek('=') || lex_p + 1 < lex_pend && lex_p[1] == '>')) {
4156 result = tIDENTIFIER;
4157 tokadd(c);
4158 }
4159 else {
4160 pushback(c);
4161 }
4162 }
4163 if (result == 0 && ISUPPER(tok()[0])) {
4164 result = tCONSTANT;
4165 }
4166 else {
4167 result = tIDENTIFIER;
4168 }
4169 }
4170
4171 if (lex_state != EXPR_DOT) {
4172 struct kwtable *kw;
4173
4174
4175 kw = rb_reserved_word(tok(), toklen());
4176 if (kw) {
4177 enum lex_state state = lex_state;
4178 lex_state = kw->state;
4179 if (state == EXPR_FNAME) {
4180 yylval.id = rb_intern(kw->name);
4181 }
4182 if (kw->id[0] == kDO) {
4183 if (COND_P()) return kDO_COND;
4184 if (CMDARG_P() && state != EXPR_CMDARG)
4185 return kDO_BLOCK;
4186 if (state == EXPR_ENDARG)
4187 return kDO_BLOCK;
4188 return kDO;
4189 }
4190 if (state == EXPR_BEG)
4191 return kw->id[0];
4192 else {
4193 if (kw->id[0] != kw->id[1])
4194 lex_state = EXPR_BEG;
4195 return kw->id[1];
4196 }
4197 }
4198 }
4199
4200 if (lex_state == EXPR_BEG ||
4201 lex_state == EXPR_MID ||
4202 lex_state == EXPR_DOT ||
4203 lex_state == EXPR_ARG ||
4204 lex_state == EXPR_CMDARG) {
4205 if (cmd_state)
4206 lex_state = EXPR_CMDARG;
4207 else
4208 lex_state = EXPR_ARG;
4209 }
4210 else {
4211 lex_state = EXPR_END;
4212 }
4213 }
4214 tokfix();
4215 if (strcmp(tok(), "__END__") == 0 &&
4216 lex_p - lex_pbeg == 7 &&
4217 (lex_pend == lex_p || *lex_p == '\n' || *lex_p == '\r')) {
4218 ruby__end__seen = 1;
4219 lex_lastline = 0;
4220 return -1;
4221 }
4222 last_id = yylval.id = rb_intern(tok());
4223 return result;
4224 }
4225 }
4226
4227 NODE*
4228 rb_node_newnode(type, a0, a1, a2)
4229 enum node_type type;
4230 NODE *a0, *a1, *a2;
4231 {
4232 NODE *n = (NODE*)rb_newobj();
4233
4234 n->flags |= T_NODE;
4235 nd_set_type(n, type);
4236 nd_set_line(n, ruby_sourceline);
4237 n->nd_file = ruby_sourcefile;
4238
4239 n->u1.node = a0;
4240 n->u2.node = a1;
4241 n->u3.node = a2;
4242
4243 return n;
4244 }
4245
4246 static enum node_type
4247 nodetype(node)
4248 NODE *node;
4249 {
4250 return (enum node_type)nd_type(node);
4251 }
4252
4253 static int
4254 nodeline(node)
4255 NODE *node;
4256 {
4257 return nd_line(node);
4258 }
4259
4260 static NODE*
4261 newline_node(node)
4262 NODE *node;
4263 {
4264 NODE *nl = 0;
4265 if (node) {
4266 nl = NEW_NEWLINE(node);
4267 fixpos(nl, node);
4268 nl->nd_nth = nd_line(node);
4269 }
4270 return nl;
4271 }
4272
4273 static void
4274 fixpos(node, orig)
4275 NODE *node, *orig;
4276 {
4277 if (!node) return;
4278 if (!orig) return;
4279 if (orig == (NODE*)1) return;
4280 node->nd_file = orig->nd_file;
4281 nd_set_line(node, nd_line(orig));
4282 }
4283
4284 static NODE*
4285 block_append(head, tail)
4286 NODE *head, *tail;
4287 {
4288 NODE *end;
4289
4290 if (tail == 0) return head;
4291 if (head == 0) return tail;
4292
4293 if (nd_type(head) != NODE_BLOCK) {
4294 end = NEW_BLOCK(head);
4295 end->nd_end = end;
4296 fixpos(end, head);
4297 head = end;
4298 }
4299 else {
4300 end = head->nd_end;
4301 }
4302
4303 if (RTEST(ruby_verbose)) {
4304 NODE *nd = end->nd_head;
4305 newline:
4306 switch (nd_type(nd)) {
4307 case NODE_RETURN:
4308 case NODE_BREAK:
4309 case NODE_NEXT:
4310 case NODE_REDO:
4311 case NODE_RETRY:
4312 rb_warning("statement not reached");
4313 break;
4314
4315 case NODE_NEWLINE:
4316 nd = nd->nd_next;
4317 goto newline;
4318
4319 default:
4320 break;
4321 }
4322 }
4323
4324 if (nd_type(tail) != NODE_BLOCK) {
4325 tail = NEW_BLOCK(tail);
4326 tail->nd_end = tail;
4327 }
4328 end->nd_next = tail;
4329 head->nd_end = tail->nd_end;
4330 return head;
4331 }
4332
4333
4334 static NODE*
4335 list_append(list, item)
4336 NODE *list, *item;
4337 {
4338 NODE *last;
4339
4340 if (list == 0) return NEW_LIST(item);
4341
4342 last = list;
4343 while (last->nd_next) {
4344 last = last->nd_next;
4345 }
4346
4347 last->nd_next = NEW_LIST(item);
4348 list->nd_alen += 1;
4349 return list;
4350 }
4351
4352
4353 static NODE*
4354 list_concat(head, tail)
4355 NODE *head, *tail;
4356 {
4357 NODE *last;
4358
4359 last = head;
4360 while (last->nd_next) {
4361 last = last->nd_next;
4362 }
4363
4364 last->nd_next = tail;
4365 head->nd_alen += tail->nd_alen;
4366
4367 return head;
4368 }
4369
4370 static NODE *
4371 literal_concat_string(head, tail, str)
4372 NODE *head, *tail;
4373 VALUE str;
4374 {
4375 NODE *last = head, *last1 = 0, *prev = 0;
4376
4377 for (;;) {
4378 switch (nd_type(last)) {
4379 case NODE_NEWLINE:
4380 last = last->nd_next;
4381 break;
4382 case NODE_BLOCK:
4383 case NODE_DSTR:
4384 if (!last1) last1 = prev;
4385 prev = last;
4386 while (last->nd_next) {
4387 last = last->nd_next;
4388 }
4389 last = last->nd_head;
4390 break;
4391 case NODE_STR:
4392 rb_str_concat(last->nd_lit, str);
4393 if (tail) rb_gc_force_recycle((VALUE)tail);
4394 return head;
4395 default:
4396 if (!last1) {
4397 last1 = head;
4398 head = NEW_DSTR(rb_str_new(0, 0));
4399 head->nd_next = last1 = NEW_LIST(last1);
4400 head->nd_alen += 1;
4401 }
4402 if (!tail) tail = NEW_STR(str);
4403 list_append(head, tail);
4404 return head;
4405 }
4406 }
4407 }
4408
4409 static NODE *
4410 literal_concat_dstr(head, tail)
4411 NODE *head, *tail;
4412 {
4413 NODE *last;
4414
4415 switch (nd_type(head)) {
4416 case NODE_STR:
4417 tail->nd_lit = head->nd_lit;
4418 rb_gc_force_recycle((VALUE)head);
4419 return tail;
4420 case NODE_DSTR:
4421 last = tail->nd_next;
4422 last->nd_alen = tail->nd_alen;
4423 rb_gc_force_recycle((VALUE)tail);
4424 return list_concat(head, last);
4425 default:
4426 head = NEW_LIST(head);
4427 case NODE_ARRAY:
4428 case NODE_ZARRAY:
4429 tail->nd_lit = 0;
4430 tail->nd_alen += head->nd_alen;
4431 tail->nd_next = list_concat(head, tail->nd_next);
4432 return tail;
4433 }
4434 }
4435
4436 static NODE *
4437 literal_concat_list(head, tail)
4438 NODE *head, *tail;
4439 {
4440 tail = NEW_LIST(tail);
4441 switch (nd_type(head)) {
4442 case NODE_STR:
4443 nd_set_type(head, NODE_DSTR);
4444 head->nd_next = tail;
4445 head->nd_alen = tail->nd_alen;
4446 return head;
4447 case NODE_DSTR:
4448 return list_concat(head, tail);
4449 default:
4450 head = NEW_LIST(head);
4451 return list_concat(NEW_DSTR(rb_str_new(0, 0)), list_concat(head, tail));
4452 }
4453 }
4454
4455 static NODE *
4456 literal_append(head, tail)
4457 NODE *head, *tail;
4458 {
4459 if (!head) return tail;
4460 if (!tail) return head;
4461
4462 switch (nd_type(tail)) {
4463 case NODE_STR:
4464 if (nd_type(head) == NODE_STR) {
4465 rb_str_concat(head->nd_lit, tail->nd_lit);
4466 rb_gc_force_recycle((VALUE)tail);
4467 return head;
4468 }
4469
4470 default:
4471 return literal_concat_list(head, tail);
4472 }
4473 }
4474
4475
4476 static NODE *
4477 literal_concat(head, tail)
4478 NODE *head, *tail;
4479 {
4480 if (!head) return tail;
4481 if (!tail) return head;
4482
4483 switch (nd_type(tail)) {
4484 case NODE_STR:
4485 return literal_concat_string(head, tail, tail->nd_lit);
4486
4487 case NODE_DSTR:
4488 head = literal_concat_string(head, 0, tail->nd_lit);
4489 return literal_concat_dstr(head, tail);
4490
4491 default:
4492 return literal_concat_list(head, tail);
4493 }
4494 }
4495
4496 static NODE *
4497 call_op(recv, id, narg, arg1)
4498 NODE *recv;
4499 ID id;
4500 int narg;
4501 NODE *arg1;
4502 {
4503 value_expr(recv);
4504 if (narg == 1) {
4505 value_expr(arg1);
4506 }
4507
4508 return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0);
4509 }
4510
4511 static NODE*
4512 match_gen(node1, node2)
4513 NODE *node1;
4514 NODE *node2;
4515 {
4516 local_cnt('~');
4517
4518 value_expr(node1);
4519 value_expr(node2);
4520 if (node1) {
4521 switch (nd_type(node1)) {
4522 case NODE_DREGX:
4523 case NODE_DREGX_ONCE:
4524 return NEW_MATCH2(node1, node2);
4525
4526 case NODE_LIT:
4527 if (TYPE(node1->nd_lit) == T_REGEXP) {
4528 return NEW_MATCH2(node1, node2);
4529 }
4530 }
4531 }
4532
4533 if (node2) {
4534 switch (nd_type(node2)) {
4535 case NODE_DREGX:
4536 case NODE_DREGX_ONCE:
4537 return NEW_MATCH3(node2, node1);
4538
4539 case NODE_LIT:
4540 if (TYPE(node2->nd_lit) == T_REGEXP) {
4541 return NEW_MATCH3(node2, node1);
4542 }
4543 }
4544 }
4545
4546 return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
4547 }
4548
4549 static NODE*
4550 gettable(id)
4551 ID id;
4552 {
4553 if (id == kSELF) {
4554 return NEW_SELF();
4555 }
4556 else if (id == kNIL) {
4557 return NEW_NIL();
4558 }
4559 else if (id == kTRUE) {
4560 return NEW_TRUE();
4561 }
4562 else if (id == kFALSE) {
4563 return NEW_FALSE();
4564 }
4565 else if (id == k__FILE__) {
4566 return NEW_STR(rb_str_new2(ruby_sourcefile));
4567 }
4568 else if (id == k__LINE__) {
4569 return NEW_LIT(INT2FIX(ruby_sourceline));
4570 }
4571 else if (is_local_id(id)) {
4572 if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id);
4573 if (local_id(id)) return NEW_LVAR(id);
4574
4575 #if 0
4576
4577 rb_warn("ambiguous identifier; %s() or self.%s is better for method call",
4578 rb_id2name(id), rb_id2name(id));
4579 #endif
4580 return NEW_VCALL(id);
4581 }
4582 else if (is_global_id(id)) {
4583 return NEW_GVAR(id);
4584 }
4585 else if (is_instance_id(id)) {
4586 return NEW_IVAR(id);
4587 }
4588 else if (is_const_id(id)) {
4589 return NEW_CONST(id);
4590 }
4591 else if (is_class_id(id)) {
4592 return NEW_CVAR(id);
4593 }
4594 rb_compile_error("identifier %s is not valid", rb_id2name(id));
4595 return 0;
4596 }
4597
4598 static NODE*
4599 assignable(id, val)
4600 ID id;
4601 NODE *val;
4602 {
4603 value_expr(val);
4604 if (id == kSELF) {
4605 yyerror("Can't change the value of self");
4606 }
4607 else if (id == kNIL) {
4608 yyerror("Can't assign to nil");
4609 }
4610 else if (id == kTRUE) {
4611 yyerror("Can't assign to true");
4612 }
4613 else if (id == kFALSE) {
4614 yyerror("Can't assign to false");
4615 }
4616 else if (id == k__FILE__) {
4617 yyerror("Can't assign to __FILE__");
4618 }
4619 else if (id == k__LINE__) {
4620 yyerror("Can't assign to __LINE__");
4621 }
4622 else if (is_local_id(id)) {
4623 if (rb_dvar_curr(id)) {
4624 return NEW_DASGN_CURR(id, val);
4625 }
4626 else if (rb_dvar_defined(id)) {
4627 return NEW_DASGN(id, val);
4628 }
4629 else if (local_id(id) || !dyna_in_block()) {
4630 return NEW_LASGN(id, val);
4631 }
4632 else{
4633 rb_dvar_push(id, Qnil);
4634 return NEW_DASGN_CURR(id, val);
4635 }
4636 }
4637 else if (is_global_id(id)) {
4638 return NEW_GASGN(id, val);
4639 }
4640 else if (is_instance_id(id)) {
4641 return NEW_IASGN(id, val);
4642 }
4643 else if (is_const_id(id)) {
4644 if (in_def || in_single)
4645 yyerror("dynamic constant assignment");
4646 return NEW_CDECL(id, val);
4647 }
4648 else if (is_class_id(id)) {
4649 if (in_def || in_single) return NEW_CVASGN(id, val);
4650 return NEW_CVDECL(id, val);
4651 }
4652 else {
4653 rb_bug("bad id for variable");
4654 }
4655 return 0;
4656 }
4657
4658 static NODE *
4659 aryset(recv, idx)
4660 NODE *recv, *idx;
4661 {
4662 value_expr(recv);
4663 return NEW_CALL(recv, tASET, idx);
4664 }
4665
4666 ID
4667 rb_id_attrset(id)
4668 ID id;
4669 {
4670 id &= ~ID_SCOPE_MASK;
4671 id |= ID_ATTRSET;
4672 return id;
4673 }
4674
4675 static NODE *
4676 attrset(recv, id)
4677 NODE *recv;
4678 ID id;
4679 {
4680 value_expr(recv);
4681 return NEW_CALL(recv, rb_id_attrset(id), 0);
4682 }
4683
4684 static void
4685 rb_backref_error(node)
4686 NODE *node;
4687 {
4688 switch (nd_type(node)) {
4689 case NODE_NTH_REF:
4690 rb_compile_error("Can't set variable $%d", node->nd_nth);
4691 break;
4692 case NODE_BACK_REF:
4693 rb_compile_error("Can't set variable $%c", node->nd_nth);
4694 break;
4695 }
4696 }
4697
4698 static NODE *
4699 arg_concat(node1, node2)
4700 NODE *node1;
4701 NODE *node2;
4702 {
4703 if (!node2) return node1;
4704 return NEW_ARGSCAT(node1, node2);
4705 }
4706
4707 static NODE *
4708 arg_add(node1, node2)
4709 NODE *node1;
4710 NODE *node2;
4711 {
4712 if (!node1) return NEW_LIST(node2);
4713 if (nd_type(node1) == NODE_ARRAY) {
4714 return list_append(node1, node2);
4715 }
4716 else {
4717 return NEW_ARGSPUSH(node1, node2);
4718 }
4719 }
4720
4721 static NODE*
4722 node_assign(lhs, rhs)
4723 NODE *lhs, *rhs;
4724 {
4725 if (!lhs) return 0;
4726
4727 value_expr(rhs);
4728 switch (nd_type(lhs)) {
4729 case NODE_GASGN:
4730 case NODE_IASGN:
4731 case NODE_LASGN:
4732 case NODE_DASGN:
4733 case NODE_DASGN_CURR:
4734 case NODE_MASGN:
4735 case NODE_CDECL:
4736 case NODE_CVDECL:
4737 case NODE_CVASGN:
4738 lhs->nd_value = rhs;
4739 break;
4740
4741 case NODE_CALL:
4742 lhs->nd_args = arg_add(lhs->nd_args, rhs);
4743 break;
4744
4745 default:
4746
4747 break;
4748 }
4749
4750 return lhs;
4751 }
4752
4753 static int
4754 value_expr(node)
4755 NODE *node;
4756 {
4757 while (node) {
4758 switch (nd_type(node)) {
4759 case NODE_CLASS:
4760 case NODE_MODULE:
4761 case NODE_DEFN:
4762 case NODE_DEFS:
4763 rb_warning("void value expression");
4764 return Qfalse;
4765
4766 case NODE_RETURN:
4767 case NODE_BREAK:
4768 case NODE_NEXT:
4769 case NODE_REDO:
4770 case NODE_RETRY:
4771 yyerror("void value expression");
4772
4773 return Qfalse;
4774
4775 case NODE_BLOCK:
4776 while (node->nd_next) {
4777 node = node->nd_next;
4778 }
4779 node = node->nd_head;
4780 break;
4781
4782 case NODE_BEGIN:
4783 node = node->nd_body;
4784 break;
4785
4786 case NODE_IF:
4787 if (!value_expr(node->nd_body)) return Qfalse;
4788 node = node->nd_else;
4789 break;
4790
4791 case NODE_AND:
4792 case NODE_OR:
4793 node = node->nd_2nd;
4794 break;
4795
4796 case NODE_NEWLINE:
4797 node = node->nd_next;
4798 break;
4799
4800 default:
4801 return Qtrue;
4802 }
4803 }
4804
4805 return Qtrue;
4806 }
4807
4808 static void
4809 void_expr(node)
4810 NODE *node;
4811 {
4812 char *useless = 0;
4813
4814 if (!RTEST(ruby_verbose)) return;
4815 if (!node) return;
4816
4817 again:
4818 switch (nd_type(node)) {
4819 case NODE_NEWLINE:
4820 node = node->nd_next;
4821 goto again;
4822
4823 case NODE_CALL:
4824 switch (node->nd_mid) {
4825 case '+':
4826 case '-':
4827 case '*':
4828 case '/':
4829 case '%':
4830 case tPOW:
4831 case tUPLUS:
4832 case tUMINUS:
4833 case '|':
4834 case '^':
4835 case '&':
4836 case tCMP:
4837 case '>':
4838 case tGEQ:
4839 case '<':
4840 case tLEQ:
4841 case tEQ:
4842 case tNEQ:
4843 useless = rb_id2name(node->nd_mid);
4844 break;
4845 }
4846 break;
4847
4848 case NODE_LVAR:
4849 case NODE_DVAR:
4850 case NODE_GVAR:
4851 case NODE_IVAR:
4852 case NODE_CVAR:
4853 case NODE_NTH_REF:
4854 case NODE_BACK_REF:
4855 useless = "a variable";
4856 break;
4857 case NODE_CONST:
4858 case NODE_CREF:
4859 useless = "a constant";
4860 break;
4861 case NODE_LIT:
4862 case NODE_STR:
4863 case NODE_DSTR:
4864 case NODE_DREGX:
4865 case NODE_DREGX_ONCE:
4866 useless = "a literal";
4867 break;
4868 case NODE_COLON2:
4869 case NODE_COLON3:
4870 useless = "::";
4871 break;
4872 case NODE_DOT2:
4873 useless = "..";
4874 break;
4875 case NODE_DOT3:
4876 useless = "...";
4877 break;
4878 case NODE_SELF:
4879 useless = "self";
4880 break;
4881 case NODE_NIL:
4882 useless = "nil";
4883 break;
4884 case NODE_TRUE:
4885 useless = "true";
4886 break;
4887 case NODE_FALSE:
4888 useless = "false";
4889 break;
4890 case NODE_DEFINED:
4891 useless = "defined?";
4892 break;
4893 }
4894
4895 if (useless) {
4896 int line = ruby_sourceline;
4897
4898 ruby_sourceline = nd_line(node);
4899 rb_warn("useless use of %s in void context", useless);
4900 ruby_sourceline = line;
4901 }
4902 }
4903
4904 static void
4905 void_stmts(node)
4906 NODE *node;
4907 {
4908 if (!RTEST(ruby_verbose)) return;
4909 if (!node) return;
4910 if (nd_type(node) != NODE_BLOCK) return;
4911
4912 for (;;) {
4913 if (!node->nd_next) return;
4914 void_expr(node->nd_head);
4915 node = node->nd_next;
4916 }
4917 }
4918
4919 static int
4920 assign_in_cond(node)
4921 NODE *node;
4922 {
4923 switch (nd_type(node)) {
4924 case NODE_MASGN:
4925 yyerror("multiple assignment in conditional");
4926 return 1;
4927
4928 case NODE_LASGN:
4929 case NODE_DASGN:
4930 case NODE_GASGN:
4931 case NODE_IASGN:
4932 break;
4933
4934 case NODE_NEWLINE:
4935 default:
4936 return 0;
4937 }
4938
4939 switch (nd_type(node->nd_value)) {
4940 case NODE_LIT:
4941 case NODE_STR:
4942 case NODE_NIL:
4943 case NODE_TRUE:
4944 case NODE_FALSE:
4945
4946 rb_warn("found = in conditional, should be ==");
4947 return 1;
4948
4949 case NODE_DSTR:
4950 case NODE_XSTR:
4951 case NODE_DXSTR:
4952 case NODE_EVSTR:
4953 case NODE_DREGX:
4954 default:
4955 break;
4956 }
4957 #if 0
4958 if (assign_in_cond(node->nd_value) == 0) {
4959 rb_warning("assignment in condition");
4960 }
4961 #endif
4962 return 1;
4963 }
4964
4965 static int
4966 e_option_supplied()
4967 {
4968 if (strcmp(ruby_sourcefile, "-e") == 0)
4969 return Qtrue;
4970 return Qfalse;
4971 }
4972
4973 static void
4974 warn_unless_e_option(str)
4975 const char *str;
4976 {
4977 if (!e_option_supplied()) rb_warn(str);
4978 }
4979
4980 static void
4981 warning_unless_e_option(str)
4982 const char *str;
4983 {
4984 if (!e_option_supplied()) rb_warning(str);
4985 }
4986
4987 static NODE *cond0();
4988
4989 static NODE*
4990 range_op(node)
4991 NODE *node;
4992 {
4993 enum node_type type;
4994
4995 if (!e_option_supplied()) return node;
4996 if (node == 0) return 0;
4997
4998 value_expr(node);
4999 node = cond0(node);
5000 type = nd_type(node);
5001 if (type == NODE_NEWLINE) node = node->nd_next;
5002 if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
5003 warn_unless_e_option("integer literal in conditional range");
5004 return call_op(node,tEQ,1,NEW_GVAR(rb_intern("$.")));
5005 }
5006 return node;
5007 }
5008
5009 static NODE*
5010 cond0(node)
5011 NODE *node;
5012 {
5013 enum node_type type = nd_type(node);
5014
5015 assign_in_cond(node);
5016
5017 switch (type) {
5018 case NODE_DSTR:
5019 case NODE_STR:
5020 rb_warn("string literal in condition");
5021 break;
5022
5023 case NODE_DREGX:
5024 case NODE_DREGX_ONCE:
5025 warning_unless_e_option("regex literal in condition");
5026 local_cnt('_');
5027 local_cnt('~');
5028 return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
5029
5030 case NODE_AND:
5031 case NODE_OR:
5032 node->nd_1st = cond0(node->nd_1st);
5033 node->nd_2nd = cond0(node->nd_2nd);
5034 break;
5035
5036 case NODE_DOT2:
5037 case NODE_DOT3:
5038 node->nd_beg = range_op(node->nd_beg);
5039 node->nd_end = range_op(node->nd_end);
5040 if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
5041 else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
5042 node->nd_cnt = local_append(internal_id());
5043 warning_unless_e_option("range literal in condition");
5044 break;
5045
5046 case NODE_LIT:
5047 if (TYPE(node->nd_lit) == T_REGEXP) {
5048 warn_unless_e_option("regex literal in condition");
5049 nd_set_type(node, NODE_MATCH);
5050 local_cnt('_');
5051 local_cnt('~');
5052 }
5053 else {
5054 rb_warning("literal in condition");
5055 }
5056 default:
5057 break;
5058 }
5059 return node;
5060 }
5061
5062 static NODE*
5063 cond(node)
5064 NODE *node;
5065 {
5066 if (node == 0) return 0;
5067 value_expr(node);
5068 if (nd_type(node) == NODE_NEWLINE){
5069 node->nd_next = cond0(node->nd_next);
5070 return node;
5071 }
5072 return cond0(node);
5073 }
5074
5075 static NODE*
5076 logop(type, left, right)
5077 enum node_type type;
5078 NODE *left, *right;
5079 {
5080 value_expr(left);
5081 if (nd_type(left) == type) {
5082 NODE *node = left, *second;
5083 while ((second = node->nd_2nd) != 0 && nd_type(second) == type) {
5084 node = second;
5085 }
5086 node->nd_2nd = rb_node_newnode(type, second, right, 0);
5087 return left;
5088 }
5089 return rb_node_newnode(type, left, right, 0);
5090 }
5091
5092 static NODE *
5093 ret_args(node)
5094 NODE *node;
5095 {
5096 if (node) {
5097 if (nd_type(node) == NODE_BLOCK_PASS) {
5098 rb_compile_error("block argument should not be given");
5099 }
5100 }
5101 return node;
5102 }
5103
5104 static NODE *
5105 arg_blk_pass(node1, node2)
5106 NODE *node1;
5107 NODE *node2;
5108 {
5109 if (node2) {
5110 node2->nd_head = node1;
5111 return node2;
5112 }
5113 return node1;
5114 }
5115
5116 static NODE*
5117 arg_prepend(node1, node2)
5118 NODE *node1, *node2;
5119 {
5120 switch (nodetype(node2)) {
5121 case NODE_ARRAY:
5122 return list_concat(NEW_LIST(node1), node2);
5123
5124 case NODE_RESTARGS:
5125 return arg_concat(node1, node2->nd_head);
5126
5127 case NODE_BLOCK_PASS:
5128 node2->nd_body = arg_prepend(node1, node2->nd_body);
5129 return node2;
5130
5131 default:
5132 rb_bug("unknown nodetype(%d) for arg_prepend", nodetype(node2));
5133 }
5134 return 0;
5135 }
5136
5137 static NODE*
5138 new_call(r,m,a)
5139 NODE *r;
5140 ID m;
5141 NODE *a;
5142 {
5143 if (a && nd_type(a) == NODE_BLOCK_PASS) {
5144 a->nd_iter = NEW_CALL(r,m,a->nd_head);
5145 return a;
5146 }
5147 return NEW_CALL(r,m,a);
5148 }
5149
5150 static NODE*
5151 new_fcall(m,a)
5152 ID m;
5153 NODE *a;
5154 {
5155 if (a && nd_type(a) == NODE_BLOCK_PASS) {
5156 a->nd_iter = NEW_FCALL(m,a->nd_head);
5157 return a;
5158 }
5159 return NEW_FCALL(m,a);
5160 }
5161
5162 static NODE*
5163 new_super(a)
5164 NODE *a;
5165 {
5166 if (a && nd_type(a) == NODE_BLOCK_PASS) {
5167 a->nd_iter = NEW_SUPER(a->nd_head);
5168 return a;
5169 }
5170 return NEW_SUPER(a);
5171 }
5172
5173 static struct local_vars {
5174 ID *tbl;
5175 int nofree;
5176 int cnt;
5177 int dlev;
5178 struct RVarmap* dyna_vars;
5179 struct local_vars *prev;
5180 } *lvtbl;
5181
5182 static void
5183 local_push(top)
5184 int top;
5185 {
5186 struct local_vars *local;
5187
5188 local = ALLOC(struct local_vars);
5189 local->prev = lvtbl;
5190 local->nofree = 0;
5191 local->cnt = 0;
5192 local->tbl = 0;
5193 local->dlev = 0;
5194 local->dyna_vars = ruby_dyna_vars;
5195 lvtbl = local;
5196 if (!top) {
5197
5198 rb_dvar_push(0, (VALUE)ruby_dyna_vars);
5199 ruby_dyna_vars->next = 0;
5200 }
5201 }
5202
5203 static void
5204 local_pop()
5205 {
5206 struct local_vars *local = lvtbl->prev;
5207
5208 if (lvtbl->tbl) {
5209 if (!lvtbl->nofree) free(lvtbl->tbl);
5210 else lvtbl->tbl[0] = lvtbl->cnt;
5211 }
5212 ruby_dyna_vars = lvtbl->dyna_vars;
5213 free(lvtbl);
5214 lvtbl = local;
5215 }
5216
5217 static ID*
5218 local_tbl()
5219 {
5220 lvtbl->nofree = 1;
5221 return lvtbl->tbl;
5222 }
5223
5224 static int
5225 local_append(id)
5226 ID id;
5227 {
5228 if (lvtbl->tbl == 0) {
5229 lvtbl->tbl = ALLOC_N(ID, 4);
5230 lvtbl->tbl[0] = 0;
5231 lvtbl->tbl[1] = '_';
5232 lvtbl->tbl[2] = '~';
5233 lvtbl->cnt = 2;
5234 if (id == '_') return 0;
5235 if (id == '~') return 1;
5236 }
5237 else {
5238 REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
5239 }
5240
5241 lvtbl->tbl[lvtbl->cnt+1] = id;
5242 return lvtbl->cnt++;
5243 }
5244
5245 static int
5246 local_cnt(id)
5247 ID id;
5248 {
5249 int cnt, max;
5250
5251 if (id == 0) return lvtbl->cnt;
5252
5253 for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
5254 if (lvtbl->tbl[cnt] == id) return cnt-1;
5255 }
5256 return local_append(id);
5257 }
5258
5259 static int
5260 local_id(id)
5261 ID id;
5262 {
5263 int i, max;
5264
5265 if (lvtbl == 0) return Qfalse;
5266 for (i=3, max=lvtbl->cnt+1; i<max; i++) {
5267 if (lvtbl->tbl[i] == id) return Qtrue;
5268 }
5269 return Qfalse;
5270 }
5271
5272 static void
5273 top_local_init()
5274 {
5275 local_push(1);
5276 lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
5277 if (lvtbl->cnt > 0) {
5278 lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
5279 MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
5280 }
5281 else {
5282 lvtbl->tbl = 0;
5283 }
5284 if (ruby_dyna_vars)
5285 lvtbl->dlev = 1;
5286 else
5287 lvtbl->dlev = 0;
5288 }
5289
5290 static void
5291 top_local_setup()
5292 {
5293 int len = lvtbl->cnt;
5294 int i;
5295
5296 if (len > 0) {
5297 i = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
5298
5299 if (i < len) {
5300 if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
5301 VALUE *vars = ALLOC_N(VALUE, len+1);
5302 if (ruby_scope->local_vars) {
5303 *vars++ = ruby_scope->local_vars[-1];
5304 MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
5305 rb_mem_clear(vars+i, len-i);
5306 }
5307 else {
5308 *vars++ = 0;
5309 rb_mem_clear(vars, len);
5310 }
5311 ruby_scope->local_vars = vars;
5312 ruby_scope->flags |= SCOPE_MALLOC;
5313 }
5314 else {
5315 VALUE *vars = ruby_scope->local_vars-1;
5316 REALLOC_N(vars, VALUE, len+1);
5317 ruby_scope->local_vars = vars+1;
5318 rb_mem_clear(ruby_scope->local_vars+i, len-i);
5319 }
5320 if (ruby_scope->local_tbl && ruby_scope->local_vars[-1] == 0) {
5321 free(ruby_scope->local_tbl);
5322 }
5323 ruby_scope->local_vars[-1] = 0;
5324 ruby_scope->local_tbl = local_tbl();
5325 }
5326 }
5327 local_pop();
5328 }
5329
5330 static struct RVarmap*
5331 dyna_push()
5332 {
5333 struct RVarmap* vars = ruby_dyna_vars;
5334
5335 rb_dvar_push(0, 0);
5336 lvtbl->dlev++;
5337 return vars;
5338 }
5339
5340 static void
5341 dyna_pop(vars)
5342 struct RVarmap* vars;
5343 {
5344 lvtbl->dlev--;
5345 ruby_dyna_vars = vars;
5346 }
5347
5348 static int
5349 dyna_in_block()
5350 {
5351 return (lvtbl->dlev > 0);
5352 }
5353
5354 int
5355 ruby_parser_stack_on_heap()
5356 {
5357 #if defined(YYBISON) && !defined(C_ALLOCA)
5358 return Qfalse;
5359 #else
5360 return Qtrue;
5361 #endif
5362 }
5363
5364 void
5365 rb_gc_mark_parser()
5366 {
5367 if (!ruby_in_compile) return;
5368
5369 rb_gc_mark_maybe((VALUE)yylval.node);
5370 rb_gc_mark(ruby_debug_lines);
5371 rb_gc_mark(lex_lastline);
5372 rb_gc_mark(lex_input);
5373 rb_gc_mark((VALUE)lex_strterm);
5374 }
5375
5376 void
5377 rb_parser_append_print()
5378 {
5379 ruby_eval_tree =
5380 block_append(ruby_eval_tree,
5381 NEW_FCALL(rb_intern("print"),
5382 NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
5383 }
5384
5385 void
5386 rb_parser_while_loop(chop, split)
5387 int chop, split;
5388 {
5389 if (split) {
5390 ruby_eval_tree =
5391 block_append(NEW_GASGN(rb_intern("$F"),
5392 NEW_CALL(NEW_GVAR(rb_intern("$_")),
5393 rb_intern("split"), 0)),
5394 ruby_eval_tree);
5395 }
5396 if (chop) {
5397 ruby_eval_tree =
5398 block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
5399 rb_intern("chop!"), 0), ruby_eval_tree);
5400 }
5401 ruby_eval_tree = NEW_OPT_N(ruby_eval_tree);
5402 }
5403
5404 static struct {
5405 ID token;
5406 char *name;
5407 } op_tbl[] = {
5408 {tDOT2, ".."},
5409 {tDOT3, "..."},
5410 {'+', "+"},
5411 {'-', "-"},
5412 {'+', "+(binary)"},
5413 {'-', "-(binary)"},
5414 {'*', "*"},
5415 {'/', "/"},
5416 {'%', "%"},
5417 {tPOW, "**"},
5418 {tUPLUS, "+@"},
5419 {tUMINUS, "-@"},
5420 {tUPLUS, "+(unary)"},
5421 {tUMINUS, "-(unary)"},
5422 {'|', "|"},
5423 {'^', "^"},
5424 {'&', "&"},
5425 {tCMP, "<=>"},
5426 {'>', ">"},
5427 {tGEQ, ">="},
5428 {'<', "<"},
5429 {tLEQ, "<="},
5430 {tEQ, "=="},
5431 {tEQQ, "==="},
5432 {tNEQ, "!="},
5433 {tMATCH, "=~"},
5434 {tNMATCH, "!~"},
5435 {'!', "!"},
5436 {'~', "~"},
5437 {'!', "!(unary)"},
5438 {'~', "~(unary)"},
5439 {'!', "!@"},
5440 {'~', "~@"},
5441 {tAREF, "[]"},
5442 {tASET, "[]="},
5443 {tLSHFT, "<<"},
5444 {tRSHFT, ">>"},
5445 {tCOLON2, "::"},
5446 {'`', "`"},
5447 {0, 0}
5448 };
5449
5450 static st_table *sym_tbl;
5451 static st_table *sym_rev_tbl;
5452
5453 void
5454 Init_sym()
5455 {
5456 sym_tbl = st_init_strtable_with_size(200);
5457 sym_rev_tbl = st_init_numtable_with_size(200);
5458 }
5459
5460 static ID last_id = LAST_TOKEN;
5461
5462 static ID
5463 internal_id()
5464 {
5465 return ID_INTERNAL | (++last_id << ID_SCOPE_SHIFT);
5466 }
5467
5468 ID
5469 rb_intern(name)
5470 const char *name;
5471 {
5472 const char *m = name;
5473 ID id;
5474 int last;
5475
5476 if (st_lookup(sym_tbl, name, &id))
5477 return id;
5478
5479 id = 0;
5480 switch (*name) {
5481 case '$':
5482 id |= ID_GLOBAL;
5483 m++;
5484 if (!is_identchar(*m)) m++;
5485 break;
5486 case '@':
5487 if (name[1] == '@') {
5488 m++;
5489 id |= ID_CLASS;
5490 }
5491 else {
5492 id |= ID_INSTANCE;
5493 }
5494 m++;
5495 break;
5496 default:
5497 if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
5498
5499 int i;
5500
5501 for (i=0; op_tbl[i].token; i++) {
5502 if (*op_tbl[i].name == *name &&
5503 strcmp(op_tbl[i].name, name) == 0) {
5504 id = op_tbl[i].token;
5505 goto id_regist;
5506 }
5507 }
5508 }
5509
5510 last = strlen(name)-1;
5511 if (name[last] == '=') {
5512
5513 char *buf = ALLOCA_N(char,last+1);
5514
5515 strncpy(buf, name, last);
5516 buf[last] = '\0';
5517 id = rb_intern(buf);
5518 if (id > LAST_TOKEN && !is_attrset_id(id)) {
5519 id = rb_id_attrset(id);
5520 goto id_regist;
5521 }
5522 id = ID_ATTRSET;
5523 }
5524 else if (ISUPPER(name[0])) {
5525 id = ID_CONST;
5526 }
5527 else {
5528 id = ID_LOCAL;
5529 }
5530 break;
5531 }
5532 while (*m && is_identchar(*m)) {
5533 m++;
5534 }
5535 if (*m) id = ID_JUNK;
5536 id |= ++last_id << ID_SCOPE_SHIFT;
5537 id_regist:
5538 name = strdup(name);
5539 st_add_direct(sym_tbl, name, id);
5540 st_add_direct(sym_rev_tbl, id, name);
5541 return id;
5542 }
5543
5544 char *
5545 rb_id2name(id)
5546 ID id;
5547 {
5548 char *name;
5549
5550 if (id < LAST_TOKEN) {
5551 int i = 0;
5552
5553 for (i=0; op_tbl[i].token; i++) {
5554 if (op_tbl[i].token == id)
5555 return op_tbl[i].name;
5556 }
5557 }
5558
5559 if (st_lookup(sym_rev_tbl, id, &name))
5560 return name;
5561
5562 if (is_attrset_id(id)) {
5563 ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
5564
5565 again:
5566 name = rb_id2name(id2);
5567 if (name) {
5568 char *buf = ALLOCA_N(char, strlen(name)+2);
5569
5570 strcpy(buf, name);
5571 strcat(buf, "=");
5572 rb_intern(buf);
5573 return rb_id2name(id);
5574 }
5575 if (is_local_id(id2)) {
5576 id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
5577 goto again;
5578 }
5579 }
5580 return 0;
5581 }
5582
5583 static int
5584 symbols_i(key, value, ary)
5585 char *key;
5586 ID value;
5587 VALUE ary;
5588 {
5589 rb_ary_push(ary, ID2SYM(value));
5590 return ST_CONTINUE;
5591 }
5592
5593 VALUE
5594 rb_sym_all_symbols()
5595 {
5596 VALUE ary = rb_ary_new2(sym_tbl->num_entries);
5597
5598 st_foreach(sym_tbl, symbols_i, ary);
5599 return ary;
5600 }
5601
5602 int
5603 rb_is_const_id(id)
5604 ID id;
5605 {
5606 if (is_const_id(id)) return Qtrue;
5607 return Qfalse;
5608 }
5609
5610 int
5611 rb_is_class_id(id)
5612 ID id;
5613 {
5614 if (is_class_id(id)) return Qtrue;
5615 return Qfalse;
5616 }
5617
5618 int
5619 rb_is_instance_id(id)
5620 ID id;
5621 {
5622 if (is_instance_id(id)) return Qtrue;
5623 return Qfalse;
5624 }
5625
5626 int
5627 rb_is_local_id(id)
5628 ID id;
5629 {
5630 if (is_local_id(id)) return Qtrue;
5631 return Qfalse;
5632 }
5633
5634 static void
5635 special_local_set(c, val)
5636 char c;
5637 VALUE val;
5638 {
5639 int cnt;
5640
5641 top_local_init();
5642 cnt = local_cnt(c);
5643 top_local_setup();
5644 ruby_scope->local_vars[cnt] = val;
5645 }
5646
5647 VALUE
5648 rb_backref_get()
5649 {
5650 VALUE *var = rb_svar(1);
5651 if (var) {
5652 return *var;
5653 }
5654 return Qnil;
5655 }
5656
5657 void
5658 rb_backref_set(val)
5659 VALUE val;
5660 {
5661 VALUE *var = rb_svar(1);
5662 if (var) {
5663 *var = val;
5664 }
5665 else {
5666 special_local_set('~', val);
5667 }
5668 }
5669
5670 VALUE
5671 rb_lastline_get()
5672 {
5673 VALUE *var = rb_svar(0);
5674 if (var) {
5675 return *var;
5676 }
5677 return Qnil;
5678 }
5679
5680 void
5681 rb_lastline_set(val)
5682 VALUE val;
5683 {
5684 VALUE *var = rb_svar(0);
5685 if (var) {
5686 *var = val;
5687 }
5688 else {
5689 special_local_set('_', val);
5690 }
5691 }