source: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/parse.y@ 473

Last change on this file since 473 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

File size: 187.8 KB
Line 
1/*
2** parse.y - mruby parser
3**
4** See Copyright Notice in mruby.h
5*/
6
7%{
8#undef PARSER_DEBUG
9#ifdef PARSER_DEBUG
10# define YYDEBUG 1
11#endif
12#define YYERROR_VERBOSE 1
13#define YYSTACK_USE_ALLOCA 1
14
15#include <ctype.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
19#include <mruby.h>
20#include <mruby/compile.h>
21#include <mruby/proc.h>
22#include <mruby/error.h>
23#include <mruby/throw.h>
24#include <mruby/string.h>
25#include "node.h"
26
27#define YYLEX_PARAM p
28
29typedef mrb_ast_node node;
30typedef struct mrb_parser_state parser_state;
31typedef struct mrb_parser_heredoc_info parser_heredoc_info;
32
33static int yyparse(parser_state *p);
34static int yylex(void *lval, parser_state *p);
35static void yyerror(parser_state *p, const char *s);
36static void yywarn(parser_state *p, const char *s);
37static void yywarning(parser_state *p, const char *s);
38static void backref_error(parser_state *p, node *n);
39static void void_expr_error(parser_state *p, node *n);
40static void tokadd(parser_state *p, int32_t c);
41
42#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
43
44typedef unsigned int stack_type;
45
46#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
47#define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
48#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
49#define BITSTACK_SET_P(stack) ((stack)&1)
50
51#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n))
52#define COND_POP() BITSTACK_POP(p->cond_stack)
53#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack)
54#define COND_P() BITSTACK_SET_P(p->cond_stack)
55
56#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n))
57#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack)
58#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
59#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
60
61#define SET_LINENO(c,n) ((c)->lineno = (n))
62#define NODE_LINENO(c,n) do {\
63 if (n) {\
64 (c)->filename_index = (n)->filename_index;\
65 (c)->lineno = (n)->lineno;\
66 }\
67} while (0)
68
69#define sym(x) ((mrb_sym)(intptr_t)(x))
70#define nsym(x) ((node*)(intptr_t)(x))
71#define nint(x) ((node*)(intptr_t)(x))
72#define intn(x) ((int)(intptr_t)(x))
73
74#define NUM_SUFFIX_R (1<<0)
75#define NUM_SUFFIX_I (1<<1)
76
77static inline mrb_sym
78intern_cstr_gen(parser_state *p, const char *s)
79{
80 return mrb_intern_cstr(p->mrb, s);
81}
82#define intern_cstr(s) intern_cstr_gen(p,(s))
83
84static inline mrb_sym
85intern_gen(parser_state *p, const char *s, size_t len)
86{
87 return mrb_intern(p->mrb, s, len);
88}
89#define intern(s,len) intern_gen(p,(s),(len))
90
91#define intern_lit(s) mrb_intern_lit(p->mrb, s)
92
93static void
94cons_free_gen(parser_state *p, node *cons)
95{
96 cons->cdr = p->cells;
97 p->cells = cons;
98}
99#define cons_free(c) cons_free_gen(p, (c))
100
101static void*
102parser_palloc(parser_state *p, size_t size)
103{
104 void *m = mrb_pool_alloc(p->pool, size);
105
106 if (!m) {
107 MRB_THROW(p->jmp);
108 }
109 return m;
110}
111
112static node*
113cons_gen(parser_state *p, node *car, node *cdr)
114{
115 node *c;
116
117 if (p->cells) {
118 c = p->cells;
119 p->cells = p->cells->cdr;
120 }
121 else {
122 c = (node *)parser_palloc(p, sizeof(mrb_ast_node));
123 }
124
125 c->car = car;
126 c->cdr = cdr;
127 c->lineno = p->lineno;
128 c->filename_index = p->current_filename_index;
129 /* beginning of next partial file; need to point the previous file */
130 if (p->lineno == 0 && p->current_filename_index > 0) {
131 c->filename_index-- ;
132 }
133 return c;
134}
135#define cons(a,b) cons_gen(p,(a),(b))
136
137static node*
138list1_gen(parser_state *p, node *a)
139{
140 return cons(a, 0);
141}
142#define list1(a) list1_gen(p, (a))
143
144static node*
145list2_gen(parser_state *p, node *a, node *b)
146{
147 return cons(a, cons(b,0));
148}
149#define list2(a,b) list2_gen(p, (a),(b))
150
151static node*
152list3_gen(parser_state *p, node *a, node *b, node *c)
153{
154 return cons(a, cons(b, cons(c,0)));
155}
156#define list3(a,b,c) list3_gen(p, (a),(b),(c))
157
158static node*
159list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
160{
161 return cons(a, cons(b, cons(c, cons(d, 0))));
162}
163#define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
164
165static node*
166list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
167{
168 return cons(a, cons(b, cons(c, cons(d, cons(e, 0)))));
169}
170#define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
171
172static node*
173list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
174{
175 return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
176}
177#define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
178
179static node*
180append_gen(parser_state *p, node *a, node *b)
181{
182 node *c = a;
183
184 if (!a) return b;
185 if (!b) return a;
186 while (c->cdr) {
187 c = c->cdr;
188 }
189 c->cdr = b;
190 return a;
191}
192#define append(a,b) append_gen(p,(a),(b))
193#define push(a,b) append_gen(p,(a),list1(b))
194
195static char*
196parser_strndup(parser_state *p, const char *s, size_t len)
197{
198 char *b = (char *)parser_palloc(p, len+1);
199
200 memcpy(b, s, len);
201 b[len] = '\0';
202 return b;
203}
204#undef strndup
205#define strndup(s,len) parser_strndup(p, s, len)
206
207static char*
208parser_strdup(parser_state *p, const char *s)
209{
210 return parser_strndup(p, s, strlen(s));
211}
212#undef strdup
213#define strdup(s) parser_strdup(p, s)
214
215static void
216dump_int(uint16_t i, char *s)
217{
218 char *p = s;
219 char *t = s;
220
221 while (i > 0) {
222 *p++ = (i % 10)+'0';
223 i /= 10;
224 }
225 if (p == s) *p++ = '0';
226 *p = 0;
227 p--; /* point the last char */
228 while (t < p) {
229 char c = *t;
230 *t++ = *p;
231 *p-- = c;
232 }
233}
234
235/* xxx ----------------------------- */
236
237static node*
238local_switch(parser_state *p)
239{
240 node *prev = p->locals;
241
242 p->locals = cons(0, 0);
243 return prev;
244}
245
246static void
247local_resume(parser_state *p, node *prev)
248{
249 p->locals = prev;
250}
251
252static void
253local_nest(parser_state *p)
254{
255 p->locals = cons(0, p->locals);
256}
257
258static void
259local_unnest(parser_state *p)
260{
261 if (p->locals) {
262 p->locals = p->locals->cdr;
263 }
264}
265
266static mrb_bool
267local_var_p(parser_state *p, mrb_sym sym)
268{
269 node *l = p->locals;
270
271 while (l) {
272 node *n = l->car;
273 while (n) {
274 if (sym(n->car) == sym) return TRUE;
275 n = n->cdr;
276 }
277 l = l->cdr;
278 }
279 return FALSE;
280}
281
282static void
283local_add_f(parser_state *p, mrb_sym sym)
284{
285 if (p->locals) {
286 p->locals->car = push(p->locals->car, nsym(sym));
287 }
288}
289
290static void
291local_add(parser_state *p, mrb_sym sym)
292{
293 if (!local_var_p(p, sym)) {
294 local_add_f(p, sym);
295 }
296}
297
298static void
299local_add_blk(parser_state *p, mrb_sym blk)
300{
301 /* allocate register for block */
302 local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&"));
303}
304
305static void
306local_add_kw(parser_state *p, mrb_sym kwd)
307{
308 /* allocate register for keywords hash */
309 local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**"));
310}
311
312static node*
313locals_node(parser_state *p)
314{
315 return p->locals ? p->locals->car : NULL;
316}
317
318static void
319nvars_nest(parser_state *p)
320{
321 p->nvars = cons(nint(0), p->nvars);
322}
323
324static void
325nvars_block(parser_state *p)
326{
327 p->nvars = cons(nint(-2), p->nvars);
328}
329
330static void
331nvars_unnest(parser_state *p)
332{
333 p->nvars = p->nvars->cdr;
334}
335
336/* (:scope (vars..) (prog...)) */
337static node*
338new_scope(parser_state *p, node *body)
339{
340 return cons((node*)NODE_SCOPE, cons(locals_node(p), body));
341}
342
343/* (:begin prog...) */
344static node*
345new_begin(parser_state *p, node *body)
346{
347 if (body) {
348 return list2((node*)NODE_BEGIN, body);
349 }
350 return cons((node*)NODE_BEGIN, 0);
351}
352
353#define newline_node(n) (n)
354
355/* (:rescue body rescue else) */
356static node*
357new_rescue(parser_state *p, node *body, node *resq, node *els)
358{
359 return list4((node*)NODE_RESCUE, body, resq, els);
360}
361
362static node*
363new_mod_rescue(parser_state *p, node *body, node *resq)
364{
365 return new_rescue(p, body, list1(list3(0, 0, resq)), 0);
366}
367
368/* (:ensure body ensure) */
369static node*
370new_ensure(parser_state *p, node *a, node *b)
371{
372 return cons((node*)NODE_ENSURE, cons(a, cons(0, b)));
373}
374
375/* (:nil) */
376static node*
377new_nil(parser_state *p)
378{
379 return list1((node*)NODE_NIL);
380}
381
382/* (:true) */
383static node*
384new_true(parser_state *p)
385{
386 return list1((node*)NODE_TRUE);
387}
388
389/* (:false) */
390static node*
391new_false(parser_state *p)
392{
393 return list1((node*)NODE_FALSE);
394}
395
396/* (:alias new old) */
397static node*
398new_alias(parser_state *p, mrb_sym a, mrb_sym b)
399{
400 return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
401}
402
403/* (:if cond then else) */
404static node*
405new_if(parser_state *p, node *a, node *b, node *c)
406{
407 void_expr_error(p, a);
408 return list4((node*)NODE_IF, a, b, c);
409}
410
411/* (:unless cond then else) */
412static node*
413new_unless(parser_state *p, node *a, node *b, node *c)
414{
415 void_expr_error(p, a);
416 return list4((node*)NODE_IF, a, c, b);
417}
418
419/* (:while cond body) */
420static node*
421new_while(parser_state *p, node *a, node *b)
422{
423 void_expr_error(p, a);
424 return cons((node*)NODE_WHILE, cons(a, b));
425}
426
427/* (:until cond body) */
428static node*
429new_until(parser_state *p, node *a, node *b)
430{
431 void_expr_error(p, a);
432 return cons((node*)NODE_UNTIL, cons(a, b));
433}
434
435/* (:for var obj body) */
436static node*
437new_for(parser_state *p, node *v, node *o, node *b)
438{
439 void_expr_error(p, o);
440 return list4((node*)NODE_FOR, v, o, b);
441}
442
443/* (:case a ((when ...) body) ((when...) body)) */
444static node*
445new_case(parser_state *p, node *a, node *b)
446{
447 node *n = list2((node*)NODE_CASE, a);
448 node *n2 = n;
449
450 void_expr_error(p, a);
451 while (n2->cdr) {
452 n2 = n2->cdr;
453 }
454 n2->cdr = b;
455 return n;
456}
457
458/* (:postexe a) */
459static node*
460new_postexe(parser_state *p, node *a)
461{
462 return cons((node*)NODE_POSTEXE, a);
463}
464
465/* (:self) */
466static node*
467new_self(parser_state *p)
468{
469 return list1((node*)NODE_SELF);
470}
471
472/* (:call a b c) */
473static node*
474new_call(parser_state *p, node *a, mrb_sym b, node *c, int pass)
475{
476 node *n = list4(nint(pass?NODE_CALL:NODE_SCALL), a, nsym(b), c);
477 void_expr_error(p, a);
478 NODE_LINENO(n, a);
479 return n;
480}
481
482/* (:fcall self mid args) */
483static node*
484new_fcall(parser_state *p, mrb_sym b, node *c)
485{
486 node *n = new_self(p);
487 NODE_LINENO(n, c);
488 n = list4((node*)NODE_FCALL, n, nsym(b), c);
489 NODE_LINENO(n, c);
490 return n;
491}
492
493/* (:super . c) */
494static node*
495new_super(parser_state *p, node *c)
496{
497 return cons((node*)NODE_SUPER, c);
498}
499
500/* (:zsuper) */
501static node*
502new_zsuper(parser_state *p)
503{
504 return list1((node*)NODE_ZSUPER);
505}
506
507/* (:yield . c) */
508static node*
509new_yield(parser_state *p, node *c)
510{
511 if (c) {
512 if (c->cdr) {
513 yyerror(p, "both block arg and actual block given");
514 }
515 return cons((node*)NODE_YIELD, c->car);
516 }
517 return cons((node*)NODE_YIELD, 0);
518}
519
520/* (:return . c) */
521static node*
522new_return(parser_state *p, node *c)
523{
524 return cons((node*)NODE_RETURN, c);
525}
526
527/* (:break . c) */
528static node*
529new_break(parser_state *p, node *c)
530{
531 return cons((node*)NODE_BREAK, c);
532}
533
534/* (:next . c) */
535static node*
536new_next(parser_state *p, node *c)
537{
538 return cons((node*)NODE_NEXT, c);
539}
540
541/* (:redo) */
542static node*
543new_redo(parser_state *p)
544{
545 return list1((node*)NODE_REDO);
546}
547
548/* (:retry) */
549static node*
550new_retry(parser_state *p)
551{
552 return list1((node*)NODE_RETRY);
553}
554
555/* (:dot2 a b) */
556static node*
557new_dot2(parser_state *p, node *a, node *b)
558{
559 return cons((node*)NODE_DOT2, cons(a, b));
560}
561
562/* (:dot3 a b) */
563static node*
564new_dot3(parser_state *p, node *a, node *b)
565{
566 return cons((node*)NODE_DOT3, cons(a, b));
567}
568
569/* (:colon2 b c) */
570static node*
571new_colon2(parser_state *p, node *b, mrb_sym c)
572{
573 void_expr_error(p, b);
574 return cons((node*)NODE_COLON2, cons(b, nsym(c)));
575}
576
577/* (:colon3 . c) */
578static node*
579new_colon3(parser_state *p, mrb_sym c)
580{
581 return cons((node*)NODE_COLON3, nsym(c));
582}
583
584/* (:and a b) */
585static node*
586new_and(parser_state *p, node *a, node *b)
587{
588 return cons((node*)NODE_AND, cons(a, b));
589}
590
591/* (:or a b) */
592static node*
593new_or(parser_state *p, node *a, node *b)
594{
595 return cons((node*)NODE_OR, cons(a, b));
596}
597
598/* (:array a...) */
599static node*
600new_array(parser_state *p, node *a)
601{
602 return cons((node*)NODE_ARRAY, a);
603}
604
605/* (:splat . a) */
606static node*
607new_splat(parser_state *p, node *a)
608{
609 return cons((node*)NODE_SPLAT, a);
610}
611
612/* (:hash (k . v) (k . v)...) */
613static node*
614new_hash(parser_state *p, node *a)
615{
616 return cons((node*)NODE_HASH, a);
617}
618
619/* (:kw_hash (k . v) (k . v)...) */
620static node*
621new_kw_hash(parser_state *p, node *a)
622{
623 return cons((node*)NODE_KW_HASH, a);
624}
625
626/* (:sym . a) */
627static node*
628new_sym(parser_state *p, mrb_sym sym)
629{
630 return cons((node*)NODE_SYM, nsym(sym));
631}
632
633static mrb_sym
634new_strsym(parser_state *p, node* str)
635{
636 const char *s = (const char*)str->cdr->car;
637 size_t len = (size_t)str->cdr->cdr;
638
639 return mrb_intern(p->mrb, s, len);
640}
641
642/* (:lvar . a) */
643static node*
644new_lvar(parser_state *p, mrb_sym sym)
645{
646 return cons((node*)NODE_LVAR, nsym(sym));
647}
648
649/* (:gvar . a) */
650static node*
651new_gvar(parser_state *p, mrb_sym sym)
652{
653 return cons((node*)NODE_GVAR, nsym(sym));
654}
655
656/* (:ivar . a) */
657static node*
658new_ivar(parser_state *p, mrb_sym sym)
659{
660 return cons((node*)NODE_IVAR, nsym(sym));
661}
662
663/* (:cvar . a) */
664static node*
665new_cvar(parser_state *p, mrb_sym sym)
666{
667 return cons((node*)NODE_CVAR, nsym(sym));
668}
669
670/* (:nvar . a) */
671static node*
672new_nvar(parser_state *p, int num)
673{
674 int nvars = intn(p->nvars->car);
675
676 p->nvars->car = nint(nvars > num ? nvars : num);
677 return cons((node*)NODE_NVAR, nint(num));
678}
679
680/* (:const . a) */
681static node*
682new_const(parser_state *p, mrb_sym sym)
683{
684 return cons((node*)NODE_CONST, nsym(sym));
685}
686
687/* (:undef a...) */
688static node*
689new_undef(parser_state *p, mrb_sym sym)
690{
691 return list2((node*)NODE_UNDEF, nsym(sym));
692}
693
694/* (:class class super body) */
695static node*
696new_class(parser_state *p, node *c, node *s, node *b)
697{
698 void_expr_error(p, s);
699 return list4((node*)NODE_CLASS, c, s, cons(locals_node(p), b));
700}
701
702/* (:sclass obj body) */
703static node*
704new_sclass(parser_state *p, node *o, node *b)
705{
706 void_expr_error(p, o);
707 return list3((node*)NODE_SCLASS, o, cons(locals_node(p), b));
708}
709
710/* (:module module body) */
711static node*
712new_module(parser_state *p, node *m, node *b)
713{
714 return list3((node*)NODE_MODULE, m, cons(locals_node(p), b));
715}
716
717/* (:def m lv (arg . body)) */
718static node*
719new_def(parser_state *p, mrb_sym m, node *a, node *b)
720{
721 return list5((node*)NODE_DEF, nsym(m), locals_node(p), a, b);
722}
723
724/* (:sdef obj m lv (arg . body)) */
725static node*
726new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
727{
728 void_expr_error(p, o);
729 return list6((node*)NODE_SDEF, o, nsym(m), locals_node(p), a, b);
730}
731
732/* (:arg . sym) */
733static node*
734new_arg(parser_state *p, mrb_sym sym)
735{
736 return cons((node*)NODE_ARG, nsym(sym));
737}
738
739static void
740local_add_margs(parser_state *p, node *n)
741{
742 while (n) {
743 if (n->car->car == (node*)NODE_MASGN) {
744 node *t = n->car->cdr->cdr;
745
746 n->car->cdr->cdr = NULL;
747 while (t) {
748 local_add_f(p, sym(t->car));
749 t = t->cdr;
750 }
751 local_add_margs(p, n->car->cdr->car->car);
752 local_add_margs(p, n->car->cdr->car->cdr->cdr->car);
753 }
754 n = n->cdr;
755 }
756}
757
758static void
759local_add_lv(parser_state *p, node *lv)
760{
761 while (lv) {
762 local_add_f(p, sym(lv->car));
763 lv = lv->cdr;
764 }
765}
766
767/* (m o r m2 tail) */
768/* m: (a b c) */
769/* o: ((a . e1) (b . e2)) */
770/* r: a */
771/* m2: (a b c) */
772/* b: a */
773static node*
774new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail)
775{
776 node *n;
777
778 local_add_margs(p, m);
779 local_add_margs(p, m2);
780 n = cons(m2, tail);
781 n = cons(nsym(rest), n);
782 n = cons(opt, n);
783 while (opt) {
784 /* opt: (sym . (opt . lv)) -> (sym . opt) */
785 local_add_lv(p, opt->car->cdr->cdr);
786 opt->car->cdr = opt->car->cdr->car;
787 opt = opt->cdr;
788 }
789 return cons(m, n);
790}
791
792/* (:args_tail keywords rest_keywords_sym block_sym) */
793static node*
794new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
795{
796 node *k;
797
798 if (kws || kwrest) {
799 local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0);
800 }
801
802 local_add_blk(p, blk);
803
804 /* allocate register for keywords arguments */
805 /* order is for Proc#parameters */
806 for (k = kws; k; k = k->cdr) {
807 if (!k->car->cdr->cdr->car) { /* allocate required keywords */
808 local_add_f(p, sym(k->car->cdr->car));
809 }
810 }
811 for (k = kws; k; k = k->cdr) {
812 if (k->car->cdr->cdr->car) { /* allocate keywords with default */
813 local_add_lv(p, k->car->cdr->cdr->car->cdr);
814 k->car->cdr->cdr->car = k->car->cdr->cdr->car->car;
815 local_add_f(p, sym(k->car->cdr->car));
816 }
817 }
818
819 return list4((node*)NODE_ARGS_TAIL, kws, kwrest, nsym(blk));
820}
821
822/* (:kw_arg kw_sym def_arg) */
823static node*
824new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
825{
826 mrb_assert(kw);
827 return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
828}
829
830/* (:block_arg . a) */
831static node*
832new_block_arg(parser_state *p, node *a)
833{
834 return cons((node*)NODE_BLOCK_ARG, a);
835}
836
837static node*
838setup_numparams(parser_state *p, node *a)
839{
840 int nvars = intn(p->nvars->car);
841 if (nvars > 0) {
842 int i;
843 mrb_sym sym;
844 // m || opt || rest || tail
845 if (a && (a->car || (a->cdr && a->cdr->car) || (a->cdr->cdr && a->cdr->cdr->car) || (a->cdr->cdr->cdr->cdr && a->cdr->cdr->cdr->cdr->car))) {
846 yyerror(p, "ordinary parameter is defined");
847 }
848 else if (p->locals) {
849 /* p->locals should not be NULL unless error happens before the point */
850 node* args = 0;
851 for (i = nvars; i > 0; i--) {
852 char buf[3];
853
854 buf[0] = '_';
855 buf[1] = i+'0';
856 buf[2] = '\0';
857 sym = intern_cstr(buf);
858 args = cons(new_arg(p, sym), args);
859 p->locals->car = cons(nsym(sym), p->locals->car);
860 }
861 a = new_args(p, args, 0, 0, 0, 0);
862 }
863 }
864 return a;
865}
866
867/* (:block arg body) */
868static node*
869new_block(parser_state *p, node *a, node *b)
870{
871 a = setup_numparams(p, a);
872 return list4((node*)NODE_BLOCK, locals_node(p), a, b);
873}
874
875/* (:lambda arg body) */
876static node*
877new_lambda(parser_state *p, node *a, node *b)
878{
879 return list4((node*)NODE_LAMBDA, locals_node(p), a, b);
880}
881
882/* (:asgn lhs rhs) */
883static node*
884new_asgn(parser_state *p, node *a, node *b)
885{
886 void_expr_error(p, b);
887 return cons((node*)NODE_ASGN, cons(a, b));
888}
889
890/* (:masgn mlhs=(pre rest post) mrhs) */
891static node*
892new_masgn(parser_state *p, node *a, node *b)
893{
894 void_expr_error(p, b);
895 return cons((node*)NODE_MASGN, cons(a, b));
896}
897
898/* (:masgn mlhs mrhs) no check */
899static node*
900new_masgn_param(parser_state *p, node *a, node *b)
901{
902 return cons((node*)NODE_MASGN, cons(a, b));
903}
904
905/* (:asgn lhs rhs) */
906static node*
907new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
908{
909 void_expr_error(p, b);
910 return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
911}
912
913static node*
914new_imaginary(parser_state *p, node *imaginary)
915{
916 return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
917}
918
919static node*
920new_rational(parser_state *p, node *rational)
921{
922 return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Rational"), list1(list1(rational)), 1);
923}
924
925/* (:int . i) */
926static node*
927new_int(parser_state *p, const char *s, int base, int suffix)
928{
929 node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base));
930 if (suffix & NUM_SUFFIX_R) {
931 result = new_rational(p, result);
932 }
933 if (suffix & NUM_SUFFIX_I) {
934 result = new_imaginary(p, result);
935 }
936 return result;
937}
938
939#ifndef MRB_WITHOUT_FLOAT
940/* (:float . i) */
941static node*
942new_float(parser_state *p, const char *s, int suffix)
943{
944 node* result = cons((node*)NODE_FLOAT, (node*)strdup(s));
945 if (suffix & NUM_SUFFIX_R) {
946 result = new_rational(p, result);
947 }
948 if (suffix & NUM_SUFFIX_I) {
949 result = new_imaginary(p, result);
950 }
951 return result;
952}
953#endif
954
955/* (:str . (s . len)) */
956static node*
957new_str(parser_state *p, const char *s, size_t len)
958{
959 return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
960}
961
962/* (:dstr . a) */
963static node*
964new_dstr(parser_state *p, node *a)
965{
966 return cons((node*)NODE_DSTR, a);
967}
968
969static int
970string_node_p(node *n)
971{
972 return (int)((enum node_type)(intptr_t)n->car == NODE_STR);
973}
974
975static node*
976composite_string_node(parser_state *p, node *a, node *b)
977{
978 size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
979 char *str = (char*)mrb_pool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
980 memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
981 str[newlen] = '\0';
982 a->car = (node*)str;
983 a->cdr = (node*)newlen;
984 cons_free(b);
985 return a;
986}
987
988static node*
989concat_string(parser_state *p, node *a, node *b)
990{
991 if (string_node_p(a)) {
992 if (string_node_p(b)) {
993 /* a == NODE_STR && b == NODE_STR */
994 composite_string_node(p, a->cdr, b->cdr);
995 cons_free(b);
996 return a;
997 }
998 else {
999 /* a == NODE_STR && b == NODE_DSTR */
1000
1001 if (string_node_p(b->cdr->car)) {
1002 /* a == NODE_STR && b->[NODE_STR, ...] */
1003 composite_string_node(p, a->cdr, b->cdr->car->cdr);
1004 cons_free(b->cdr->car);
1005 b->cdr->car = a;
1006 return b;
1007 }
1008 }
1009 }
1010 else {
1011 node *c; /* last node of a */
1012 for (c = a; c->cdr != NULL; c = c->cdr) ;
1013
1014 if (string_node_p(b)) {
1015 /* a == NODE_DSTR && b == NODE_STR */
1016 if (string_node_p(c->car)) {
1017 /* a->[..., NODE_STR] && b == NODE_STR */
1018 composite_string_node(p, c->car->cdr, b->cdr);
1019 cons_free(b);
1020 return a;
1021 }
1022
1023 push(a, b);
1024 return a;
1025 }
1026 else {
1027 /* a == NODE_DSTR && b == NODE_DSTR */
1028 if (string_node_p(c->car) && string_node_p(b->cdr->car)) {
1029 /* a->[..., NODE_STR] && b->[NODE_STR, ...] */
1030 node *d = b->cdr;
1031 cons_free(b);
1032 composite_string_node(p, c->car->cdr, d->car->cdr);
1033 cons_free(d->car);
1034 c->cdr = d->cdr;
1035 cons_free(d);
1036 return a;
1037 }
1038 else {
1039 c->cdr = b->cdr;
1040 cons_free(b);
1041 return a;
1042 }
1043 }
1044 }
1045
1046 return new_dstr(p, list2(a, b));
1047}
1048
1049/* (:str . (s . len)) */
1050static node*
1051new_xstr(parser_state *p, const char *s, int len)
1052{
1053 return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), nint(len)));
1054}
1055
1056/* (:xstr . a) */
1057static node*
1058new_dxstr(parser_state *p, node *a)
1059{
1060 return cons((node*)NODE_DXSTR, a);
1061}
1062
1063/* (:dsym . a) */
1064static node*
1065new_dsym(parser_state *p, node *a)
1066{
1067 return cons((node*)NODE_DSYM, a);
1068}
1069
1070/* (:regx . (s . (opt . enc))) */
1071static node*
1072new_regx(parser_state *p, const char *p1, const char* p2, const char* p3)
1073{
1074 return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3)));
1075}
1076
1077/* (:dregx . (a . b)) */
1078static node*
1079new_dregx(parser_state *p, node *a, node *b)
1080{
1081 return cons((node*)NODE_DREGX, cons(a, b));
1082}
1083
1084/* (:backref . n) */
1085static node*
1086new_back_ref(parser_state *p, int n)
1087{
1088 return cons((node*)NODE_BACK_REF, nint(n));
1089}
1090
1091/* (:nthref . n) */
1092static node*
1093new_nth_ref(parser_state *p, int n)
1094{
1095 return cons((node*)NODE_NTH_REF, nint(n));
1096}
1097
1098/* (:heredoc . a) */
1099static node*
1100new_heredoc(parser_state *p)
1101{
1102 parser_heredoc_info *inf = (parser_heredoc_info *)parser_palloc(p, sizeof(parser_heredoc_info));
1103 return cons((node*)NODE_HEREDOC, (node*)inf);
1104}
1105
1106static void
1107new_bv(parser_state *p, mrb_sym id)
1108{
1109}
1110
1111static node*
1112new_literal_delim(parser_state *p)
1113{
1114 return cons((node*)NODE_LITERAL_DELIM, 0);
1115}
1116
1117/* (:words . a) */
1118static node*
1119new_words(parser_state *p, node *a)
1120{
1121 return cons((node*)NODE_WORDS, a);
1122}
1123
1124/* (:symbols . a) */
1125static node*
1126new_symbols(parser_state *p, node *a)
1127{
1128 return cons((node*)NODE_SYMBOLS, a);
1129}
1130
1131/* xxx ----------------------------- */
1132
1133/* (:call a op) */
1134static node*
1135call_uni_op(parser_state *p, node *recv, const char *m)
1136{
1137 void_expr_error(p, recv);
1138 return new_call(p, recv, intern_cstr(m), 0, 1);
1139}
1140
1141/* (:call a op b) */
1142static node*
1143call_bin_op(parser_state *p, node *recv, const char *m, node *arg1)
1144{
1145 return new_call(p, recv, intern_cstr(m), list1(list1(arg1)), 1);
1146}
1147
1148static void
1149args_with_block(parser_state *p, node *a, node *b)
1150{
1151 if (b) {
1152 if (a->cdr) {
1153 yyerror(p, "both block arg and actual block given");
1154 }
1155 a->cdr = b;
1156 }
1157}
1158
1159static void
1160call_with_block(parser_state *p, node *a, node *b)
1161{
1162 node *n;
1163
1164 switch ((enum node_type)intn(a->car)) {
1165 case NODE_SUPER:
1166 case NODE_ZSUPER:
1167 if (!a->cdr) a->cdr = cons(0, b);
1168 else {
1169 args_with_block(p, a->cdr, b);
1170 }
1171 break;
1172 case NODE_CALL:
1173 case NODE_FCALL:
1174 case NODE_SCALL:
1175 n = a->cdr->cdr->cdr;
1176 if (!n->car) n->car = cons(0, b);
1177 else {
1178 args_with_block(p, n->car, b);
1179 }
1180 break;
1181 default:
1182 break;
1183 }
1184}
1185
1186static node*
1187negate_lit(parser_state *p, node *n)
1188{
1189 return cons((node*)NODE_NEGATE, n);
1190}
1191
1192static node*
1193cond(node *n)
1194{
1195 return n;
1196}
1197
1198static node*
1199ret_args(parser_state *p, node *n)
1200{
1201 if (n->cdr) {
1202 yyerror(p, "block argument should not be given");
1203 return NULL;
1204 }
1205 if (!n->car->cdr) return n->car->car;
1206 return new_array(p, n->car);
1207}
1208
1209static void
1210assignable(parser_state *p, node *lhs)
1211{
1212 if (intn(lhs->car) == NODE_LVAR) {
1213 local_add(p, sym(lhs->cdr));
1214 }
1215}
1216
1217static node*
1218var_reference(parser_state *p, node *lhs)
1219{
1220 node *n;
1221
1222 if (intn(lhs->car) == NODE_LVAR) {
1223 if (!local_var_p(p, sym(lhs->cdr))) {
1224 n = new_fcall(p, sym(lhs->cdr), 0);
1225 cons_free(lhs);
1226 return n;
1227 }
1228 }
1229
1230 return lhs;
1231}
1232
1233typedef enum mrb_string_type string_type;
1234
1235static node*
1236new_strterm(parser_state *p, string_type type, int term, int paren)
1237{
1238 return cons(nint(type), cons((node*)0, cons(nint(paren), nint(term))));
1239}
1240
1241static void
1242end_strterm(parser_state *p)
1243{
1244 cons_free(p->lex_strterm->cdr->cdr);
1245 cons_free(p->lex_strterm->cdr);
1246 cons_free(p->lex_strterm);
1247 p->lex_strterm = NULL;
1248}
1249
1250static parser_heredoc_info *
1251parsing_heredoc_inf(parser_state *p)
1252{
1253 node *nd = p->parsing_heredoc;
1254 if (nd == NULL)
1255 return NULL;
1256 /* mrb_assert(nd->car->car == NODE_HEREDOC); */
1257 return (parser_heredoc_info*)nd->car->cdr;
1258}
1259
1260static void
1261heredoc_treat_nextline(parser_state *p)
1262{
1263 if (p->heredocs_from_nextline == NULL)
1264 return;
1265 if (p->parsing_heredoc == NULL) {
1266 node *n;
1267 p->parsing_heredoc = p->heredocs_from_nextline;
1268 p->lex_strterm_before_heredoc = p->lex_strterm;
1269 p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
1270 n = p->all_heredocs;
1271 if (n) {
1272 while (n->cdr)
1273 n = n->cdr;
1274 n->cdr = p->parsing_heredoc;
1275 }
1276 else {
1277 p->all_heredocs = p->parsing_heredoc;
1278 }
1279 }
1280 else {
1281 node *n, *m;
1282 m = p->heredocs_from_nextline;
1283 while (m->cdr)
1284 m = m->cdr;
1285 n = p->all_heredocs;
1286 mrb_assert(n != NULL);
1287 if (n == p->parsing_heredoc) {
1288 m->cdr = n;
1289 p->all_heredocs = p->heredocs_from_nextline;
1290 p->parsing_heredoc = p->heredocs_from_nextline;
1291 }
1292 else {
1293 while (n->cdr != p->parsing_heredoc) {
1294 n = n->cdr;
1295 mrb_assert(n != NULL);
1296 }
1297 m->cdr = n->cdr;
1298 n->cdr = p->heredocs_from_nextline;
1299 p->parsing_heredoc = p->heredocs_from_nextline;
1300 }
1301 }
1302 p->heredocs_from_nextline = NULL;
1303}
1304
1305static void
1306heredoc_end(parser_state *p)
1307{
1308 p->parsing_heredoc = p->parsing_heredoc->cdr;
1309 if (p->parsing_heredoc == NULL) {
1310 p->lstate = EXPR_BEG;
1311 end_strterm(p);
1312 p->lex_strterm = p->lex_strterm_before_heredoc;
1313 p->lex_strterm_before_heredoc = NULL;
1314 }
1315 else {
1316 /* next heredoc */
1317 p->lex_strterm->car = nint(parsing_heredoc_inf(p)->type);
1318 }
1319}
1320#define is_strterm_type(p,str_func) (intn((p)->lex_strterm->car) & (str_func))
1321
1322/* xxx ----------------------------- */
1323
1324%}
1325
1326%pure-parser
1327%parse-param {parser_state *p}
1328%lex-param {parser_state *p}
1329
1330%union {
1331 node *nd;
1332 mrb_sym id;
1333 int num;
1334 stack_type stack;
1335 const struct vtable *vars;
1336}
1337
1338%token <num>
1339 keyword_class
1340 keyword_module
1341 keyword_def
1342 keyword_begin
1343 keyword_if
1344 keyword_unless
1345 keyword_while
1346 keyword_until
1347 keyword_for
1348
1349%token
1350 keyword_undef
1351 keyword_rescue
1352 keyword_ensure
1353 keyword_end
1354 keyword_then
1355 keyword_elsif
1356 keyword_else
1357 keyword_case
1358 keyword_when
1359 keyword_break
1360 keyword_next
1361 keyword_redo
1362 keyword_retry
1363 keyword_in
1364 keyword_do
1365 keyword_do_cond
1366 keyword_do_block
1367 keyword_do_LAMBDA
1368 keyword_return
1369 keyword_yield
1370 keyword_super
1371 keyword_self
1372 keyword_nil
1373 keyword_true
1374 keyword_false
1375 keyword_and
1376 keyword_or
1377 keyword_not
1378 modifier_if
1379 modifier_unless
1380 modifier_while
1381 modifier_until
1382 modifier_rescue
1383 keyword_alias
1384 keyword_BEGIN
1385 keyword_END
1386 keyword__LINE__
1387 keyword__FILE__
1388 keyword__ENCODING__
1389
1390%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL_TAG
1391%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
1392%token <nd> tSTRING tSTRING_PART tSTRING_MID
1393%token <nd> tNTH_REF tBACK_REF
1394%token <num> tREGEXP_END
1395%token <num> tNUMPARAM
1396
1397%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
1398%type <nd> literal numeric cpath symbol
1399%type <nd> top_compstmt top_stmts top_stmt
1400%type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
1401%type <nd> expr_value arg_rhs primary_value
1402%type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
1403%type <nd> args call_args opt_call_args
1404%type <nd> paren_args opt_paren_args variable
1405%type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
1406%type <nd> command_asgn command_rhs mrhs superclass block_call block_command
1407%type <nd> f_block_optarg f_block_opt
1408%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_margs
1409%type <nd> assoc_list assocs assoc undef_list backref for_var
1410%type <nd> block_param opt_block_param block_param_def f_opt
1411%type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
1412%type <nd> brace_block cmd_brace_block do_block lhs none f_bad_arg
1413%type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
1414%type <id> fsym sym basic_symbol operation operation2 operation3
1415%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_opt_asgn
1416%type <nd> heredoc words symbols
1417%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
1418
1419%type <nd> args_tail opt_args_tail f_kwarg f_kw f_kwrest
1420%type <nd> f_block_kwarg f_block_kw block_args_tail opt_block_args_tail
1421%type <id> f_label
1422
1423%token tUPLUS /* unary+ */
1424%token tUMINUS /* unary- */
1425%token tPOW /* ** */
1426%token tCMP /* <=> */
1427%token tEQ /* == */
1428%token tEQQ /* === */
1429%token tNEQ /* != */
1430%token tGEQ /* >= */
1431%token tLEQ /* <= */
1432%token tANDOP tOROP /* && and || */
1433%token tMATCH tNMATCH /* =~ and !~ */
1434%token tDOT2 tDOT3 /* .. and ... */
1435%token tAREF tASET /* [] and []= */
1436%token tLSHFT tRSHFT /* << and >> */
1437%token tCOLON2 /* :: */
1438%token tCOLON3 /* :: at EXPR_BEG */
1439%token <id> tOP_ASGN /* +=, -= etc. */
1440%token tASSOC /* => */
1441%token tLPAREN /* ( */
1442%token tLPAREN_ARG /* ( */
1443%token tRPAREN /* ) */
1444%token tLBRACK /* [ */
1445%token tLBRACE /* { */
1446%token tLBRACE_ARG /* { */
1447%token tSTAR /* * */
1448%token tDSTAR /* ** */
1449%token tAMPER /* & */
1450%token tLAMBDA /* -> */
1451%token tANDDOT /* &. */
1452%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
1453%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
1454%token <nd> tHEREDOC_BEG /* <<, <<- */
1455%token tHEREDOC_END tLITERAL_DELIM tHD_LITERAL_DELIM
1456%token <nd> tHD_STRING_PART tHD_STRING_MID
1457
1458/*
1459 * precedence table
1460 */
1461
1462%nonassoc tLOWEST
1463%nonassoc tLBRACE_ARG
1464
1465%nonassoc modifier_if modifier_unless modifier_while modifier_until
1466%left keyword_or keyword_and
1467%right keyword_not
1468%right '=' tOP_ASGN
1469%left modifier_rescue
1470%right '?' ':' tLABEL_TAG
1471%nonassoc tDOT2 tDOT3
1472%left tOROP
1473%left tANDOP
1474%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
1475%left '>' tGEQ '<' tLEQ
1476%left '|' '^'
1477%left '&'
1478%left tLSHFT tRSHFT
1479%left '+' '-'
1480%left '*' '/' '%'
1481%right tUMINUS_NUM tUMINUS
1482%right tPOW
1483%right '!' '~' tUPLUS
1484
1485%token tLAST_TOKEN
1486
1487%%
1488program : {
1489 p->lstate = EXPR_BEG;
1490 if (!p->locals) p->locals = cons(0,0);
1491 }
1492 top_compstmt
1493 {
1494 p->tree = new_scope(p, $2);
1495 NODE_LINENO(p->tree, $2);
1496 }
1497 ;
1498
1499top_compstmt : top_stmts opt_terms
1500 {
1501 $$ = $1;
1502 }
1503 ;
1504
1505top_stmts : none
1506 {
1507 $$ = new_begin(p, 0);
1508 }
1509 | top_stmt
1510 {
1511 $$ = new_begin(p, $1);
1512 NODE_LINENO($$, $1);
1513 }
1514 | top_stmts terms top_stmt
1515 {
1516 $$ = push($1, newline_node($3));
1517 }
1518 | error top_stmt
1519 {
1520 $$ = new_begin(p, 0);
1521 }
1522 ;
1523
1524top_stmt : stmt
1525 | keyword_BEGIN
1526 {
1527 $<nd>$ = local_switch(p);
1528 nvars_block(p);
1529 }
1530 '{' top_compstmt '}'
1531 {
1532 yyerror(p, "BEGIN not supported");
1533 local_resume(p, $<nd>2);
1534 nvars_unnest(p);
1535 $$ = 0;
1536 }
1537 ;
1538
1539bodystmt : compstmt
1540 opt_rescue
1541 opt_else
1542 opt_ensure
1543 {
1544 if ($2) {
1545 $$ = new_rescue(p, $1, $2, $3);
1546 NODE_LINENO($$, $1);
1547 }
1548 else if ($3) {
1549 yywarn(p, "else without rescue is useless");
1550 $$ = push($1, $3);
1551 }
1552 else {
1553 $$ = $1;
1554 }
1555 if ($4) {
1556 if ($$) {
1557 $$ = new_ensure(p, $$, $4);
1558 }
1559 else {
1560 $$ = push($4, new_nil(p));
1561 }
1562 }
1563 }
1564 ;
1565
1566compstmt : stmts opt_terms
1567 {
1568 $$ = $1;
1569 }
1570 ;
1571
1572stmts : none
1573 {
1574 $$ = new_begin(p, 0);
1575 }
1576 | stmt
1577 {
1578 $$ = new_begin(p, $1);
1579 NODE_LINENO($$, $1);
1580 }
1581 | stmts terms stmt
1582 {
1583 $$ = push($1, newline_node($3));
1584 }
1585 | error stmt
1586 {
1587 $$ = new_begin(p, $2);
1588 }
1589 ;
1590
1591stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
1592 {
1593 $$ = new_alias(p, $2, $4);
1594 }
1595 | keyword_undef undef_list
1596 {
1597 $$ = $2;
1598 }
1599 | stmt modifier_if expr_value
1600 {
1601 $$ = new_if(p, cond($3), $1, 0);
1602 }
1603 | stmt modifier_unless expr_value
1604 {
1605 $$ = new_unless(p, cond($3), $1, 0);
1606 }
1607 | stmt modifier_while expr_value
1608 {
1609 $$ = new_while(p, cond($3), $1);
1610 }
1611 | stmt modifier_until expr_value
1612 {
1613 $$ = new_until(p, cond($3), $1);
1614 }
1615 | stmt modifier_rescue stmt
1616 {
1617 $$ = new_mod_rescue(p, $1, $3);
1618 }
1619 | keyword_END '{' compstmt '}'
1620 {
1621 yyerror(p, "END not supported");
1622 $$ = new_postexe(p, $3);
1623 }
1624 | command_asgn
1625 | mlhs '=' command_call
1626 {
1627 $$ = new_masgn(p, $1, $3);
1628 }
1629 | lhs '=' mrhs
1630 {
1631 $$ = new_asgn(p, $1, new_array(p, $3));
1632 }
1633 | mlhs '=' arg
1634 {
1635 $$ = new_masgn(p, $1, $3);
1636 }
1637 | mlhs '=' mrhs
1638 {
1639 $$ = new_masgn(p, $1, new_array(p, $3));
1640 }
1641 | expr
1642 ;
1643
1644command_asgn : lhs '=' command_rhs
1645 {
1646 $$ = new_asgn(p, $1, $3);
1647 }
1648 | var_lhs tOP_ASGN command_rhs
1649 {
1650 $$ = new_op_asgn(p, $1, $2, $3);
1651 }
1652 | primary_value '[' opt_call_args ']' tOP_ASGN command_rhs
1653 {
1654 $$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
1655 }
1656 | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
1657 {
1658 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
1659 }
1660 | primary_value call_op tCONSTANT tOP_ASGN command_rhs
1661 {
1662 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
1663 }
1664 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
1665 {
1666 yyerror(p, "constant re-assignment");
1667 $$ = 0;
1668 }
1669 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
1670 {
1671 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
1672 }
1673 | backref tOP_ASGN command_rhs
1674 {
1675 backref_error(p, $1);
1676 $$ = new_begin(p, 0);
1677 }
1678 ;
1679
1680command_rhs : command_call %prec tOP_ASGN
1681 | command_call modifier_rescue stmt
1682 {
1683 $$ = new_mod_rescue(p, $1, $3);
1684 }
1685 | command_asgn
1686 ;
1687
1688
1689expr : command_call
1690 | expr keyword_and expr
1691 {
1692 $$ = new_and(p, $1, $3);
1693 }
1694 | expr keyword_or expr
1695 {
1696 $$ = new_or(p, $1, $3);
1697 }
1698 | keyword_not opt_nl expr
1699 {
1700 $$ = call_uni_op(p, cond($3), "!");
1701 }
1702 | '!' command_call
1703 {
1704 $$ = call_uni_op(p, cond($2), "!");
1705 }
1706 | arg
1707 ;
1708
1709expr_value : expr
1710 {
1711 if (!$1) $$ = new_nil(p);
1712 else {
1713 $$ = $1;
1714 }
1715 }
1716 ;
1717
1718command_call : command
1719 | block_command
1720 ;
1721
1722block_command : block_call
1723 | block_call call_op2 operation2 command_args
1724 {
1725 $$ = new_call(p, $1, $3, $4, $2);
1726 }
1727 ;
1728
1729cmd_brace_block : tLBRACE_ARG
1730 {
1731 local_nest(p);
1732 nvars_nest(p);
1733 }
1734 opt_block_param
1735 compstmt
1736 '}'
1737 {
1738 $$ = new_block(p, $3, $4);
1739 local_unnest(p);
1740 nvars_unnest(p);
1741 }
1742 ;
1743
1744command : operation command_args %prec tLOWEST
1745 {
1746 $$ = new_fcall(p, $1, $2);
1747 }
1748 | operation command_args cmd_brace_block
1749 {
1750 args_with_block(p, $2, $3);
1751 $$ = new_fcall(p, $1, $2);
1752 }
1753 | primary_value call_op operation2 command_args %prec tLOWEST
1754 {
1755 $$ = new_call(p, $1, $3, $4, $2);
1756 }
1757 | primary_value call_op operation2 command_args cmd_brace_block
1758 {
1759 args_with_block(p, $4, $5);
1760 $$ = new_call(p, $1, $3, $4, $2);
1761 }
1762 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
1763 {
1764 $$ = new_call(p, $1, $3, $4, tCOLON2);
1765 }
1766 | primary_value tCOLON2 operation2 command_args cmd_brace_block
1767 {
1768 args_with_block(p, $4, $5);
1769 $$ = new_call(p, $1, $3, $4, tCOLON2);
1770 }
1771 | keyword_super command_args
1772 {
1773 $$ = new_super(p, $2);
1774 }
1775 | keyword_yield command_args
1776 {
1777 $$ = new_yield(p, $2);
1778 }
1779 | keyword_return call_args
1780 {
1781 $$ = new_return(p, ret_args(p, $2));
1782 }
1783 | keyword_break call_args
1784 {
1785 $$ = new_break(p, ret_args(p, $2));
1786 }
1787 | keyword_next call_args
1788 {
1789 $$ = new_next(p, ret_args(p, $2));
1790 }
1791 ;
1792
1793mlhs : mlhs_basic
1794 {
1795 $$ = $1;
1796 }
1797 | tLPAREN mlhs_inner rparen
1798 {
1799 $$ = $2;
1800 }
1801 ;
1802
1803mlhs_inner : mlhs_basic
1804 | tLPAREN mlhs_inner rparen
1805 {
1806 $$ = $2;
1807 }
1808 ;
1809
1810mlhs_basic : mlhs_list
1811 {
1812 $$ = list1($1);
1813 }
1814 | mlhs_list mlhs_item
1815 {
1816 $$ = list1(push($1,$2));
1817 }
1818 | mlhs_list tSTAR mlhs_node
1819 {
1820 $$ = list2($1, $3);
1821 }
1822 | mlhs_list tSTAR mlhs_node ',' mlhs_post
1823 {
1824 $$ = list3($1, $3, $5);
1825 }
1826 | mlhs_list tSTAR
1827 {
1828 $$ = list2($1, new_nil(p));
1829 }
1830 | mlhs_list tSTAR ',' mlhs_post
1831 {
1832 $$ = list3($1, new_nil(p), $4);
1833 }
1834 | tSTAR mlhs_node
1835 {
1836 $$ = list2(0, $2);
1837 }
1838 | tSTAR mlhs_node ',' mlhs_post
1839 {
1840 $$ = list3(0, $2, $4);
1841 }
1842 | tSTAR
1843 {
1844 $$ = list2(0, new_nil(p));
1845 }
1846 | tSTAR ',' mlhs_post
1847 {
1848 $$ = list3(0, new_nil(p), $3);
1849 }
1850 ;
1851
1852mlhs_item : mlhs_node
1853 | tLPAREN mlhs_inner rparen
1854 {
1855 $$ = new_masgn(p, $2, NULL);
1856 }
1857 ;
1858
1859mlhs_list : mlhs_item ','
1860 {
1861 $$ = list1($1);
1862 }
1863 | mlhs_list mlhs_item ','
1864 {
1865 $$ = push($1, $2);
1866 }
1867 ;
1868
1869mlhs_post : mlhs_item
1870 {
1871 $$ = list1($1);
1872 }
1873 | mlhs_list mlhs_item
1874 {
1875 $$ = push($1, $2);
1876 }
1877 ;
1878
1879mlhs_node : variable
1880 {
1881 assignable(p, $1);
1882 }
1883 | primary_value '[' opt_call_args ']'
1884 {
1885 $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
1886 }
1887 | primary_value call_op tIDENTIFIER
1888 {
1889 $$ = new_call(p, $1, $3, 0, $2);
1890 }
1891 | primary_value tCOLON2 tIDENTIFIER
1892 {
1893 $$ = new_call(p, $1, $3, 0, tCOLON2);
1894 }
1895 | primary_value call_op tCONSTANT
1896 {
1897 $$ = new_call(p, $1, $3, 0, $2);
1898 }
1899 | primary_value tCOLON2 tCONSTANT
1900 {
1901 if (p->in_def || p->in_single)
1902 yyerror(p, "dynamic constant assignment");
1903 $$ = new_colon2(p, $1, $3);
1904 }
1905 | tCOLON3 tCONSTANT
1906 {
1907 if (p->in_def || p->in_single)
1908 yyerror(p, "dynamic constant assignment");
1909 $$ = new_colon3(p, $2);
1910 }
1911 | backref
1912 {
1913 backref_error(p, $1);
1914 $$ = 0;
1915 }
1916 ;
1917
1918lhs : variable
1919 {
1920 assignable(p, $1);
1921 }
1922 | primary_value '[' opt_call_args ']'
1923 {
1924 $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
1925 }
1926 | primary_value call_op tIDENTIFIER
1927 {
1928 $$ = new_call(p, $1, $3, 0, $2);
1929 }
1930 | primary_value tCOLON2 tIDENTIFIER
1931 {
1932 $$ = new_call(p, $1, $3, 0, tCOLON2);
1933 }
1934 | primary_value call_op tCONSTANT
1935 {
1936 $$ = new_call(p, $1, $3, 0, $2);
1937 }
1938 | primary_value tCOLON2 tCONSTANT
1939 {
1940 if (p->in_def || p->in_single)
1941 yyerror(p, "dynamic constant assignment");
1942 $$ = new_colon2(p, $1, $3);
1943 }
1944 | tCOLON3 tCONSTANT
1945 {
1946 if (p->in_def || p->in_single)
1947 yyerror(p, "dynamic constant assignment");
1948 $$ = new_colon3(p, $2);
1949 }
1950 | backref
1951 {
1952 backref_error(p, $1);
1953 $$ = 0;
1954 }
1955 | tNUMPARAM
1956 {
1957 yyerror(p, "can't assign to numbered parameter");
1958 }
1959 ;
1960
1961cname : tIDENTIFIER
1962 {
1963 yyerror(p, "class/module name must be CONSTANT");
1964 }
1965 | tCONSTANT
1966 ;
1967
1968cpath : tCOLON3 cname
1969 {
1970 $$ = cons((node*)1, nsym($2));
1971 }
1972 | cname
1973 {
1974 $$ = cons((node*)0, nsym($1));
1975 }
1976 | primary_value tCOLON2 cname
1977 {
1978 void_expr_error(p, $1);
1979 $$ = cons($1, nsym($3));
1980 }
1981 ;
1982
1983fname : tIDENTIFIER
1984 | tCONSTANT
1985 | tFID
1986 | op
1987 {
1988 p->lstate = EXPR_ENDFN;
1989 $$ = $1;
1990 }
1991 | reswords
1992 {
1993 p->lstate = EXPR_ENDFN;
1994 $$ = $<id>1;
1995 }
1996 ;
1997
1998fsym : fname
1999 | basic_symbol
2000 ;
2001
2002undef_list : fsym
2003 {
2004 $$ = new_undef(p, $1);
2005 }
2006 | undef_list ',' {p->lstate = EXPR_FNAME;} fsym
2007 {
2008 $$ = push($1, nsym($4));
2009 }
2010 ;
2011
2012op : '|' { $$ = intern_lit("|"); }
2013 | '^' { $$ = intern_lit("^"); }
2014 | '&' { $$ = intern_lit("&"); }
2015 | tCMP { $$ = intern_lit("<=>"); }
2016 | tEQ { $$ = intern_lit("=="); }
2017 | tEQQ { $$ = intern_lit("==="); }
2018 | tMATCH { $$ = intern_lit("=~"); }
2019 | tNMATCH { $$ = intern_lit("!~"); }
2020 | '>' { $$ = intern_lit(">"); }
2021 | tGEQ { $$ = intern_lit(">="); }
2022 | '<' { $$ = intern_lit("<"); }
2023 | tLEQ { $$ = intern_lit("<="); }
2024 | tNEQ { $$ = intern_lit("!="); }
2025 | tLSHFT { $$ = intern_lit("<<"); }
2026 | tRSHFT { $$ = intern_lit(">>"); }
2027 | '+' { $$ = intern_lit("+"); }
2028 | '-' { $$ = intern_lit("-"); }
2029 | '*' { $$ = intern_lit("*"); }
2030 | tSTAR { $$ = intern_lit("*"); }
2031 | '/' { $$ = intern_lit("/"); }
2032 | '%' { $$ = intern_lit("%"); }
2033 | tPOW { $$ = intern_lit("**"); }
2034 | tDSTAR { $$ = intern_lit("**"); }
2035 | '!' { $$ = intern_lit("!"); }
2036 | '~' { $$ = intern_lit("~"); }
2037 | tUPLUS { $$ = intern_lit("+@"); }
2038 | tUMINUS { $$ = intern_lit("-@"); }
2039 | tAREF { $$ = intern_lit("[]"); }
2040 | tASET { $$ = intern_lit("[]="); }
2041 | '`' { $$ = intern_lit("`"); }
2042 ;
2043
2044reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
2045 | keyword_BEGIN | keyword_END
2046 | keyword_alias | keyword_and | keyword_begin
2047 | keyword_break | keyword_case | keyword_class | keyword_def
2048 | keyword_do | keyword_else | keyword_elsif
2049 | keyword_end | keyword_ensure | keyword_false
2050 | keyword_for | keyword_in | keyword_module | keyword_next
2051 | keyword_nil | keyword_not | keyword_or | keyword_redo
2052 | keyword_rescue | keyword_retry | keyword_return | keyword_self
2053 | keyword_super | keyword_then | keyword_true | keyword_undef
2054 | keyword_when | keyword_yield | keyword_if | keyword_unless
2055 | keyword_while | keyword_until
2056 ;
2057
2058arg : lhs '=' arg_rhs
2059 {
2060 $$ = new_asgn(p, $1, $3);
2061 }
2062 | var_lhs tOP_ASGN arg_rhs
2063 {
2064 $$ = new_op_asgn(p, $1, $2, $3);
2065 }
2066 | primary_value '[' opt_call_args ']' tOP_ASGN arg_rhs
2067 {
2068 $$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
2069 }
2070 | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
2071 {
2072 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
2073 }
2074 | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
2075 {
2076 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
2077 }
2078 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
2079 {
2080 $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
2081 }
2082 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
2083 {
2084 yyerror(p, "constant re-assignment");
2085 $$ = new_begin(p, 0);
2086 }
2087 | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
2088 {
2089 yyerror(p, "constant re-assignment");
2090 $$ = new_begin(p, 0);
2091 }
2092 | backref tOP_ASGN arg_rhs
2093 {
2094 backref_error(p, $1);
2095 $$ = new_begin(p, 0);
2096 }
2097 | arg tDOT2 arg
2098 {
2099 $$ = new_dot2(p, $1, $3);
2100 }
2101 | arg tDOT3 arg
2102 {
2103 $$ = new_dot3(p, $1, $3);
2104 }
2105 | arg '+' arg
2106 {
2107 $$ = call_bin_op(p, $1, "+", $3);
2108 }
2109 | arg '-' arg
2110 {
2111 $$ = call_bin_op(p, $1, "-", $3);
2112 }
2113 | arg '*' arg
2114 {
2115 $$ = call_bin_op(p, $1, "*", $3);
2116 }
2117 | arg '/' arg
2118 {
2119 $$ = call_bin_op(p, $1, "/", $3);
2120 }
2121 | arg '%' arg
2122 {
2123 $$ = call_bin_op(p, $1, "%", $3);
2124 }
2125 | arg tPOW arg
2126 {
2127 $$ = call_bin_op(p, $1, "**", $3);
2128 }
2129 | tUMINUS_NUM tINTEGER tPOW arg
2130 {
2131 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
2132 }
2133 | tUMINUS_NUM tFLOAT tPOW arg
2134 {
2135 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
2136 }
2137 | tUPLUS arg
2138 {
2139 $$ = call_uni_op(p, $2, "+@");
2140 }
2141 | tUMINUS arg
2142 {
2143 $$ = call_uni_op(p, $2, "-@");
2144 }
2145 | arg '|' arg
2146 {
2147 $$ = call_bin_op(p, $1, "|", $3);
2148 }
2149 | arg '^' arg
2150 {
2151 $$ = call_bin_op(p, $1, "^", $3);
2152 }
2153 | arg '&' arg
2154 {
2155 $$ = call_bin_op(p, $1, "&", $3);
2156 }
2157 | arg tCMP arg
2158 {
2159 $$ = call_bin_op(p, $1, "<=>", $3);
2160 }
2161 | arg '>' arg
2162 {
2163 $$ = call_bin_op(p, $1, ">", $3);
2164 }
2165 | arg tGEQ arg
2166 {
2167 $$ = call_bin_op(p, $1, ">=", $3);
2168 }
2169 | arg '<' arg
2170 {
2171 $$ = call_bin_op(p, $1, "<", $3);
2172 }
2173 | arg tLEQ arg
2174 {
2175 $$ = call_bin_op(p, $1, "<=", $3);
2176 }
2177 | arg tEQ arg
2178 {
2179 $$ = call_bin_op(p, $1, "==", $3);
2180 }
2181 | arg tEQQ arg
2182 {
2183 $$ = call_bin_op(p, $1, "===", $3);
2184 }
2185 | arg tNEQ arg
2186 {
2187 $$ = call_bin_op(p, $1, "!=", $3);
2188 }
2189 | arg tMATCH arg
2190 {
2191 $$ = call_bin_op(p, $1, "=~", $3);
2192 }
2193 | arg tNMATCH arg
2194 {
2195 $$ = call_bin_op(p, $1, "!~", $3);
2196 }
2197 | '!' arg
2198 {
2199 $$ = call_uni_op(p, cond($2), "!");
2200 }
2201 | '~' arg
2202 {
2203 $$ = call_uni_op(p, cond($2), "~");
2204 }
2205 | arg tLSHFT arg
2206 {
2207 $$ = call_bin_op(p, $1, "<<", $3);
2208 }
2209 | arg tRSHFT arg
2210 {
2211 $$ = call_bin_op(p, $1, ">>", $3);
2212 }
2213 | arg tANDOP arg
2214 {
2215 $$ = new_and(p, $1, $3);
2216 }
2217 | arg tOROP arg
2218 {
2219 $$ = new_or(p, $1, $3);
2220 }
2221 | arg '?' arg opt_nl ':' arg
2222 {
2223 $$ = new_if(p, cond($1), $3, $6);
2224 }
2225 | arg '?' arg opt_nl tLABEL_TAG arg
2226 {
2227 $$ = new_if(p, cond($1), $3, $6);
2228 }
2229 | primary
2230 {
2231 $$ = $1;
2232 }
2233 ;
2234
2235aref_args : none
2236 | args trailer
2237 {
2238 $$ = $1;
2239 NODE_LINENO($$, $1);
2240 }
2241 | args comma assocs trailer
2242 {
2243 $$ = push($1, new_kw_hash(p, $3));
2244 }
2245 | assocs trailer
2246 {
2247 $$ = cons(new_kw_hash(p, $1), 0);
2248 NODE_LINENO($$, $1);
2249 }
2250 ;
2251
2252arg_rhs : arg %prec tOP_ASGN
2253 {
2254 $$ = $1;
2255 }
2256 | arg modifier_rescue arg
2257 {
2258 void_expr_error(p, $1);
2259 void_expr_error(p, $3);
2260 $$ = new_mod_rescue(p, $1, $3);
2261 }
2262 ;
2263
2264paren_args : '(' opt_call_args ')'
2265 {
2266 $$ = $2;
2267 }
2268 ;
2269
2270opt_paren_args : none
2271 | paren_args
2272 ;
2273
2274opt_call_args : none
2275 | call_args opt_terms
2276 | args comma
2277 {
2278 $$ = cons($1,0);
2279 NODE_LINENO($$, $1);
2280 }
2281 | args comma assocs comma
2282 {
2283 $$ = cons(push($1, new_kw_hash(p, $3)), 0);
2284 NODE_LINENO($$, $1);
2285 }
2286 | assocs comma
2287 {
2288 $$ = cons(list1(new_kw_hash(p, $1)), 0);
2289 NODE_LINENO($$, $1);
2290 }
2291 ;
2292
2293call_args : command
2294 {
2295 void_expr_error(p, $1);
2296 $$ = cons(list1($1), 0);
2297 NODE_LINENO($$, $1);
2298 }
2299 | args opt_block_arg
2300 {
2301 $$ = cons($1, $2);
2302 NODE_LINENO($$, $1);
2303 }
2304 | assocs opt_block_arg
2305 {
2306 $$ = cons(list1(new_kw_hash(p, $1)), $2);
2307 NODE_LINENO($$, $1);
2308 }
2309 | args comma assocs opt_block_arg
2310 {
2311 $$ = cons(push($1, new_kw_hash(p, $3)), $4);
2312 NODE_LINENO($$, $1);
2313 }
2314 | block_arg
2315 {
2316 $$ = cons(0, $1);
2317 NODE_LINENO($$, $1);
2318 }
2319 ;
2320
2321command_args : {
2322 $<stack>$ = p->cmdarg_stack;
2323 CMDARG_PUSH(1);
2324 }
2325 call_args
2326 {
2327 p->cmdarg_stack = $<stack>1;
2328 $$ = $2;
2329 }
2330 ;
2331
2332block_arg : tAMPER arg
2333 {
2334 $$ = new_block_arg(p, $2);
2335 }
2336 ;
2337
2338opt_block_arg : comma block_arg
2339 {
2340 $$ = $2;
2341 }
2342 | none
2343 {
2344 $$ = 0;
2345 }
2346 ;
2347
2348comma : ','
2349 | ',' opt_nl heredoc_bodies
2350 ;
2351
2352args : arg
2353 {
2354 void_expr_error(p, $1);
2355 $$ = cons($1, 0);
2356 NODE_LINENO($$, $1);
2357 }
2358 | tSTAR arg
2359 {
2360 void_expr_error(p, $2);
2361 $$ = cons(new_splat(p, $2), 0);
2362 NODE_LINENO($$, $2);
2363 }
2364 | args comma arg
2365 {
2366 void_expr_error(p, $3);
2367 $$ = push($1, $3);
2368 }
2369 | args comma tSTAR arg
2370 {
2371 void_expr_error(p, $4);
2372 $$ = push($1, new_splat(p, $4));
2373 }
2374 ;
2375
2376mrhs : args comma arg
2377 {
2378 void_expr_error(p, $3);
2379 $$ = push($1, $3);
2380 }
2381 | args comma tSTAR arg
2382 {
2383 void_expr_error(p, $4);
2384 $$ = push($1, new_splat(p, $4));
2385 }
2386 | tSTAR arg
2387 {
2388 void_expr_error(p, $2);
2389 $$ = list1(new_splat(p, $2));
2390 }
2391 ;
2392
2393primary : literal
2394 | string
2395 | xstring
2396 | regexp
2397 | heredoc
2398 | var_ref
2399 | backref
2400 | tNUMPARAM
2401 {
2402 $$ = new_nvar(p, $1);
2403 }
2404 | tFID
2405 {
2406 $$ = new_fcall(p, $1, 0);
2407 }
2408 | keyword_begin
2409 {
2410 $<stack>$ = p->cmdarg_stack;
2411 p->cmdarg_stack = 0;
2412 }
2413 bodystmt
2414 keyword_end
2415 {
2416 p->cmdarg_stack = $<stack>2;
2417 $$ = $3;
2418 }
2419 | tLPAREN_ARG
2420 {
2421 $<stack>$ = p->cmdarg_stack;
2422 p->cmdarg_stack = 0;
2423 }
2424 stmt {p->lstate = EXPR_ENDARG;} rparen
2425 {
2426 p->cmdarg_stack = $<stack>2;
2427 $$ = $3;
2428 }
2429 | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
2430 {
2431 $$ = new_nil(p);
2432 }
2433 | tLPAREN compstmt ')'
2434 {
2435 $$ = $2;
2436 }
2437 | primary_value tCOLON2 tCONSTANT
2438 {
2439 $$ = new_colon2(p, $1, $3);
2440 }
2441 | tCOLON3 tCONSTANT
2442 {
2443 $$ = new_colon3(p, $2);
2444 }
2445 | tLBRACK aref_args ']'
2446 {
2447 $$ = new_array(p, $2);
2448 NODE_LINENO($$, $2);
2449 }
2450 | tLBRACE assoc_list '}'
2451 {
2452 $$ = new_hash(p, $2);
2453 NODE_LINENO($$, $2);
2454 }
2455 | keyword_return
2456 {
2457 $$ = new_return(p, 0);
2458 }
2459 | keyword_yield opt_paren_args
2460 {
2461 $$ = new_yield(p, $2);
2462 }
2463 | keyword_not '(' expr rparen
2464 {
2465 $$ = call_uni_op(p, cond($3), "!");
2466 }
2467 | keyword_not '(' rparen
2468 {
2469 $$ = call_uni_op(p, new_nil(p), "!");
2470 }
2471 | operation brace_block
2472 {
2473 $$ = new_fcall(p, $1, cons(0, $2));
2474 }
2475 | method_call
2476 | method_call brace_block
2477 {
2478 call_with_block(p, $1, $2);
2479 $$ = $1;
2480 }
2481 | tLAMBDA
2482 {
2483 local_nest(p);
2484 $<num>$ = p->lpar_beg;
2485 p->lpar_beg = ++p->paren_nest;
2486 }
2487 f_larglist
2488 {
2489 $<stack>$ = p->cmdarg_stack;
2490 p->cmdarg_stack = 0;
2491 }
2492 lambda_body
2493 {
2494 p->lpar_beg = $<num>2;
2495 $$ = new_lambda(p, $3, $5);
2496 local_unnest(p);
2497 p->cmdarg_stack = $<stack>4;
2498 CMDARG_LEXPOP();
2499 }
2500 | keyword_if expr_value then
2501 compstmt
2502 if_tail
2503 keyword_end
2504 {
2505 $$ = new_if(p, cond($2), $4, $5);
2506 SET_LINENO($$, $1);
2507 }
2508 | keyword_unless expr_value then
2509 compstmt
2510 opt_else
2511 keyword_end
2512 {
2513 $$ = new_unless(p, cond($2), $4, $5);
2514 SET_LINENO($$, $1);
2515 }
2516 | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();}
2517 compstmt
2518 keyword_end
2519 {
2520 $$ = new_while(p, cond($3), $6);
2521 SET_LINENO($$, $1);
2522 }
2523 | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();}
2524 compstmt
2525 keyword_end
2526 {
2527 $$ = new_until(p, cond($3), $6);
2528 SET_LINENO($$, $1);
2529 }
2530 | keyword_case expr_value opt_terms
2531 case_body
2532 keyword_end
2533 {
2534 $$ = new_case(p, $2, $4);
2535 }
2536 | keyword_case opt_terms case_body keyword_end
2537 {
2538 $$ = new_case(p, 0, $3);
2539 }
2540 | keyword_for for_var keyword_in
2541 {COND_PUSH(1);}
2542 expr_value do
2543 {COND_POP();}
2544 compstmt
2545 keyword_end
2546 {
2547 $$ = new_for(p, $2, $5, $8);
2548 SET_LINENO($$, $1);
2549 }
2550 | keyword_class
2551 cpath superclass
2552 {
2553 if (p->in_def || p->in_single)
2554 yyerror(p, "class definition in method body");
2555 $<nd>$ = local_switch(p);
2556 nvars_block(p);
2557 }
2558 bodystmt
2559 keyword_end
2560 {
2561 $$ = new_class(p, $2, $3, $5);
2562 SET_LINENO($$, $1);
2563 local_resume(p, $<nd>4);
2564 nvars_unnest(p);
2565 }
2566 | keyword_class
2567 tLSHFT expr
2568 {
2569 $<num>$ = p->in_def;
2570 p->in_def = 0;
2571 }
2572 term
2573 {
2574 $<nd>$ = cons(local_switch(p), nint(p->in_single));
2575 nvars_block(p);
2576 p->in_single = 0;
2577 }
2578 bodystmt
2579 keyword_end
2580 {
2581 $$ = new_sclass(p, $3, $7);
2582 SET_LINENO($$, $1);
2583 local_resume(p, $<nd>6->car);
2584 nvars_unnest(p);
2585 p->in_def = $<num>4;
2586 p->in_single = intn($<nd>6->cdr);
2587 }
2588 | keyword_module
2589 cpath
2590 {
2591 if (p->in_def || p->in_single)
2592 yyerror(p, "module definition in method body");
2593 $<nd>$ = local_switch(p);
2594 nvars_block(p);
2595 }
2596 bodystmt
2597 keyword_end
2598 {
2599 $$ = new_module(p, $2, $4);
2600 SET_LINENO($$, $1);
2601 local_resume(p, $<nd>3);
2602 nvars_unnest(p);
2603 }
2604 | keyword_def fname
2605 {
2606 $<stack>$ = p->cmdarg_stack;
2607 p->cmdarg_stack = 0;
2608 }
2609 {
2610 p->in_def++;
2611 $<nd>$ = local_switch(p);
2612 nvars_block(p);
2613 }
2614 f_arglist
2615 bodystmt
2616 keyword_end
2617 {
2618 $$ = new_def(p, $2, $5, $6);
2619 SET_LINENO($$, $1);
2620 local_resume(p, $<nd>4);
2621 nvars_unnest(p);
2622 p->in_def--;
2623 p->cmdarg_stack = $<stack>3;
2624 }
2625 | keyword_def singleton dot_or_colon
2626 {
2627 p->lstate = EXPR_FNAME;
2628 $<stack>$ = p->cmdarg_stack;
2629 p->cmdarg_stack = 0;
2630 }
2631 fname
2632 {
2633 p->in_single++;
2634 p->lstate = EXPR_ENDFN; /* force for args */
2635 $<nd>$ = local_switch(p);
2636 nvars_block(p);
2637 }
2638 f_arglist
2639 bodystmt
2640 keyword_end
2641 {
2642 $$ = new_sdef(p, $2, $5, $7, $8);
2643 SET_LINENO($$, $1);
2644 local_resume(p, $<nd>6);
2645 nvars_unnest(p);
2646 p->in_single--;
2647 p->cmdarg_stack = $<stack>4;
2648 }
2649 | keyword_break
2650 {
2651 $$ = new_break(p, 0);
2652 }
2653 | keyword_next
2654 {
2655 $$ = new_next(p, 0);
2656 }
2657 | keyword_redo
2658 {
2659 $$ = new_redo(p);
2660 }
2661 | keyword_retry
2662 {
2663 $$ = new_retry(p);
2664 }
2665 ;
2666
2667primary_value : primary
2668 {
2669 $$ = $1;
2670 if (!$$) $$ = new_nil(p);
2671 }
2672 ;
2673
2674then : term
2675 | keyword_then
2676 | term keyword_then
2677 ;
2678
2679do : term
2680 | keyword_do_cond
2681 ;
2682
2683if_tail : opt_else
2684 | keyword_elsif expr_value then
2685 compstmt
2686 if_tail
2687 {
2688 $$ = new_if(p, cond($2), $4, $5);
2689 }
2690 ;
2691
2692opt_else : none
2693 | keyword_else compstmt
2694 {
2695 $$ = $2;
2696 }
2697 ;
2698
2699for_var : lhs
2700 {
2701 $$ = list1(list1($1));
2702 }
2703 | mlhs
2704 ;
2705
2706f_margs : f_arg
2707 {
2708 $$ = list3($1,0,0);
2709 }
2710 | f_arg ',' tSTAR f_norm_arg
2711 {
2712 $$ = list3($1, new_arg(p, $4), 0);
2713 }
2714 | f_arg ',' tSTAR f_norm_arg ',' f_arg
2715 {
2716 $$ = list3($1, new_arg(p, $4), $6);
2717 }
2718 | f_arg ',' tSTAR
2719 {
2720 local_add_f(p, 0);
2721 $$ = list3($1, (node*)-1, 0);
2722 }
2723 | f_arg ',' tSTAR ',' f_arg
2724 {
2725 $$ = list3($1, (node*)-1, $5);
2726 }
2727 | tSTAR f_norm_arg
2728 {
2729 $$ = list3(0, new_arg(p, $2), 0);
2730 }
2731 | tSTAR f_norm_arg ',' f_arg
2732 {
2733 $$ = list3(0, new_arg(p, $2), $4);
2734 }
2735 | tSTAR
2736 {
2737 local_add_f(p, 0);
2738 $$ = list3(0, (node*)-1, 0);
2739 }
2740 | tSTAR ','
2741 {
2742 local_add_f(p, 0);
2743 }
2744 f_arg
2745 {
2746 $$ = list3(0, (node*)-1, $4);
2747 }
2748 ;
2749
2750block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
2751 {
2752 $$ = new_args_tail(p, $1, $3, $4);
2753 }
2754 | f_block_kwarg opt_f_block_arg
2755 {
2756 $$ = new_args_tail(p, $1, 0, $2);
2757 }
2758 | f_kwrest opt_f_block_arg
2759 {
2760 $$ = new_args_tail(p, 0, $1, $2);
2761 }
2762 | f_block_arg
2763 {
2764 $$ = new_args_tail(p, 0, 0, $1);
2765 }
2766 ;
2767
2768opt_block_args_tail : ',' block_args_tail
2769 {
2770 $$ = $2;
2771 }
2772 | /* none */
2773 {
2774 $$ = new_args_tail(p, 0, 0, 0);
2775 }
2776 ;
2777
2778block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
2779 {
2780 $$ = new_args(p, $1, $3, $5, 0, $6);
2781 }
2782 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
2783 {
2784 $$ = new_args(p, $1, $3, $5, $7, $8);
2785 }
2786 | f_arg ',' f_block_optarg opt_block_args_tail
2787 {
2788 $$ = new_args(p, $1, $3, 0, 0, $4);
2789 }
2790 | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail
2791 {
2792 $$ = new_args(p, $1, $3, 0, $5, $6);
2793 }
2794 | f_arg ',' f_rest_arg opt_block_args_tail
2795 {
2796 $$ = new_args(p, $1, 0, $3, 0, $4);
2797 }
2798 | f_arg ',' opt_block_args_tail
2799 {
2800 $$ = new_args(p, $1, 0, 0, 0, $3);
2801 }
2802 | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
2803 {
2804 $$ = new_args(p, $1, 0, $3, $5, $6);
2805 }
2806 | f_arg opt_block_args_tail
2807 {
2808 $$ = new_args(p, $1, 0, 0, 0, $2);
2809 }
2810 | f_block_optarg ',' f_rest_arg opt_block_args_tail
2811 {
2812 $$ = new_args(p, 0, $1, $3, 0, $4);
2813 }
2814 | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
2815 {
2816 $$ = new_args(p, 0, $1, $3, $5, $6);
2817 }
2818 | f_block_optarg opt_block_args_tail
2819 {
2820 $$ = new_args(p, 0, $1, 0, 0, $2);
2821 }
2822 | f_block_optarg ',' f_arg opt_block_args_tail
2823 {
2824 $$ = new_args(p, 0, $1, 0, $3, $4);
2825 }
2826 | f_rest_arg opt_block_args_tail
2827 {
2828 $$ = new_args(p, 0, 0, $1, 0, $2);
2829 }
2830 | f_rest_arg ',' f_arg opt_block_args_tail
2831 {
2832 $$ = new_args(p, 0, 0, $1, $3, $4);
2833 }
2834 | block_args_tail
2835 {
2836 $$ = new_args(p, 0, 0, 0, 0, $1);
2837 }
2838 ;
2839
2840opt_block_param : none
2841 {
2842 local_add_blk(p, 0);
2843 $$ = 0;
2844 }
2845 | block_param_def
2846 {
2847 p->cmd_start = TRUE;
2848 $$ = $1;
2849 }
2850 ;
2851
2852block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|'
2853 {
2854 $$ = 0;
2855 }
2856 | tOROP
2857 {
2858 local_add_blk(p, 0);
2859 $$ = 0;
2860 }
2861 | '|' block_param opt_bv_decl '|'
2862 {
2863 $$ = $2;
2864 }
2865 ;
2866
2867
2868opt_bv_decl : opt_nl
2869 {
2870 $$ = 0;
2871 }
2872 | opt_nl ';' bv_decls opt_nl
2873 {
2874 $$ = 0;
2875 }
2876 ;
2877
2878bv_decls : bvar
2879 | bv_decls ',' bvar
2880 ;
2881
2882bvar : tIDENTIFIER
2883 {
2884 local_add_f(p, $1);
2885 new_bv(p, $1);
2886 }
2887 | f_bad_arg
2888 ;
2889
2890f_larglist : '(' f_args opt_bv_decl ')'
2891 {
2892 $$ = $2;
2893 }
2894 | f_args
2895 {
2896 $$ = $1;
2897 }
2898 ;
2899
2900lambda_body : tLAMBEG compstmt '}'
2901 {
2902 $$ = $2;
2903 }
2904 | keyword_do_LAMBDA bodystmt keyword_end
2905 {
2906 $$ = $2;
2907 }
2908 ;
2909
2910do_block : keyword_do_block
2911 {
2912 local_nest(p);
2913 nvars_nest(p);
2914 }
2915 opt_block_param
2916 bodystmt
2917 keyword_end
2918 {
2919 $$ = new_block(p,$3,$4);
2920 local_unnest(p);
2921 nvars_unnest(p);
2922 }
2923 ;
2924
2925block_call : command do_block
2926 {
2927 if ($1->car == (node*)NODE_YIELD) {
2928 yyerror(p, "block given to yield");
2929 }
2930 else {
2931 call_with_block(p, $1, $2);
2932 }
2933 $$ = $1;
2934 }
2935 | block_call call_op2 operation2 opt_paren_args
2936 {
2937 $$ = new_call(p, $1, $3, $4, $2);
2938 }
2939 | block_call call_op2 operation2 opt_paren_args brace_block
2940 {
2941 $$ = new_call(p, $1, $3, $4, $2);
2942 call_with_block(p, $$, $5);
2943 }
2944 | block_call call_op2 operation2 command_args do_block
2945 {
2946 $$ = new_call(p, $1, $3, $4, $2);
2947 call_with_block(p, $$, $5);
2948 }
2949 ;
2950
2951method_call : operation paren_args
2952 {
2953 $$ = new_fcall(p, $1, $2);
2954 }
2955 | primary_value call_op operation2 opt_paren_args
2956 {
2957 $$ = new_call(p, $1, $3, $4, $2);
2958 }
2959 | primary_value tCOLON2 operation2 paren_args
2960 {
2961 $$ = new_call(p, $1, $3, $4, tCOLON2);
2962 }
2963 | primary_value tCOLON2 operation3
2964 {
2965 $$ = new_call(p, $1, $3, 0, tCOLON2);
2966 }
2967 | primary_value call_op paren_args
2968 {
2969 $$ = new_call(p, $1, intern_lit("call"), $3, $2);
2970 }
2971 | primary_value tCOLON2 paren_args
2972 {
2973 $$ = new_call(p, $1, intern_lit("call"), $3, tCOLON2);
2974 }
2975 | keyword_super paren_args
2976 {
2977 $$ = new_super(p, $2);
2978 }
2979 | keyword_super
2980 {
2981 $$ = new_zsuper(p);
2982 }
2983 | primary_value '[' opt_call_args ']'
2984 {
2985 $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
2986 }
2987 ;
2988
2989brace_block : '{'
2990 {
2991 local_nest(p);
2992 nvars_nest(p);
2993 $<num>$ = p->lineno;
2994 }
2995 opt_block_param
2996 compstmt '}'
2997 {
2998 $$ = new_block(p,$3,$4);
2999 SET_LINENO($$, $<num>2);
3000 local_unnest(p);
3001 nvars_unnest(p);
3002 }
3003 | keyword_do
3004 {
3005 local_nest(p);
3006 nvars_nest(p);
3007 $<num>$ = p->lineno;
3008 }
3009 opt_block_param
3010 bodystmt keyword_end
3011 {
3012 $$ = new_block(p,$3,$4);
3013 SET_LINENO($$, $<num>2);
3014 local_unnest(p);
3015 nvars_unnest(p);
3016 }
3017 ;
3018
3019case_body : keyword_when args then
3020 compstmt
3021 cases
3022 {
3023 $$ = cons(cons($2, $4), $5);
3024 }
3025 ;
3026
3027cases : opt_else
3028 {
3029 if ($1) {
3030 $$ = cons(cons(0, $1), 0);
3031 }
3032 else {
3033 $$ = 0;
3034 }
3035 }
3036 | case_body
3037 ;
3038
3039opt_rescue : keyword_rescue exc_list exc_var then
3040 compstmt
3041 opt_rescue
3042 {
3043 $$ = list1(list3($2, $3, $5));
3044 if ($6) $$ = append($$, $6);
3045 }
3046 | none
3047 ;
3048
3049exc_list : arg
3050 {
3051 $$ = list1($1);
3052 }
3053 | mrhs
3054 | none
3055 ;
3056
3057exc_var : tASSOC lhs
3058 {
3059 $$ = $2;
3060 }
3061 | none
3062 ;
3063
3064opt_ensure : keyword_ensure compstmt
3065 {
3066 $$ = $2;
3067 }
3068 | none
3069 ;
3070
3071literal : numeric
3072 | symbol
3073 | words
3074 | symbols
3075 ;
3076
3077string : string_fragment
3078 | string string_fragment
3079 {
3080 $$ = concat_string(p, $1, $2);
3081 }
3082 ;
3083
3084string_fragment : tCHAR
3085 | tSTRING
3086 | tSTRING_BEG tSTRING
3087 {
3088 $$ = $2;
3089 }
3090 | tSTRING_BEG string_rep tSTRING
3091 {
3092 $$ = new_dstr(p, push($2, $3));
3093 }
3094 ;
3095
3096string_rep : string_interp
3097 | string_rep string_interp
3098 {
3099 $$ = append($1, $2);
3100 }
3101 ;
3102
3103string_interp : tSTRING_MID
3104 {
3105 $$ = list1($1);
3106 }
3107 | tSTRING_PART
3108 {
3109 $<nd>$ = p->lex_strterm;
3110 p->lex_strterm = NULL;
3111 }
3112 compstmt
3113 '}'
3114 {
3115 p->lex_strterm = $<nd>2;
3116 $$ = list2($1, $3);
3117 }
3118 | tLITERAL_DELIM
3119 {
3120 $$ = list1(new_literal_delim(p));
3121 }
3122 | tHD_LITERAL_DELIM heredoc_bodies
3123 {
3124 $$ = list1(new_literal_delim(p));
3125 }
3126 ;
3127
3128xstring : tXSTRING_BEG tXSTRING
3129 {
3130 $$ = $2;
3131 }
3132 | tXSTRING_BEG string_rep tXSTRING
3133 {
3134 $$ = new_dxstr(p, push($2, $3));
3135 }
3136 ;
3137
3138regexp : tREGEXP_BEG tREGEXP
3139 {
3140 $$ = $2;
3141 }
3142 | tREGEXP_BEG string_rep tREGEXP
3143 {
3144 $$ = new_dregx(p, $2, $3);
3145 }
3146 ;
3147
3148heredoc : tHEREDOC_BEG
3149 ;
3150
3151heredoc_bodies : heredoc_body
3152 | heredoc_bodies heredoc_body
3153 ;
3154
3155heredoc_body : tHEREDOC_END
3156 {
3157 parser_heredoc_info * inf = parsing_heredoc_inf(p);
3158 inf->doc = push(inf->doc, new_str(p, "", 0));
3159 heredoc_end(p);
3160 }
3161 | heredoc_string_rep tHEREDOC_END
3162 {
3163 heredoc_end(p);
3164 }
3165 ;
3166
3167heredoc_string_rep : heredoc_string_interp
3168 | heredoc_string_rep heredoc_string_interp
3169 ;
3170
3171heredoc_string_interp : tHD_STRING_MID
3172 {
3173 parser_heredoc_info * inf = parsing_heredoc_inf(p);
3174 inf->doc = push(inf->doc, $1);
3175 heredoc_treat_nextline(p);
3176 }
3177 | tHD_STRING_PART
3178 {
3179 $<nd>$ = p->lex_strterm;
3180 p->lex_strterm = NULL;
3181 }
3182 compstmt
3183 '}'
3184 {
3185 parser_heredoc_info * inf = parsing_heredoc_inf(p);
3186 p->lex_strterm = $<nd>2;
3187 inf->doc = push(push(inf->doc, $1), $3);
3188 }
3189 ;
3190
3191words : tWORDS_BEG tSTRING
3192 {
3193 $$ = new_words(p, list1($2));
3194 }
3195 | tWORDS_BEG string_rep tSTRING
3196 {
3197 $$ = new_words(p, push($2, $3));
3198 }
3199 ;
3200
3201
3202symbol : basic_symbol
3203 {
3204 p->lstate = EXPR_ENDARG;
3205 $$ = new_sym(p, $1);
3206 }
3207 | tSYMBEG tSTRING_BEG string_rep tSTRING
3208 {
3209 p->lstate = EXPR_ENDARG;
3210 $$ = new_dsym(p, new_dstr(p, push($3, $4)));
3211 }
3212 ;
3213
3214basic_symbol : tSYMBEG sym
3215 {
3216 $$ = $2;
3217 }
3218 ;
3219
3220sym : fname
3221 | tIVAR
3222 | tGVAR
3223 | tCVAR
3224 | tSTRING
3225 {
3226 $$ = new_strsym(p, $1);
3227 }
3228 | tSTRING_BEG tSTRING
3229 {
3230 $$ = new_strsym(p, $2);
3231 }
3232 ;
3233
3234symbols : tSYMBOLS_BEG tSTRING
3235 {
3236 $$ = new_symbols(p, list1($2));
3237 }
3238 | tSYMBOLS_BEG string_rep tSTRING
3239 {
3240 $$ = new_symbols(p, push($2, $3));
3241 }
3242 ;
3243
3244numeric : tINTEGER
3245 | tFLOAT
3246 | tUMINUS_NUM tINTEGER %prec tLOWEST
3247 {
3248 $$ = negate_lit(p, $2);
3249 }
3250 | tUMINUS_NUM tFLOAT %prec tLOWEST
3251 {
3252 $$ = negate_lit(p, $2);
3253 }
3254 ;
3255
3256variable : tIDENTIFIER
3257 {
3258 $$ = new_lvar(p, $1);
3259 }
3260 | tIVAR
3261 {
3262 $$ = new_ivar(p, $1);
3263 }
3264 | tGVAR
3265 {
3266 $$ = new_gvar(p, $1);
3267 }
3268 | tCVAR
3269 {
3270 $$ = new_cvar(p, $1);
3271 }
3272 | tCONSTANT
3273 {
3274 $$ = new_const(p, $1);
3275 }
3276 ;
3277
3278var_lhs : variable
3279 {
3280 assignable(p, $1);
3281 }
3282 | tNUMPARAM
3283 {
3284 yyerror(p, "can't assign to numbered parameter");
3285 }
3286 ;
3287
3288var_ref : variable
3289 {
3290 $$ = var_reference(p, $1);
3291 }
3292 | keyword_nil
3293 {
3294 $$ = new_nil(p);
3295 }
3296 | keyword_self
3297 {
3298 $$ = new_self(p);
3299 }
3300 | keyword_true
3301 {
3302 $$ = new_true(p);
3303 }
3304 | keyword_false
3305 {
3306 $$ = new_false(p);
3307 }
3308 | keyword__FILE__
3309 {
3310 const char *fn = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
3311 if (!fn) {
3312 fn = "(null)";
3313 }
3314 $$ = new_str(p, fn, strlen(fn));
3315 }
3316 | keyword__LINE__
3317 {
3318 char buf[16];
3319
3320 dump_int(p->lineno, buf);
3321 $$ = new_int(p, buf, 10, 0);
3322 }
3323 | keyword__ENCODING__
3324 {
3325#ifdef MRB_UTF8_STRING
3326 const char *enc = "UTF-8";
3327#else
3328 const char *enc = "ASCII-8BIT";
3329#endif
3330 $$ = new_str(p, enc, strlen(enc));
3331 }
3332 ;
3333
3334backref : tNTH_REF
3335 | tBACK_REF
3336 ;
3337
3338superclass : /* term */
3339 {
3340 $$ = 0;
3341 }
3342 | '<'
3343 {
3344 p->lstate = EXPR_BEG;
3345 p->cmd_start = TRUE;
3346 }
3347 expr_value term
3348 {
3349 $$ = $3;
3350 } /*
3351 | error term
3352 {
3353 yyerrok;
3354 $$ = 0;
3355 } */
3356 ;
3357
3358f_arglist : '(' f_args rparen
3359 {
3360 $$ = $2;
3361 p->lstate = EXPR_BEG;
3362 p->cmd_start = TRUE;
3363 }
3364 | f_args term
3365 {
3366 $$ = $1;
3367 }
3368 ;
3369
3370f_label : tIDENTIFIER tLABEL_TAG
3371 {
3372 local_nest(p);
3373 }
3374 ;
3375
3376f_kw : f_label arg
3377 {
3378 void_expr_error(p, $2);
3379 $$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
3380 local_unnest(p);
3381 }
3382 | f_label
3383 {
3384 $$ = new_kw_arg(p, $1, 0);
3385 local_unnest(p);
3386 }
3387 ;
3388
3389f_block_kw : f_label primary_value
3390 {
3391 $$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
3392 local_unnest(p);
3393 }
3394 | f_label
3395 {
3396 $$ = new_kw_arg(p, $1, 0);
3397 local_unnest(p);
3398 }
3399 ;
3400
3401f_block_kwarg : f_block_kw
3402 {
3403 $$ = list1($1);
3404 }
3405 | f_block_kwarg ',' f_block_kw
3406 {
3407 $$ = push($1, $3);
3408 }
3409 ;
3410
3411f_kwarg : f_kw
3412 {
3413 $$ = list1($1);
3414 }
3415 | f_kwarg ',' f_kw
3416 {
3417 $$ = push($1, $3);
3418 }
3419 ;
3420
3421kwrest_mark : tPOW
3422 | tDSTAR
3423 ;
3424
3425f_kwrest : kwrest_mark tIDENTIFIER
3426 {
3427 $$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
3428 }
3429 | kwrest_mark
3430 {
3431 $$ = cons((node*)NODE_KW_REST_ARGS, 0);
3432 }
3433 ;
3434
3435args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
3436 {
3437 $$ = new_args_tail(p, $1, $3, $4);
3438 }
3439 | f_kwarg opt_f_block_arg
3440 {
3441 $$ = new_args_tail(p, $1, 0, $2);
3442 }
3443 | f_kwrest opt_f_block_arg
3444 {
3445 $$ = new_args_tail(p, 0, $1, $2);
3446 }
3447 | f_block_arg
3448 {
3449 $$ = new_args_tail(p, 0, 0, $1);
3450 }
3451 ;
3452
3453opt_args_tail : ',' args_tail
3454 {
3455 $$ = $2;
3456 }
3457 | /* none */
3458 {
3459 $$ = new_args_tail(p, 0, 0, 0);
3460 }
3461 ;
3462
3463f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
3464 {
3465 $$ = new_args(p, $1, $3, $5, 0, $6);
3466 }
3467 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
3468 {
3469 $$ = new_args(p, $1, $3, $5, $7, $8);
3470 }
3471 | f_arg ',' f_optarg opt_args_tail
3472 {
3473 $$ = new_args(p, $1, $3, 0, 0, $4);
3474 }
3475 | f_arg ',' f_optarg ',' f_arg opt_args_tail
3476 {
3477 $$ = new_args(p, $1, $3, 0, $5, $6);
3478 }
3479 | f_arg ',' f_rest_arg opt_args_tail
3480 {
3481 $$ = new_args(p, $1, 0, $3, 0, $4);
3482 }
3483 | f_arg ',' f_rest_arg ',' f_arg opt_args_tail
3484 {
3485 $$ = new_args(p, $1, 0, $3, $5, $6);
3486 }
3487 | f_arg opt_args_tail
3488 {
3489 $$ = new_args(p, $1, 0, 0, 0, $2);
3490 }
3491 | f_optarg ',' f_rest_arg opt_args_tail
3492 {
3493 $$ = new_args(p, 0, $1, $3, 0, $4);
3494 }
3495 | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
3496 {
3497 $$ = new_args(p, 0, $1, $3, $5, $6);
3498 }
3499 | f_optarg opt_args_tail
3500 {
3501 $$ = new_args(p, 0, $1, 0, 0, $2);
3502 }
3503 | f_optarg ',' f_arg opt_args_tail
3504 {
3505 $$ = new_args(p, 0, $1, 0, $3, $4);
3506 }
3507 | f_rest_arg opt_args_tail
3508 {
3509 $$ = new_args(p, 0, 0, $1, 0, $2);
3510 }
3511 | f_rest_arg ',' f_arg opt_args_tail
3512 {
3513 $$ = new_args(p, 0, 0, $1, $3, $4);
3514 }
3515 | args_tail
3516 {
3517 $$ = new_args(p, 0, 0, 0, 0, $1);
3518 }
3519 | /* none */
3520 {
3521 local_add_f(p, mrb_intern_lit(p->mrb, "&"));
3522 $$ = new_args(p, 0, 0, 0, 0, 0);
3523 }
3524 ;
3525
3526f_bad_arg : tCONSTANT
3527 {
3528 yyerror(p, "formal argument cannot be a constant");
3529 $$ = 0;
3530 }
3531 | tIVAR
3532 {
3533 yyerror(p, "formal argument cannot be an instance variable");
3534 $$ = 0;
3535 }
3536 | tGVAR
3537 {
3538 yyerror(p, "formal argument cannot be a global variable");
3539 $$ = 0;
3540 }
3541 | tCVAR
3542 {
3543 yyerror(p, "formal argument cannot be a class variable");
3544 $$ = 0;
3545 }
3546 | tNUMPARAM
3547 {
3548 yyerror(p, "formal argument cannot be a numbered parameter");
3549 $$ = 0;
3550 }
3551 ;
3552
3553f_norm_arg : f_bad_arg
3554 {
3555 $$ = 0;
3556 }
3557 | tIDENTIFIER
3558 {
3559 local_add_f(p, $1);
3560 $$ = $1;
3561 }
3562 ;
3563
3564f_arg_item : f_norm_arg
3565 {
3566 $$ = new_arg(p, $1);
3567 }
3568 | tLPAREN
3569 {
3570 $<nd>$ = local_switch(p);
3571 }
3572 f_margs rparen
3573 {
3574 $$ = new_masgn_param(p, $3, p->locals->car);
3575 local_resume(p, $<nd>2);
3576 local_add_f(p, 0);
3577 }
3578 ;
3579
3580f_arg : f_arg_item
3581 {
3582 $$ = list1($1);
3583 }
3584 | f_arg ',' f_arg_item
3585 {
3586 $$ = push($1, $3);
3587 }
3588 ;
3589
3590f_opt_asgn : tIDENTIFIER '='
3591 {
3592 local_add_f(p, $1);
3593 local_nest(p);
3594 $$ = $1;
3595 }
3596 ;
3597
3598f_opt : f_opt_asgn arg
3599 {
3600 void_expr_error(p, $2);
3601 $$ = cons(nsym($1), cons($2, locals_node(p)));
3602 local_unnest(p);
3603 }
3604 ;
3605
3606f_block_opt : f_opt_asgn primary_value
3607 {
3608 void_expr_error(p, $2);
3609 $$ = cons(nsym($1), cons($2, locals_node(p)));
3610 local_unnest(p);
3611 }
3612 ;
3613
3614f_block_optarg : f_block_opt
3615 {
3616 $$ = list1($1);
3617 }
3618 | f_block_optarg ',' f_block_opt
3619 {
3620 $$ = push($1, $3);
3621 }
3622 ;
3623
3624f_optarg : f_opt
3625 {
3626 $$ = list1($1);
3627 }
3628 | f_optarg ',' f_opt
3629 {
3630 $$ = push($1, $3);
3631 }
3632 ;
3633
3634restarg_mark : '*'
3635 | tSTAR
3636 ;
3637
3638f_rest_arg : restarg_mark tIDENTIFIER
3639 {
3640 local_add_f(p, $2);
3641 $$ = $2;
3642 }
3643 | restarg_mark
3644 {
3645 local_add_f(p, mrb_intern_lit(p->mrb, "*"));
3646 $$ = -1;
3647 }
3648 ;
3649
3650blkarg_mark : '&'
3651 | tAMPER
3652 ;
3653
3654f_block_arg : blkarg_mark tIDENTIFIER
3655 {
3656 $$ = $2;
3657 }
3658 ;
3659
3660opt_f_block_arg : ',' f_block_arg
3661 {
3662 $$ = $2;
3663 }
3664 | none
3665 {
3666 $$ = 0;
3667 }
3668 ;
3669
3670singleton : var_ref
3671 {
3672 $$ = $1;
3673 if (!$$) $$ = new_nil(p);
3674 }
3675 | '(' {p->lstate = EXPR_BEG;} expr rparen
3676 {
3677 if ($3 == 0) {
3678 yyerror(p, "can't define singleton method for ().");
3679 }
3680 else {
3681 switch ((enum node_type)intn($3->car)) {
3682 case NODE_STR:
3683 case NODE_DSTR:
3684 case NODE_XSTR:
3685 case NODE_DXSTR:
3686 case NODE_DREGX:
3687 case NODE_MATCH:
3688 case NODE_FLOAT:
3689 case NODE_ARRAY:
3690 case NODE_HEREDOC:
3691 yyerror(p, "can't define singleton method for literals");
3692 default:
3693 break;
3694 }
3695 }
3696 $$ = $3;
3697 }
3698 ;
3699
3700assoc_list : none
3701 | assocs trailer
3702 {
3703 $$ = $1;
3704 }
3705 ;
3706
3707assocs : assoc
3708 {
3709 $$ = list1($1);
3710 NODE_LINENO($$, $1);
3711 }
3712 | assocs comma assoc
3713 {
3714 $$ = push($1, $3);
3715 }
3716 ;
3717
3718label_tag : tLABEL_TAG
3719 | tLABEL_TAG heredoc_bodies
3720 ;
3721
3722assoc : arg tASSOC arg
3723 {
3724 void_expr_error(p, $1);
3725 void_expr_error(p, $3);
3726 $$ = cons($1, $3);
3727 }
3728 | tIDENTIFIER label_tag arg
3729 {
3730 void_expr_error(p, $3);
3731 $$ = cons(new_sym(p, $1), $3);
3732 }
3733 | string_fragment label_tag arg
3734 {
3735 void_expr_error(p, $3);
3736 if ($1->car == (node*)NODE_DSTR) {
3737 $$ = cons(new_dsym(p, $1), $3);
3738 }
3739 else {
3740 $$ = cons(new_sym(p, new_strsym(p, $1)), $3);
3741 }
3742 }
3743 | tDSTAR arg
3744 {
3745 void_expr_error(p, $2);
3746 $$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
3747 }
3748 ;
3749
3750operation : tIDENTIFIER
3751 | tCONSTANT
3752 | tFID
3753 ;
3754
3755operation2 : tIDENTIFIER
3756 | tCONSTANT
3757 | tFID
3758 | op
3759 ;
3760
3761operation3 : tIDENTIFIER
3762 | tFID
3763 | op
3764 ;
3765
3766dot_or_colon : '.'
3767 | tCOLON2
3768 ;
3769
3770call_op : '.'
3771 {
3772 $$ = '.';
3773 }
3774 | tANDDOT
3775 {
3776 $$ = 0;
3777 }
3778 ;
3779
3780call_op2 : call_op
3781 | tCOLON2
3782 {
3783 $$ = tCOLON2;
3784 }
3785 ;
3786
3787opt_terms : /* none */
3788 | terms
3789 ;
3790
3791opt_nl : /* none */
3792 | nl
3793 ;
3794
3795rparen : opt_terms ')'
3796 ;
3797
3798trailer : /* none */
3799 | terms
3800 | comma
3801 ;
3802
3803term : ';' {yyerrok;}
3804 | nl
3805 | heredoc_body
3806 ;
3807
3808nl : '\n'
3809 {
3810 p->lineno++;
3811 p->column = 0;
3812 }
3813 ;
3814
3815terms : term
3816 | terms term
3817 ;
3818
3819none : /* none */
3820 {
3821 $$ = 0;
3822 }
3823 ;
3824%%
3825#define pylval (*((YYSTYPE*)(p->ylval)))
3826
3827static void
3828yyerror(parser_state *p, const char *s)
3829{
3830 char* c;
3831 size_t n;
3832
3833 if (! p->capture_errors) {
3834#ifndef MRB_DISABLE_STDIO
3835 if (p->filename_sym) {
3836 const char *filename = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
3837 fprintf(stderr, "%s:%d:%d: %s\n", filename, p->lineno, p->column, s);
3838 }
3839 else {
3840 fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
3841 }
3842#endif
3843 }
3844 else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) {
3845 n = strlen(s);
3846 c = (char *)parser_palloc(p, n + 1);
3847 memcpy(c, s, n + 1);
3848 p->error_buffer[p->nerr].message = c;
3849 p->error_buffer[p->nerr].lineno = p->lineno;
3850 p->error_buffer[p->nerr].column = p->column;
3851 }
3852 p->nerr++;
3853}
3854
3855static void
3856yyerror_c(parser_state *p, const char *msg, char c)
3857{
3858 char buf[256];
3859
3860 strncpy(buf, msg, sizeof(buf) - 2);
3861 buf[sizeof(buf) - 2] = '\0';
3862 strncat(buf, &c, 1);
3863 yyerror(p, buf);
3864}
3865
3866static void
3867yywarn(parser_state *p, const char *s)
3868{
3869 char* c;
3870 size_t n;
3871
3872 if (! p->capture_errors) {
3873#ifndef MRB_DISABLE_STDIO
3874 if (p->filename_sym) {
3875 const char *filename = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
3876 fprintf(stderr, "%s:%d:%d: warning: %s\n", filename, p->lineno, p->column, s);
3877 }
3878 else {
3879 fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s);
3880 }
3881#endif
3882 }
3883 else if (p->nwarn < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) {
3884 n = strlen(s);
3885 c = (char *)parser_palloc(p, n + 1);
3886 memcpy(c, s, n + 1);
3887 p->warn_buffer[p->nwarn].message = c;
3888 p->warn_buffer[p->nwarn].lineno = p->lineno;
3889 p->warn_buffer[p->nwarn].column = p->column;
3890 }
3891 p->nwarn++;
3892}
3893
3894static void
3895yywarning(parser_state *p, const char *s)
3896{
3897 yywarn(p, s);
3898}
3899
3900static void
3901yywarning_s(parser_state *p, const char *msg, const char *s)
3902{
3903 char buf[256];
3904
3905 strncpy(buf, msg, sizeof(buf) - 1);
3906 buf[sizeof(buf) - 1] = '\0';
3907 strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
3908 strncat(buf, s, sizeof(buf) - strlen(buf) - 1);
3909 yywarning(p, buf);
3910}
3911
3912static void
3913backref_error(parser_state *p, node *n)
3914{
3915 int c;
3916
3917 c = intn(n->car);
3918
3919 if (c == NODE_NTH_REF) {
3920 yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0');
3921 }
3922 else if (c == NODE_BACK_REF) {
3923 yyerror_c(p, "can't set variable $", (char)intn(n->cdr));
3924 }
3925 else {
3926 mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %d", c);
3927 }
3928}
3929
3930static void
3931void_expr_error(parser_state *p, node *n)
3932{
3933 int c;
3934
3935 if (n == NULL) return;
3936 c = intn(n->car);
3937 switch (c) {
3938 case NODE_BREAK:
3939 case NODE_RETURN:
3940 case NODE_NEXT:
3941 case NODE_REDO:
3942 case NODE_RETRY:
3943 yyerror(p, "void value expression");
3944 break;
3945 case NODE_AND:
3946 case NODE_OR:
3947 if (n->cdr) {
3948 void_expr_error(p, n->cdr->car);
3949 void_expr_error(p, n->cdr->cdr);
3950 }
3951 break;
3952 case NODE_BEGIN:
3953 if (n->cdr) {
3954 while (n->cdr) {
3955 n = n->cdr;
3956 }
3957 void_expr_error(p, n->car);
3958 }
3959 break;
3960 default:
3961 break;
3962 }
3963}
3964
3965static void pushback(parser_state *p, int c);
3966static mrb_bool peeks(parser_state *p, const char *s);
3967static mrb_bool skips(parser_state *p, const char *s);
3968
3969static inline int
3970nextc0(parser_state *p)
3971{
3972 int c;
3973#ifndef MRB_DISABLE_STDIO
3974 if (p->f) {
3975 if (feof(p->f)) return -1;
3976 c = fgetc(p->f);
3977 if (c == EOF) return -1;
3978 }
3979 else
3980#endif
3981 if (!p->s || p->s >= p->send) {
3982 return -1;
3983 }
3984 else {
3985 c = (unsigned char)*p->s++;
3986 }
3987 return c;
3988}
3989
3990static inline int
3991nextc(parser_state *p)
3992{
3993 int c;
3994
3995 if (p->pb) {
3996 node *tmp;
3997
3998 c = intn(p->pb->car);
3999 tmp = p->pb;
4000 p->pb = p->pb->cdr;
4001 cons_free(tmp);
4002 }
4003 else {
4004 c = nextc0(p);
4005 if (c < 0) goto eof;
4006 }
4007 if (c >= 0) {
4008 p->column++;
4009 }
4010 if (c == '\r') {
4011 const int lf = nextc0(p);
4012 if (lf == '\n') {
4013 return '\n';
4014 }
4015 if (lf > 0) pushback(p, lf);
4016 }
4017 return c;
4018
4019 eof:
4020 if (!p->cxt) return -1;
4021 else {
4022 if (p->cxt->partial_hook(p) < 0)
4023 return -1; /* end of program(s) */
4024 return -2; /* end of a file in the program files */
4025 }
4026}
4027
4028static void
4029pushback(parser_state *p, int c)
4030{
4031 if (c >= 0) {
4032 p->column--;
4033 }
4034 p->pb = cons(nint(c), p->pb);
4035}
4036
4037static void
4038skip(parser_state *p, char term)
4039{
4040 int c;
4041
4042 for (;;) {
4043 c = nextc(p);
4044 if (c < 0) break;
4045 if (c == term) break;
4046 }
4047}
4048
4049static int
4050peekc_n(parser_state *p, int n)
4051{
4052 node *list = 0;
4053 int c0;
4054
4055 do {
4056 c0 = nextc(p);
4057 if (c0 == -1) return c0; /* do not skip partial EOF */
4058 if (c0 >= 0) --p->column;
4059 list = push(list, nint(c0));
4060 } while(n--);
4061 if (p->pb) {
4062 p->pb = append((node*)list, p->pb);
4063 }
4064 else {
4065 p->pb = list;
4066 }
4067 return c0;
4068}
4069
4070static mrb_bool
4071peek_n(parser_state *p, int c, int n)
4072{
4073 return peekc_n(p, n) == c && c >= 0;
4074}
4075#define peek(p,c) peek_n((p), (c), 0)
4076
4077static mrb_bool
4078peeks(parser_state *p, const char *s)
4079{
4080 size_t len = strlen(s);
4081
4082#ifndef MRB_DISABLE_STDIO
4083 if (p->f) {
4084 int n = 0;
4085 while (*s) {
4086 if (!peek_n(p, *s++, n++)) return FALSE;
4087 }
4088 return TRUE;
4089 }
4090 else
4091#endif
4092 if (p->s && p->s + len <= p->send) {
4093 if (memcmp(p->s, s, len) == 0) return TRUE;
4094 }
4095 return FALSE;
4096}
4097
4098static mrb_bool
4099skips(parser_state *p, const char *s)
4100{
4101 int c;
4102
4103 for (;;) {
4104 /* skip until first char */
4105 for (;;) {
4106 c = nextc(p);
4107 if (c < 0) return FALSE;
4108 if (c == '\n') {
4109 p->lineno++;
4110 p->column = 0;
4111 }
4112 if (c == *s) break;
4113 }
4114 s++;
4115 if (peeks(p, s)) {
4116 size_t len = strlen(s);
4117
4118 while (len--) {
4119 if (nextc(p) == '\n') {
4120 p->lineno++;
4121 p->column = 0;
4122 }
4123 }
4124 return TRUE;
4125 }
4126 else{
4127 s--;
4128 }
4129 }
4130 return FALSE;
4131}
4132
4133
4134static int
4135newtok(parser_state *p)
4136{
4137 if (p->tokbuf != p->buf) {
4138 mrb_free(p->mrb, p->tokbuf);
4139 p->tokbuf = p->buf;
4140 p->tsiz = MRB_PARSER_TOKBUF_SIZE;
4141 }
4142 p->tidx = 0;
4143 return p->column - 1;
4144}
4145
4146static void
4147tokadd(parser_state *p, int32_t c)
4148{
4149 char utf8[4];
4150 int i, len;
4151
4152 /* mrb_assert(-0x10FFFF <= c && c <= 0xFF); */
4153 if (c >= 0) {
4154 /* Single byte from source or non-Unicode escape */
4155 utf8[0] = (char)c;
4156 len = 1;
4157 }
4158 else {
4159 /* Unicode character */
4160 c = -c;
4161 if (c < 0x80) {
4162 utf8[0] = (char)c;
4163 len = 1;
4164 }
4165 else if (c < 0x800) {
4166 utf8[0] = (char)(0xC0 | (c >> 6));
4167 utf8[1] = (char)(0x80 | (c & 0x3F));
4168 len = 2;
4169 }
4170 else if (c < 0x10000) {
4171 utf8[0] = (char)(0xE0 | (c >> 12) );
4172 utf8[1] = (char)(0x80 | ((c >> 6) & 0x3F));
4173 utf8[2] = (char)(0x80 | ( c & 0x3F));
4174 len = 3;
4175 }
4176 else {
4177 utf8[0] = (char)(0xF0 | (c >> 18) );
4178 utf8[1] = (char)(0x80 | ((c >> 12) & 0x3F));
4179 utf8[2] = (char)(0x80 | ((c >> 6) & 0x3F));
4180 utf8[3] = (char)(0x80 | ( c & 0x3F));
4181 len = 4;
4182 }
4183 }
4184 if (p->tidx+len >= p->tsiz) {
4185 if (p->tsiz >= MRB_PARSER_TOKBUF_MAX) {
4186 p->tidx += len;
4187 return;
4188 }
4189 p->tsiz *= 2;
4190 if (p->tokbuf == p->buf) {
4191 p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
4192 memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
4193 }
4194 else {
4195 p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
4196 }
4197 }
4198 for (i = 0; i < len; i++) {
4199 p->tokbuf[p->tidx++] = utf8[i];
4200 }
4201}
4202
4203static int
4204toklast(parser_state *p)
4205{
4206 return p->tokbuf[p->tidx-1];
4207}
4208
4209static void
4210tokfix(parser_state *p)
4211{
4212 if (p->tidx >= MRB_PARSER_TOKBUF_MAX) {
4213 p->tidx = MRB_PARSER_TOKBUF_MAX-1;
4214 yyerror(p, "string too long (truncated)");
4215 }
4216 p->tokbuf[p->tidx] = '\0';
4217}
4218
4219static const char*
4220tok(parser_state *p)
4221{
4222 return p->tokbuf;
4223}
4224
4225static int
4226toklen(parser_state *p)
4227{
4228 return p->tidx;
4229}
4230
4231#define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG)
4232#define IS_END() (p->lstate == EXPR_END || p->lstate == EXPR_ENDARG || p->lstate == EXPR_ENDFN)
4233#define IS_BEG() (p->lstate == EXPR_BEG || p->lstate == EXPR_MID || p->lstate == EXPR_VALUE || p->lstate == EXPR_CLASS)
4234#define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
4235#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
4236#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
4237
4238static int32_t
4239scan_oct(const int *start, int len, int *retlen)
4240{
4241 const int *s = start;
4242 int32_t retval = 0;
4243
4244 /* mrb_assert(len <= 3) */
4245 while (len-- && *s >= '0' && *s <= '7') {
4246 retval <<= 3;
4247 retval |= *s++ - '0';
4248 }
4249 *retlen = (int)(s - start);
4250
4251 return retval;
4252}
4253
4254static int32_t
4255scan_hex(parser_state *p, const int *start, int len, int *retlen)
4256{
4257 static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
4258 const int *s = start;
4259 uint32_t retval = 0;
4260 char *tmp;
4261
4262 /* mrb_assert(len <= 8) */
4263 while (len-- && *s && (tmp = (char*)strchr(hexdigit, *s))) {
4264 retval <<= 4;
4265 retval |= (tmp - hexdigit) & 15;
4266 s++;
4267 }
4268 *retlen = (int)(s - start);
4269
4270 return (int32_t)retval;
4271}
4272
4273static int32_t
4274read_escape_unicode(parser_state *p, int limit)
4275{
4276 int buf[9];
4277 int i;
4278 int32_t hex;
4279
4280 /* Look for opening brace */
4281 i = 0;
4282 buf[0] = nextc(p);
4283 if (buf[0] < 0) {
4284 eof:
4285 yyerror(p, "invalid escape character syntax");
4286 return -1;
4287 }
4288 if (ISXDIGIT(buf[0])) {
4289 /* \uxxxx form */
4290 for (i=1; i<limit; i++) {
4291 buf[i] = nextc(p);
4292 if (buf[i] < 0) goto eof;
4293 if (!ISXDIGIT(buf[i])) {
4294 pushback(p, buf[i]);
4295 break;
4296 }
4297 }
4298 }
4299 else {
4300 pushback(p, buf[0]);
4301 }
4302 hex = scan_hex(p, buf, i, &i);
4303 if (i == 0 || hex > 0x10FFFF || (hex & 0xFFFFF800) == 0xD800) {
4304 yyerror(p, "invalid Unicode code point");
4305 return -1;
4306 }
4307 return hex;
4308}
4309
4310/* Return negative to indicate Unicode code point */
4311static int32_t
4312read_escape(parser_state *p)
4313{
4314 int32_t c;
4315
4316 switch (c = nextc(p)) {
4317 case '\\':/* Backslash */
4318 return c;
4319
4320 case 'n':/* newline */
4321 return '\n';
4322
4323 case 't':/* horizontal tab */
4324 return '\t';
4325
4326 case 'r':/* carriage-return */
4327 return '\r';
4328
4329 case 'f':/* form-feed */
4330 return '\f';
4331
4332 case 'v':/* vertical tab */
4333 return '\13';
4334
4335 case 'a':/* alarm(bell) */
4336 return '\007';
4337
4338 case 'e':/* escape */
4339 return 033;
4340
4341 case '0': case '1': case '2': case '3': /* octal constant */
4342 case '4': case '5': case '6': case '7':
4343 {
4344 int buf[3];
4345 int i;
4346
4347 buf[0] = c;
4348 for (i=1; i<3; i++) {
4349 buf[i] = nextc(p);
4350 if (buf[i] < 0) goto eof;
4351 if (buf[i] < '0' || '7' < buf[i]) {
4352 pushback(p, buf[i]);
4353 break;
4354 }
4355 }
4356 c = scan_oct(buf, i, &i);
4357 }
4358 return c;
4359
4360 case 'x': /* hex constant */
4361 {
4362 int buf[2];
4363 int i;
4364
4365 for (i=0; i<2; i++) {
4366 buf[i] = nextc(p);
4367 if (buf[i] < 0) goto eof;
4368 if (!ISXDIGIT(buf[i])) {
4369 pushback(p, buf[i]);
4370 break;
4371 }
4372 }
4373 if (i == 0) {
4374 yyerror(p, "invalid hex escape");
4375 return -1;
4376 }
4377 return scan_hex(p, buf, i, &i);
4378 }
4379
4380 case 'u': /* Unicode */
4381 if (peek(p, '{')) {
4382 /* \u{xxxxxxxx} form */
4383 nextc(p);
4384 c = read_escape_unicode(p, 8);
4385 if (c < 0) return 0;
4386 if (nextc(p) != '}') goto eof;
4387 }
4388 else {
4389 c = read_escape_unicode(p, 4);
4390 if (c < 0) return 0;
4391 }
4392 return -c;
4393
4394 case 'b':/* backspace */
4395 return '\010';
4396
4397 case 's':/* space */
4398 return ' ';
4399
4400 case 'M':
4401 if ((c = nextc(p)) != '-') {
4402 yyerror(p, "Invalid escape character syntax");
4403 pushback(p, c);
4404 return '\0';
4405 }
4406 if ((c = nextc(p)) == '\\') {
4407 return read_escape(p) | 0x80;
4408 }
4409 else if (c < 0) goto eof;
4410 else {
4411 return ((c & 0xff) | 0x80);
4412 }
4413
4414 case 'C':
4415 if ((c = nextc(p)) != '-') {
4416 yyerror(p, "Invalid escape character syntax");
4417 pushback(p, c);
4418 return '\0';
4419 }
4420 case 'c':
4421 if ((c = nextc(p))== '\\') {
4422 c = read_escape(p);
4423 }
4424 else if (c == '?')
4425 return 0177;
4426 else if (c < 0) goto eof;
4427 return c & 0x9f;
4428
4429 eof:
4430 case -1:
4431 case -2: /* end of a file */
4432 yyerror(p, "Invalid escape character syntax");
4433 return '\0';
4434
4435 default:
4436 return c;
4437 }
4438}
4439
4440static int
4441parse_string(parser_state *p)
4442{
4443 int c;
4444 string_type type = (string_type)(intptr_t)p->lex_strterm->car;
4445 int nest_level = intn(p->lex_strterm->cdr->car);
4446 int beg = intn(p->lex_strterm->cdr->cdr->car);
4447 int end = intn(p->lex_strterm->cdr->cdr->cdr);
4448 parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
4449
4450 if (beg == 0) beg = -3; /* should never happen */
4451 if (end == 0) end = -3;
4452 newtok(p);
4453 while ((c = nextc(p)) != end || nest_level != 0) {
4454 if (hinf && (c == '\n' || c < 0)) {
4455 mrb_bool line_head;
4456 tokadd(p, '\n');
4457 tokfix(p);
4458 p->lineno++;
4459 p->column = 0;
4460 line_head = hinf->line_head;
4461 hinf->line_head = TRUE;
4462 if (line_head) {
4463 /* check whether end of heredoc */
4464 const char *s = tok(p);
4465 int len = toklen(p);
4466 if (hinf->allow_indent) {
4467 while (ISSPACE(*s) && len > 0) {
4468 ++s;
4469 --len;
4470 }
4471 }
4472 if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
4473 return tHEREDOC_END;
4474 }
4475 }
4476 if (c < 0) {
4477 char buf[256];
4478 const char s1[] = "can't find heredoc delimiter \"";
4479 const char s2[] = "\" anywhere before EOF";
4480
4481 if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
4482 yyerror(p, "can't find heredoc delimiter anywhere before EOF");
4483 } else {
4484 strcpy(buf, s1);
4485 strcat(buf, hinf->term);
4486 strcat(buf, s2);
4487 yyerror(p, buf);
4488 }
4489 return 0;
4490 }
4491 pylval.nd = new_str(p, tok(p), toklen(p));
4492 return tHD_STRING_MID;
4493 }
4494 if (c < 0) {
4495 yyerror(p, "unterminated string meets end of file");
4496 return 0;
4497 }
4498 else if (c == beg) {
4499 nest_level++;
4500 p->lex_strterm->cdr->car = nint(nest_level);
4501 }
4502 else if (c == end) {
4503 nest_level--;
4504 p->lex_strterm->cdr->car = nint(nest_level);
4505 }
4506 else if (c == '\\') {
4507 c = nextc(p);
4508 if (type & STR_FUNC_EXPAND) {
4509 if (c == end || c == beg) {
4510 tokadd(p, c);
4511 }
4512 else if (c == '\n') {
4513 p->lineno++;
4514 p->column = 0;
4515 if (type & STR_FUNC_ARRAY) {
4516 tokadd(p, '\n');
4517 }
4518 }
4519 else if (type & STR_FUNC_REGEXP) {
4520 tokadd(p, '\\');
4521 tokadd(p, c);
4522 }
4523 else if (c == 'u' && peek(p, '{')) {
4524 /* \u{xxxx xxxx xxxx} form */
4525 nextc(p);
4526 while (1) {
4527 do c = nextc(p); while (ISSPACE(c));
4528 if (c == '}') break;
4529 pushback(p, c);
4530 c = read_escape_unicode(p, 8);
4531 if (c < 0) break;
4532 tokadd(p, -c);
4533 }
4534 if (hinf)
4535 hinf->line_head = FALSE;
4536 }
4537 else {
4538 pushback(p, c);
4539 tokadd(p, read_escape(p));
4540 if (hinf)
4541 hinf->line_head = FALSE;
4542 }
4543 }
4544 else {
4545 if (c != beg && c != end) {
4546 if (c == '\n') {
4547 p->lineno++;
4548 p->column = 0;
4549 }
4550 if (!(c == '\\' || ((type & STR_FUNC_ARRAY) && ISSPACE(c)))) {
4551 tokadd(p, '\\');
4552 }
4553 }
4554 tokadd(p, c);
4555 }
4556 continue;
4557 }
4558 else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
4559 c = nextc(p);
4560 if (c == '{') {
4561 tokfix(p);
4562 p->lstate = EXPR_BEG;
4563 p->cmd_start = TRUE;
4564 pylval.nd = new_str(p, tok(p), toklen(p));
4565 if (hinf) {
4566 hinf->line_head = FALSE;
4567 return tHD_STRING_PART;
4568 }
4569 return tSTRING_PART;
4570 }
4571 tokadd(p, '#');
4572 pushback(p, c);
4573 continue;
4574 }
4575 if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
4576 if (toklen(p) == 0) {
4577 do {
4578 if (c == '\n') {
4579 p->lineno++;
4580 p->column = 0;
4581 heredoc_treat_nextline(p);
4582 if (p->parsing_heredoc != NULL) {
4583 return tHD_LITERAL_DELIM;
4584 }
4585 }
4586 c = nextc(p);
4587 } while (ISSPACE(c));
4588 pushback(p, c);
4589 return tLITERAL_DELIM;
4590 }
4591 else {
4592 pushback(p, c);
4593 tokfix(p);
4594 pylval.nd = new_str(p, tok(p), toklen(p));
4595 return tSTRING_MID;
4596 }
4597 }
4598 if (c == '\n') {
4599 p->lineno++;
4600 p->column = 0;
4601 }
4602 tokadd(p, c);
4603 }
4604
4605 tokfix(p);
4606 p->lstate = EXPR_ENDARG;
4607 end_strterm(p);
4608
4609 if (type & STR_FUNC_XQUOTE) {
4610 pylval.nd = new_xstr(p, tok(p), toklen(p));
4611 return tXSTRING;
4612 }
4613
4614 if (type & STR_FUNC_REGEXP) {
4615 int f = 0;
4616 int re_opt;
4617 char *s = strndup(tok(p), toklen(p));
4618 char flags[3];
4619 char *flag = flags;
4620 char enc = '\0';
4621 char *encp;
4622 char *dup;
4623
4624 newtok(p);
4625 while (re_opt = nextc(p), re_opt >= 0 && ISALPHA(re_opt)) {
4626 switch (re_opt) {
4627 case 'i': f |= 1; break;
4628 case 'x': f |= 2; break;
4629 case 'm': f |= 4; break;
4630 case 'u': f |= 16; break;
4631 case 'n': f |= 32; break;
4632 case 'o': break;
4633 default: tokadd(p, re_opt); break;
4634 }
4635 }
4636 pushback(p, re_opt);
4637 if (toklen(p)) {
4638 char msg[128];
4639
4640 strcpy(msg, "unknown regexp option");
4641 tokfix(p);
4642 if (toklen(p) > 1) {
4643 strcat(msg, "s");
4644 }
4645 strcat(msg, " - ");
4646 strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1);
4647 yyerror(p, msg);
4648 }
4649 if (f != 0) {
4650 if (f & 1) *flag++ = 'i';
4651 if (f & 2) *flag++ = 'x';
4652 if (f & 4) *flag++ = 'm';
4653 if (f & 16) enc = 'u';
4654 if (f & 32) enc = 'n';
4655 }
4656 if (flag > flags) {
4657 dup = strndup(flags, (size_t)(flag - flags));
4658 }
4659 else {
4660 dup = NULL;
4661 }
4662 if (enc) {
4663 encp = strndup(&enc, 1);
4664 }
4665 else {
4666 encp = NULL;
4667 }
4668 pylval.nd = new_regx(p, s, dup, encp);
4669
4670 return tREGEXP;
4671 }
4672 pylval.nd = new_str(p, tok(p), toklen(p));
4673
4674 return tSTRING;
4675}
4676
4677static int
4678number_literal_suffix(parser_state *p)
4679{
4680 int c, result = 0;
4681 node *list = 0;
4682 int column = p->column;
4683 int mask = NUM_SUFFIX_R|NUM_SUFFIX_I;
4684
4685 while ((c = nextc(p)) != -1) {
4686 list = push(list, (node*)(intptr_t)c);
4687
4688 if ((mask & NUM_SUFFIX_I) && c == 'i') {
4689 result |= (mask & NUM_SUFFIX_I);
4690 mask &= ~NUM_SUFFIX_I;
4691 /* r after i, rational of complex is disallowed */
4692 mask &= ~NUM_SUFFIX_R;
4693 continue;
4694 }
4695 if ((mask & NUM_SUFFIX_R) && c == 'r') {
4696 result |= (mask & NUM_SUFFIX_R);
4697 mask &= ~NUM_SUFFIX_R;
4698 continue;
4699 }
4700 if (!ISASCII(c) || ISALPHA(c) || c == '_') {
4701 p->column = column;
4702 if (p->pb) {
4703 p->pb = append((node*)list, p->pb);
4704 }
4705 else {
4706 p->pb = list;
4707 }
4708 return 0;
4709 }
4710 pushback(p, c);
4711 break;
4712 }
4713 return result;
4714}
4715
4716static int
4717heredoc_identifier(parser_state *p)
4718{
4719 int c;
4720 int type = str_heredoc;
4721 mrb_bool indent = FALSE;
4722 mrb_bool quote = FALSE;
4723 node *newnode;
4724 parser_heredoc_info *info;
4725
4726 c = nextc(p);
4727 if (ISSPACE(c) || c == '=') {
4728 pushback(p, c);
4729 return 0;
4730 }
4731 if (c == '-') {
4732 indent = TRUE;
4733 c = nextc(p);
4734 }
4735 if (c == '\'' || c == '"') {
4736 int term = c;
4737 if (c == '\'')
4738 quote = TRUE;
4739 newtok(p);
4740 while ((c = nextc(p)) >= 0 && c != term) {
4741 if (c == '\n') {
4742 c = -1;
4743 break;
4744 }
4745 tokadd(p, c);
4746 }
4747 if (c < 0) {
4748 yyerror(p, "unterminated here document identifier");
4749 return 0;
4750 }
4751 }
4752 else {
4753 if (c < 0) {
4754 return 0; /* missing here document identifier */
4755 }
4756 if (! identchar(c)) {
4757 pushback(p, c);
4758 if (indent) pushback(p, '-');
4759 return 0;
4760 }
4761 newtok(p);
4762 do {
4763 tokadd(p, c);
4764 } while ((c = nextc(p)) >= 0 && identchar(c));
4765 pushback(p, c);
4766 }
4767 tokfix(p);
4768 newnode = new_heredoc(p);
4769 info = (parser_heredoc_info*)newnode->cdr;
4770 info->term = strndup(tok(p), toklen(p));
4771 info->term_len = toklen(p);
4772 if (! quote)
4773 type |= STR_FUNC_EXPAND;
4774 info->type = (string_type)type;
4775 info->allow_indent = indent;
4776 info->line_head = TRUE;
4777 info->doc = NULL;
4778 p->heredocs_from_nextline = push(p->heredocs_from_nextline, newnode);
4779 p->lstate = EXPR_END;
4780
4781 pylval.nd = newnode;
4782 return tHEREDOC_BEG;
4783}
4784
4785static int
4786arg_ambiguous(parser_state *p)
4787{
4788 yywarning(p, "ambiguous first argument; put parentheses or even spaces");
4789 return 1;
4790}
4791
4792#include "lex.def"
4793
4794static int
4795parser_yylex(parser_state *p)
4796{
4797 int32_t c;
4798 int space_seen = 0;
4799 int cmd_state;
4800 enum mrb_lex_state_enum last_state;
4801 int token_column;
4802
4803 if (p->lex_strterm) {
4804 if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
4805 if (p->parsing_heredoc != NULL)
4806 return parse_string(p);
4807 }
4808 else
4809 return parse_string(p);
4810 }
4811 cmd_state = p->cmd_start;
4812 p->cmd_start = FALSE;
4813 retry:
4814 last_state = p->lstate;
4815 switch (c = nextc(p)) {
4816 case '\004': /* ^D */
4817 case '\032': /* ^Z */
4818 case '\0': /* NUL */
4819 case -1: /* end of script. */
4820 if (p->heredocs_from_nextline)
4821 goto maybe_heredoc;
4822 return 0;
4823
4824 /* white spaces */
4825 case ' ': case '\t': case '\f': case '\r':
4826 case '\13': /* '\v' */
4827 space_seen = 1;
4828 goto retry;
4829
4830 case '#': /* it's a comment */
4831 skip(p, '\n');
4832 /* fall through */
4833 case -2: /* end of a file */
4834 case '\n':
4835 maybe_heredoc:
4836 heredoc_treat_nextline(p);
4837 p->column = 0;
4838 switch (p->lstate) {
4839 case EXPR_BEG:
4840 case EXPR_FNAME:
4841 case EXPR_DOT:
4842 case EXPR_CLASS:
4843 case EXPR_VALUE:
4844 p->lineno++;
4845 if (p->parsing_heredoc != NULL) {
4846 if (p->lex_strterm) {
4847 return parse_string(p);
4848 }
4849 }
4850 goto retry;
4851 default:
4852 break;
4853 }
4854 if (p->parsing_heredoc != NULL) {
4855 return '\n';
4856 }
4857 while ((c = nextc(p))) {
4858 switch (c) {
4859 case ' ': case '\t': case '\f': case '\r':
4860 case '\13': /* '\v' */
4861 space_seen = 1;
4862 break;
4863 case '#': /* comment as a whitespace */
4864 pushback(p, '#');
4865 p->lineno++;
4866 goto retry;
4867 case '.':
4868 if (!peek(p, '.')) {
4869 pushback(p, '.');
4870 p->lineno++;
4871 goto retry;
4872 }
4873 pushback(p, c);
4874 goto normal_newline;
4875 case '&':
4876 if (peek(p, '.')) {
4877 pushback(p, '&');
4878 p->lineno++;
4879 goto retry;
4880 }
4881 pushback(p, c);
4882 goto normal_newline;
4883 case -1: /* EOF */
4884 case -2: /* end of a file */
4885 goto normal_newline;
4886 default:
4887 pushback(p, c);
4888 goto normal_newline;
4889 }
4890 }
4891 normal_newline:
4892 p->cmd_start = TRUE;
4893 p->lstate = EXPR_BEG;
4894 return '\n';
4895
4896 case '*':
4897 if ((c = nextc(p)) == '*') {
4898 if ((c = nextc(p)) == '=') {
4899 pylval.id = intern_lit("**");
4900 p->lstate = EXPR_BEG;
4901 return tOP_ASGN;
4902 }
4903 pushback(p, c);
4904 if (IS_SPCARG(c)) {
4905 yywarning(p, "'**' interpreted as argument prefix");
4906 c = tDSTAR;
4907 }
4908 else if (IS_BEG()) {
4909 c = tDSTAR;
4910 }
4911 else {
4912 c = tPOW; /* "**", "argument prefix" */
4913 }
4914 }
4915 else {
4916 if (c == '=') {
4917 pylval.id = intern_lit("*");
4918 p->lstate = EXPR_BEG;
4919 return tOP_ASGN;
4920 }
4921 pushback(p, c);
4922 if (IS_SPCARG(c)) {
4923 yywarning(p, "'*' interpreted as argument prefix");
4924 c = tSTAR;
4925 }
4926 else if (IS_BEG()) {
4927 c = tSTAR;
4928 }
4929 else {
4930 c = '*';
4931 }
4932 }
4933 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4934 p->lstate = EXPR_ARG;
4935 }
4936 else {
4937 p->lstate = EXPR_BEG;
4938 }
4939 return c;
4940
4941 case '!':
4942 c = nextc(p);
4943 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4944 p->lstate = EXPR_ARG;
4945 if (c == '@') {
4946 return '!';
4947 }
4948 }
4949 else {
4950 p->lstate = EXPR_BEG;
4951 }
4952 if (c == '=') {
4953 return tNEQ;
4954 }
4955 if (c == '~') {
4956 return tNMATCH;
4957 }
4958 pushback(p, c);
4959 return '!';
4960
4961 case '=':
4962 if (p->column == 1) {
4963 static const char begin[] = "begin";
4964 static const char end[] = "\n=end";
4965 if (peeks(p, begin)) {
4966 c = peekc_n(p, sizeof(begin)-1);
4967 if (c < 0 || ISSPACE(c)) {
4968 do {
4969 if (!skips(p, end)) {
4970 yyerror(p, "embedded document meets end of file");
4971 return 0;
4972 }
4973 c = nextc(p);
4974 } while (!(c < 0 || ISSPACE(c)));
4975 if (c != '\n') skip(p, '\n');
4976 p->lineno++;
4977 p->column = 0;
4978 goto retry;
4979 }
4980 }
4981 }
4982 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4983 p->lstate = EXPR_ARG;
4984 }
4985 else {
4986 p->lstate = EXPR_BEG;
4987 }
4988 if ((c = nextc(p)) == '=') {
4989 if ((c = nextc(p)) == '=') {
4990 return tEQQ;
4991 }
4992 pushback(p, c);
4993 return tEQ;
4994 }
4995 if (c == '~') {
4996 return tMATCH;
4997 }
4998 else if (c == '>') {
4999 return tASSOC;
5000 }
5001 pushback(p, c);
5002 return '=';
5003
5004 case '<':
5005 c = nextc(p);
5006 if (c == '<' &&
5007 p->lstate != EXPR_DOT &&
5008 p->lstate != EXPR_CLASS &&
5009 !IS_END() &&
5010 (!IS_ARG() || space_seen)) {
5011 int token = heredoc_identifier(p);
5012 if (token)
5013 return token;
5014 }
5015 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5016 p->lstate = EXPR_ARG;
5017 }
5018 else {
5019 p->lstate = EXPR_BEG;
5020 if (p->lstate == EXPR_CLASS) {
5021 p->cmd_start = TRUE;
5022 }
5023 }
5024 if (c == '=') {
5025 if ((c = nextc(p)) == '>') {
5026 return tCMP;
5027 }
5028 pushback(p, c);
5029 return tLEQ;
5030 }
5031 if (c == '<') {
5032 if ((c = nextc(p)) == '=') {
5033 pylval.id = intern_lit("<<");
5034 p->lstate = EXPR_BEG;
5035 return tOP_ASGN;
5036 }
5037 pushback(p, c);
5038 return tLSHFT;
5039 }
5040 pushback(p, c);
5041 return '<';
5042
5043 case '>':
5044 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5045 p->lstate = EXPR_ARG;
5046 }
5047 else {
5048 p->lstate = EXPR_BEG;
5049 }
5050 if ((c = nextc(p)) == '=') {
5051 return tGEQ;
5052 }
5053 if (c == '>') {
5054 if ((c = nextc(p)) == '=') {
5055 pylval.id = intern_lit(">>");
5056 p->lstate = EXPR_BEG;
5057 return tOP_ASGN;
5058 }
5059 pushback(p, c);
5060 return tRSHFT;
5061 }
5062 pushback(p, c);
5063 return '>';
5064
5065 case '"':
5066 p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
5067 return tSTRING_BEG;
5068
5069 case '\'':
5070 p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
5071 return parse_string(p);
5072
5073 case '`':
5074 if (p->lstate == EXPR_FNAME) {
5075 p->lstate = EXPR_ENDFN;
5076 return '`';
5077 }
5078 if (p->lstate == EXPR_DOT) {
5079 if (cmd_state)
5080 p->lstate = EXPR_CMDARG;
5081 else
5082 p->lstate = EXPR_ARG;
5083 return '`';
5084 }
5085 p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
5086 return tXSTRING_BEG;
5087
5088 case '?':
5089 if (IS_END()) {
5090 p->lstate = EXPR_VALUE;
5091 return '?';
5092 }
5093 c = nextc(p);
5094 if (c < 0) {
5095 yyerror(p, "incomplete character syntax");
5096 return 0;
5097 }
5098 if (ISSPACE(c)) {
5099 if (!IS_ARG()) {
5100 int c2;
5101 switch (c) {
5102 case ' ':
5103 c2 = 's';
5104 break;
5105 case '\n':
5106 c2 = 'n';
5107 break;
5108 case '\t':
5109 c2 = 't';
5110 break;
5111 case '\v':
5112 c2 = 'v';
5113 break;
5114 case '\r':
5115 c2 = 'r';
5116 break;
5117 case '\f':
5118 c2 = 'f';
5119 break;
5120 default:
5121 c2 = 0;
5122 break;
5123 }
5124 if (c2) {
5125 char buf[256];
5126 char cc[] = { (char)c2, '\0' };
5127
5128 strcpy(buf, "invalid character syntax; use ?\\");
5129 strncat(buf, cc, 2);
5130 yyerror(p, buf);
5131 }
5132 }
5133 ternary:
5134 pushback(p, c);
5135 p->lstate = EXPR_VALUE;
5136 return '?';
5137 }
5138 newtok(p);
5139 /* need support UTF-8 if configured */
5140 if ((ISALNUM(c) || c == '_')) {
5141 int c2 = nextc(p);
5142 pushback(p, c2);
5143 if ((ISALNUM(c2) || c2 == '_')) {
5144 goto ternary;
5145 }
5146 }
5147 if (c == '\\') {
5148 c = read_escape(p);
5149 tokadd(p, c);
5150 }
5151 else {
5152 tokadd(p, c);
5153 }
5154 tokfix(p);
5155 pylval.nd = new_str(p, tok(p), toklen(p));
5156 p->lstate = EXPR_ENDARG;
5157 return tCHAR;
5158
5159 case '&':
5160 if ((c = nextc(p)) == '&') {
5161 p->lstate = EXPR_BEG;
5162 if ((c = nextc(p)) == '=') {
5163 pylval.id = intern_lit("&&");
5164 p->lstate = EXPR_BEG;
5165 return tOP_ASGN;
5166 }
5167 pushback(p, c);
5168 return tANDOP;
5169 }
5170 else if (c == '.') {
5171 p->lstate = EXPR_DOT;
5172 return tANDDOT;
5173 }
5174 else if (c == '=') {
5175 pylval.id = intern_lit("&");
5176 p->lstate = EXPR_BEG;
5177 return tOP_ASGN;
5178 }
5179 pushback(p, c);
5180 if (IS_SPCARG(c)) {
5181 yywarning(p, "'&' interpreted as argument prefix");
5182 c = tAMPER;
5183 }
5184 else if (IS_BEG()) {
5185 c = tAMPER;
5186 }
5187 else {
5188 c = '&';
5189 }
5190 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5191 p->lstate = EXPR_ARG;
5192 }
5193 else {
5194 p->lstate = EXPR_BEG;
5195 }
5196 return c;
5197
5198 case '|':
5199 if ((c = nextc(p)) == '|') {
5200 p->lstate = EXPR_BEG;
5201 if ((c = nextc(p)) == '=') {
5202 pylval.id = intern_lit("||");
5203 p->lstate = EXPR_BEG;
5204 return tOP_ASGN;
5205 }
5206 pushback(p, c);
5207 return tOROP;
5208 }
5209 if (c == '=') {
5210 pylval.id = intern_lit("|");
5211 p->lstate = EXPR_BEG;
5212 return tOP_ASGN;
5213 }
5214 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5215 p->lstate = EXPR_ARG;
5216 }
5217 else {
5218 p->lstate = EXPR_BEG;
5219 }
5220 pushback(p, c);
5221 return '|';
5222
5223 case '+':
5224 c = nextc(p);
5225 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5226 p->lstate = EXPR_ARG;
5227 if (c == '@') {
5228 return tUPLUS;
5229 }
5230 pushback(p, c);
5231 return '+';
5232 }
5233 if (c == '=') {
5234 pylval.id = intern_lit("+");
5235 p->lstate = EXPR_BEG;
5236 return tOP_ASGN;
5237 }
5238 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
5239 p->lstate = EXPR_BEG;
5240 pushback(p, c);
5241 if (c >= 0 && ISDIGIT(c)) {
5242 c = '+';
5243 goto start_num;
5244 }
5245 return tUPLUS;
5246 }
5247 p->lstate = EXPR_BEG;
5248 pushback(p, c);
5249 return '+';
5250
5251 case '-':
5252 c = nextc(p);
5253 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5254 p->lstate = EXPR_ARG;
5255 if (c == '@') {
5256 return tUMINUS;
5257 }
5258 pushback(p, c);
5259 return '-';
5260 }
5261 if (c == '=') {
5262 pylval.id = intern_lit("-");
5263 p->lstate = EXPR_BEG;
5264 return tOP_ASGN;
5265 }
5266 if (c == '>') {
5267 p->lstate = EXPR_ENDFN;
5268 return tLAMBDA;
5269 }
5270 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
5271 p->lstate = EXPR_BEG;
5272 pushback(p, c);
5273 if (c >= 0 && ISDIGIT(c)) {
5274 return tUMINUS_NUM;
5275 }
5276 return tUMINUS;
5277 }
5278 p->lstate = EXPR_BEG;
5279 pushback(p, c);
5280 return '-';
5281
5282 case '.':
5283 p->lstate = EXPR_BEG;
5284 if ((c = nextc(p)) == '.') {
5285 if ((c = nextc(p)) == '.') {
5286 return tDOT3;
5287 }
5288 pushback(p, c);
5289 return tDOT2;
5290 }
5291 pushback(p, c);
5292 if (c >= 0 && ISDIGIT(c)) {
5293 yyerror(p, "no .<digit> floating literal anymore; put 0 before dot");
5294 }
5295 p->lstate = EXPR_DOT;
5296 return '.';
5297
5298 start_num:
5299 case '0': case '1': case '2': case '3': case '4':
5300 case '5': case '6': case '7': case '8': case '9':
5301 {
5302 int is_float, seen_point, seen_e, nondigit;
5303 int suffix = 0;
5304
5305 is_float = seen_point = seen_e = nondigit = 0;
5306 p->lstate = EXPR_ENDARG;
5307 newtok(p);
5308 if (c == '-' || c == '+') {
5309 tokadd(p, c);
5310 c = nextc(p);
5311 }
5312 if (c == '0') {
5313#define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0)
5314 int start = toklen(p);
5315 c = nextc(p);
5316 if (c == 'x' || c == 'X') {
5317 /* hexadecimal */
5318 c = nextc(p);
5319 if (c >= 0 && ISXDIGIT(c)) {
5320 do {
5321 if (c == '_') {
5322 if (nondigit) break;
5323 nondigit = c;
5324 continue;
5325 }
5326 if (!ISXDIGIT(c)) break;
5327 nondigit = 0;
5328 tokadd(p, tolower(c));
5329 } while ((c = nextc(p)) >= 0);
5330 }
5331 pushback(p, c);
5332 tokfix(p);
5333 if (toklen(p) == start) {
5334 no_digits();
5335 }
5336 else if (nondigit) goto trailing_uc;
5337 suffix = number_literal_suffix(p);
5338 pylval.nd = new_int(p, tok(p), 16, suffix);
5339 return tINTEGER;
5340 }
5341 if (c == 'b' || c == 'B') {
5342 /* binary */
5343 c = nextc(p);
5344 if (c == '0' || c == '1') {
5345 do {
5346 if (c == '_') {
5347 if (nondigit) break;
5348 nondigit = c;
5349 continue;
5350 }
5351 if (c != '0' && c != '1') break;
5352 nondigit = 0;
5353 tokadd(p, c);
5354 } while ((c = nextc(p)) >= 0);
5355 }
5356 pushback(p, c);
5357 tokfix(p);
5358 if (toklen(p) == start) {
5359 no_digits();
5360 }
5361 else if (nondigit) goto trailing_uc;
5362 suffix = number_literal_suffix(p);
5363 pylval.nd = new_int(p, tok(p), 2, suffix);
5364 return tINTEGER;
5365 }
5366 if (c == 'd' || c == 'D') {
5367 /* decimal */
5368 c = nextc(p);
5369 if (c >= 0 && ISDIGIT(c)) {
5370 do {
5371 if (c == '_') {
5372 if (nondigit) break;
5373 nondigit = c;
5374 continue;
5375 }
5376 if (!ISDIGIT(c)) break;
5377 nondigit = 0;
5378 tokadd(p, c);
5379 } while ((c = nextc(p)) >= 0);
5380 }
5381 pushback(p, c);
5382 tokfix(p);
5383 if (toklen(p) == start) {
5384 no_digits();
5385 }
5386 else if (nondigit) goto trailing_uc;
5387 suffix = number_literal_suffix(p);
5388 pylval.nd = new_int(p, tok(p), 10, suffix);
5389 return tINTEGER;
5390 }
5391 if (c == '_') {
5392 /* 0_0 */
5393 goto octal_number;
5394 }
5395 if (c == 'o' || c == 'O') {
5396 /* prefixed octal */
5397 c = nextc(p);
5398 if (c < 0 || c == '_' || !ISDIGIT(c)) {
5399 no_digits();
5400 }
5401 }
5402 if (c >= '0' && c <= '7') {
5403 /* octal */
5404 octal_number:
5405 do {
5406 if (c == '_') {
5407 if (nondigit) break;
5408 nondigit = c;
5409 continue;
5410 }
5411 if (c < '0' || c > '9') break;
5412 if (c > '7') goto invalid_octal;
5413 nondigit = 0;
5414 tokadd(p, c);
5415 } while ((c = nextc(p)) >= 0);
5416
5417 if (toklen(p) > start) {
5418 pushback(p, c);
5419 tokfix(p);
5420 if (nondigit) goto trailing_uc;
5421 suffix = number_literal_suffix(p);
5422 pylval.nd = new_int(p, tok(p), 8, suffix);
5423 return tINTEGER;
5424 }
5425 if (nondigit) {
5426 pushback(p, c);
5427 goto trailing_uc;
5428 }
5429 }
5430 if (c > '7' && c <= '9') {
5431 invalid_octal:
5432 yyerror(p, "Invalid octal digit");
5433 }
5434 else if (c == '.' || c == 'e' || c == 'E') {
5435 tokadd(p, '0');
5436 }
5437 else {
5438 pushback(p, c);
5439 suffix = number_literal_suffix(p);
5440 pylval.nd = new_int(p, "0", 10, suffix);
5441 return tINTEGER;
5442 }
5443 }
5444
5445 for (;;) {
5446 switch (c) {
5447 case '0': case '1': case '2': case '3': case '4':
5448 case '5': case '6': case '7': case '8': case '9':
5449 nondigit = 0;
5450 tokadd(p, c);
5451 break;
5452
5453 case '.':
5454 if (nondigit) goto trailing_uc;
5455 if (seen_point || seen_e) {
5456 goto decode_num;
5457 }
5458 else {
5459 int c0 = nextc(p);
5460 if (c0 < 0 || !ISDIGIT(c0)) {
5461 pushback(p, c0);
5462 goto decode_num;
5463 }
5464 c = c0;
5465 }
5466 tokadd(p, '.');
5467 tokadd(p, c);
5468 is_float++;
5469 seen_point++;
5470 nondigit = 0;
5471 break;
5472
5473 case 'e':
5474 case 'E':
5475 if (nondigit) {
5476 pushback(p, c);
5477 c = nondigit;
5478 goto decode_num;
5479 }
5480 if (seen_e) {
5481 goto decode_num;
5482 }
5483 tokadd(p, c);
5484 seen_e++;
5485 is_float++;
5486 nondigit = c;
5487 c = nextc(p);
5488 if (c != '-' && c != '+') continue;
5489 tokadd(p, c);
5490 nondigit = c;
5491 break;
5492
5493 case '_': /* '_' in number just ignored */
5494 if (nondigit) goto decode_num;
5495 nondigit = c;
5496 break;
5497
5498 default:
5499 goto decode_num;
5500 }
5501 c = nextc(p);
5502 }
5503
5504 decode_num:
5505 pushback(p, c);
5506 if (nondigit) {
5507 trailing_uc:
5508 yyerror_c(p, "trailing non digit in number: ", (char)nondigit);
5509 }
5510 tokfix(p);
5511 if (is_float) {
5512#ifdef MRB_WITHOUT_FLOAT
5513 yywarning_s(p, "floating point numbers are not supported", tok(p));
5514 pylval.nd = new_int(p, "0", 10, 0);
5515 return tINTEGER;
5516#else
5517 double d;
5518 char *endp;
5519
5520 errno = 0;
5521 d = mrb_float_read(tok(p), &endp);
5522 if (d == 0 && endp == tok(p)) {
5523 yywarning_s(p, "corrupted float value", tok(p));
5524 }
5525 else if (errno == ERANGE) {
5526 yywarning_s(p, "float out of range", tok(p));
5527 errno = 0;
5528 }
5529 suffix = number_literal_suffix(p);
5530 pylval.nd = new_float(p, tok(p), suffix);
5531 return tFLOAT;
5532#endif
5533 }
5534 suffix = number_literal_suffix(p);
5535 pylval.nd = new_int(p, tok(p), 10, suffix);
5536 return tINTEGER;
5537 }
5538
5539 case ')':
5540 case ']':
5541 p->paren_nest--;
5542 /* fall through */
5543 case '}':
5544 COND_LEXPOP();
5545 CMDARG_LEXPOP();
5546 if (c == ')')
5547 p->lstate = EXPR_ENDFN;
5548 else
5549 p->lstate = EXPR_END;
5550 return c;
5551
5552 case ':':
5553 c = nextc(p);
5554 if (c == ':') {
5555 if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) {
5556 p->lstate = EXPR_BEG;
5557 return tCOLON3;
5558 }
5559 p->lstate = EXPR_DOT;
5560 return tCOLON2;
5561 }
5562 if (!space_seen && IS_END()) {
5563 pushback(p, c);
5564 p->lstate = EXPR_BEG;
5565 return tLABEL_TAG;
5566 }
5567 if (!ISSPACE(c) || IS_BEG()) {
5568 pushback(p, c);
5569 p->lstate = EXPR_FNAME;
5570 return tSYMBEG;
5571 }
5572 pushback(p, c);
5573 p->lstate = EXPR_BEG;
5574 return ':';
5575
5576 case '/':
5577 if (IS_BEG()) {
5578 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
5579 return tREGEXP_BEG;
5580 }
5581 if ((c = nextc(p)) == '=') {
5582 pylval.id = intern_lit("/");
5583 p->lstate = EXPR_BEG;
5584 return tOP_ASGN;
5585 }
5586 pushback(p, c);
5587 if (IS_SPCARG(c)) {
5588 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
5589 return tREGEXP_BEG;
5590 }
5591 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5592 p->lstate = EXPR_ARG;
5593 }
5594 else {
5595 p->lstate = EXPR_BEG;
5596 }
5597 return '/';
5598
5599 case '^':
5600 if ((c = nextc(p)) == '=') {
5601 pylval.id = intern_lit("^");
5602 p->lstate = EXPR_BEG;
5603 return tOP_ASGN;
5604 }
5605 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5606 p->lstate = EXPR_ARG;
5607 }
5608 else {
5609 p->lstate = EXPR_BEG;
5610 }
5611 pushback(p, c);
5612 return '^';
5613
5614 case ';':
5615 p->lstate = EXPR_BEG;
5616 return ';';
5617
5618 case ',':
5619 p->lstate = EXPR_BEG;
5620 return ',';
5621
5622 case '~':
5623 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5624 if ((c = nextc(p)) != '@') {
5625 pushback(p, c);
5626 }
5627 p->lstate = EXPR_ARG;
5628 }
5629 else {
5630 p->lstate = EXPR_BEG;
5631 }
5632 return '~';
5633
5634 case '(':
5635 if (IS_BEG()) {
5636 c = tLPAREN;
5637 }
5638 else if (IS_SPCARG(-1)) {
5639 c = tLPAREN_ARG;
5640 }
5641 else if (p->lstate == EXPR_END && space_seen) {
5642 c = tLPAREN_ARG;
5643 }
5644 p->paren_nest++;
5645 COND_PUSH(0);
5646 CMDARG_PUSH(0);
5647 p->lstate = EXPR_BEG;
5648 return c;
5649
5650 case '[':
5651 p->paren_nest++;
5652 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5653 p->lstate = EXPR_ARG;
5654 if ((c = nextc(p)) == ']') {
5655 if ((c = nextc(p)) == '=') {
5656 return tASET;
5657 }
5658 pushback(p, c);
5659 return tAREF;
5660 }
5661 pushback(p, c);
5662 return '[';
5663 }
5664 else if (IS_BEG()) {
5665 c = tLBRACK;
5666 }
5667 else if (IS_ARG() && space_seen) {
5668 c = tLBRACK;
5669 }
5670 p->lstate = EXPR_BEG;
5671 COND_PUSH(0);
5672 CMDARG_PUSH(0);
5673 return c;
5674
5675 case '{':
5676 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
5677 p->lstate = EXPR_BEG;
5678 p->lpar_beg = 0;
5679 p->paren_nest--;
5680 COND_PUSH(0);
5681 CMDARG_PUSH(0);
5682 return tLAMBEG;
5683 }
5684 if (IS_ARG() || p->lstate == EXPR_END || p->lstate == EXPR_ENDFN)
5685 c = '{'; /* block (primary) */
5686 else if (p->lstate == EXPR_ENDARG)
5687 c = tLBRACE_ARG; /* block (expr) */
5688 else
5689 c = tLBRACE; /* hash */
5690 COND_PUSH(0);
5691 CMDARG_PUSH(0);
5692 p->lstate = EXPR_BEG;
5693 return c;
5694
5695 case '\\':
5696 c = nextc(p);
5697 if (c == '\n') {
5698 p->lineno++;
5699 p->column = 0;
5700 space_seen = 1;
5701 goto retry; /* skip \\n */
5702 }
5703 pushback(p, c);
5704 return '\\';
5705
5706 case '%':
5707 if (IS_BEG()) {
5708 int term;
5709 int paren;
5710
5711 c = nextc(p);
5712 quotation:
5713 if (c < 0 || !ISALNUM(c)) {
5714 term = c;
5715 c = 'Q';
5716 }
5717 else {
5718 term = nextc(p);
5719 if (ISALNUM(term)) {
5720 yyerror(p, "unknown type of %string");
5721 return 0;
5722 }
5723 }
5724 if (c < 0 || term < 0) {
5725 yyerror(p, "unterminated quoted string meets end of file");
5726 return 0;
5727 }
5728 paren = term;
5729 if (term == '(') term = ')';
5730 else if (term == '[') term = ']';
5731 else if (term == '{') term = '}';
5732 else if (term == '<') term = '>';
5733 else paren = 0;
5734
5735 switch (c) {
5736 case 'Q':
5737 p->lex_strterm = new_strterm(p, str_dquote, term, paren);
5738 return tSTRING_BEG;
5739
5740 case 'q':
5741 p->lex_strterm = new_strterm(p, str_squote, term, paren);
5742 return parse_string(p);
5743
5744 case 'W':
5745 p->lex_strterm = new_strterm(p, str_dword, term, paren);
5746 return tWORDS_BEG;
5747
5748 case 'w':
5749 p->lex_strterm = new_strterm(p, str_sword, term, paren);
5750 return tWORDS_BEG;
5751
5752 case 'x':
5753 p->lex_strterm = new_strterm(p, str_xquote, term, paren);
5754 return tXSTRING_BEG;
5755
5756 case 'r':
5757 p->lex_strterm = new_strterm(p, str_regexp, term, paren);
5758 return tREGEXP_BEG;
5759
5760 case 's':
5761 p->lex_strterm = new_strterm(p, str_ssym, term, paren);
5762 return tSYMBEG;
5763
5764 case 'I':
5765 p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
5766 return tSYMBOLS_BEG;
5767
5768 case 'i':
5769 p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
5770 return tSYMBOLS_BEG;
5771
5772 default:
5773 yyerror(p, "unknown type of %string");
5774 return 0;
5775 }
5776 }
5777 if ((c = nextc(p)) == '=') {
5778 pylval.id = intern_lit("%");
5779 p->lstate = EXPR_BEG;
5780 return tOP_ASGN;
5781 }
5782 if (IS_SPCARG(c)) {
5783 goto quotation;
5784 }
5785 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
5786 p->lstate = EXPR_ARG;
5787 }
5788 else {
5789 p->lstate = EXPR_BEG;
5790 }
5791 pushback(p, c);
5792 return '%';
5793
5794 case '$':
5795 p->lstate = EXPR_END;
5796 token_column = newtok(p);
5797 c = nextc(p);
5798 if (c < 0) {
5799 yyerror(p, "incomplete global variable syntax");
5800 return 0;
5801 }
5802 switch (c) {
5803 case '_': /* $_: last read line string */
5804 c = nextc(p);
5805 if (c >= 0 && identchar(c)) { /* if there is more after _ it is a variable */
5806 tokadd(p, '$');
5807 tokadd(p, c);
5808 break;
5809 }
5810 pushback(p, c);
5811 c = '_';
5812 /* fall through */
5813 case '~': /* $~: match-data */
5814 case '*': /* $*: argv */
5815 case '$': /* $$: pid */
5816 case '?': /* $?: last status */
5817 case '!': /* $!: error string */
5818 case '@': /* $@: error position */
5819 case '/': /* $/: input record separator */
5820 case '\\': /* $\: output record separator */
5821 case ';': /* $;: field separator */
5822 case ',': /* $,: output field separator */
5823 case '.': /* $.: last read line number */
5824 case '=': /* $=: ignorecase */
5825 case ':': /* $:: load path */
5826 case '<': /* $<: reading filename */
5827 case '>': /* $>: default output handle */
5828 case '\"': /* $": already loaded files */
5829 tokadd(p, '$');
5830 tokadd(p, c);
5831 tokfix(p);
5832 pylval.id = intern(tok(p), toklen(p));
5833 return tGVAR;
5834
5835 case '-':
5836 tokadd(p, '$');
5837 tokadd(p, c);
5838 c = nextc(p);
5839 pushback(p, c);
5840 gvar:
5841 tokfix(p);
5842 pylval.id = intern(tok(p), toklen(p));
5843 return tGVAR;
5844
5845 case '&': /* $&: last match */
5846 case '`': /* $`: string before last match */
5847 case '\'': /* $': string after last match */
5848 case '+': /* $+: string matches last pattern */
5849 if (last_state == EXPR_FNAME) {
5850 tokadd(p, '$');
5851 tokadd(p, c);
5852 goto gvar;
5853 }
5854 pylval.nd = new_back_ref(p, c);
5855 return tBACK_REF;
5856
5857 case '1': case '2': case '3':
5858 case '4': case '5': case '6':
5859 case '7': case '8': case '9':
5860 do {
5861 tokadd(p, c);
5862 c = nextc(p);
5863 } while (c >= 0 && ISDIGIT(c));
5864 pushback(p, c);
5865 if (last_state == EXPR_FNAME) goto gvar;
5866 tokfix(p);
5867 {
5868 unsigned long n = strtoul(tok(p), NULL, 10);
5869 if (n > INT_MAX) {
5870 yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX));
5871 return 0;
5872 }
5873 pylval.nd = new_nth_ref(p, (int)n);
5874 }
5875 return tNTH_REF;
5876
5877 default:
5878 if (!identchar(c)) {
5879 pushback(p, c);
5880 return '$';
5881 }
5882 /* fall through */
5883 case '0':
5884 tokadd(p, '$');
5885 }
5886 break;
5887
5888 case '@':
5889 c = nextc(p);
5890 token_column = newtok(p);
5891 tokadd(p, '@');
5892 if (c == '@') {
5893 tokadd(p, '@');
5894 c = nextc(p);
5895 }
5896 if (c < 0) {
5897 if (p->tidx == 1) {
5898 yyerror(p, "incomplete instance variable syntax");
5899 }
5900 else {
5901 yyerror(p, "incomplete class variable syntax");
5902 }
5903 return 0;
5904 }
5905 else if (ISDIGIT(c)) {
5906 if (p->tidx == 1) {
5907 yyerror_c(p, "wrong instance variable name: @", c);
5908 }
5909 else {
5910 yyerror_c(p, "wrong class variable name: @@", c);
5911 }
5912 return 0;
5913 }
5914 if (!identchar(c)) {
5915 pushback(p, c);
5916 return '@';
5917 }
5918 break;
5919
5920 case '_':
5921 token_column = newtok(p);
5922 break;
5923
5924 default:
5925 if (!identchar(c)) {
5926 char buf[36];
5927 const char s[] = "Invalid char in expression: 0x";
5928 const char hexdigits[] = "0123456789ABCDEF";
5929
5930 strcpy(buf, s);
5931 buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4];
5932 buf[sizeof(s)] = hexdigits[(c & 0x0f)];
5933 buf[sizeof(s)+1] = 0;
5934 yyerror(p, buf);
5935 goto retry;
5936 }
5937
5938 token_column = newtok(p);
5939 break;
5940 }
5941
5942 do {
5943 tokadd(p, c);
5944 c = nextc(p);
5945 if (c < 0) break;
5946 } while (identchar(c));
5947 if (token_column == 0 && toklen(p) == 7 && (c < 0 || c == '\n') &&
5948 strncmp(tok(p), "__END__", toklen(p)) == 0)
5949 return -1;
5950
5951 switch (tok(p)[0]) {
5952 case '@': case '$':
5953 pushback(p, c);
5954 break;
5955 default:
5956 if ((c == '!' || c == '?') && !peek(p, '=')) {
5957 tokadd(p, c);
5958 }
5959 else {
5960 pushback(p, c);
5961 }
5962 }
5963 tokfix(p);
5964 {
5965 int result = 0;
5966
5967 switch (tok(p)[0]) {
5968 case '$':
5969 p->lstate = EXPR_END;
5970 result = tGVAR;
5971 break;
5972 case '@':
5973 p->lstate = EXPR_END;
5974 if (tok(p)[1] == '@')
5975 result = tCVAR;
5976 else
5977 result = tIVAR;
5978 break;
5979
5980 case '_':
5981 if (toklen(p) == 2 && ISDIGIT(tok(p)[1]) && p->nvars) {
5982 int n = tok(p)[1] - '0';
5983 int nvar;
5984
5985 if (n > 0) {
5986 node *nvars = p->nvars->cdr;
5987
5988 while (nvars) {
5989 nvar = intn(nvars->car);
5990 if (nvar == -2) break; /* top of the scope */
5991 if (nvar > 0) {
5992 yywarning(p, "numbered parameter used in outer block");
5993 break;
5994 }
5995 nvars->car = nint(-1);
5996 nvars = nvars->cdr;
5997 }
5998 nvar = intn(p->nvars->car);
5999 if (nvar == -1) {
6000 yywarning(p, "numbered parameter used in inner block");
6001 }
6002 if (nvar >= -1) {
6003 pylval.num = n;
6004 p->lstate = EXPR_END;
6005 return tNUMPARAM;
6006 }
6007 else {
6008 yywarning(p, "identifier for numbered parameter; consider another name");
6009 }
6010 }
6011 }
6012 /* fall through */
6013 default:
6014 if (toklast(p) == '!' || toklast(p) == '?') {
6015 result = tFID;
6016 }
6017 else {
6018 if (p->lstate == EXPR_FNAME) {
6019 if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
6020 (!peek(p, '=') || (peek_n(p, '>', 1)))) {
6021 result = tIDENTIFIER;
6022 tokadd(p, c);
6023 tokfix(p);
6024 }
6025 else {
6026 pushback(p, c);
6027 }
6028 if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
6029 (!peek(p, '=') || (peek_n(p, '>', 1)))) {
6030 result = tIDENTIFIER;
6031 tokadd(p, c);
6032 tokfix(p);
6033 }
6034 else {
6035 pushback(p, c);
6036 }
6037 }
6038 if (result == 0 && ISUPPER(tok(p)[0])) {
6039 result = tCONSTANT;
6040 }
6041 else {
6042 result = tIDENTIFIER;
6043 }
6044 }
6045
6046 if (IS_LABEL_POSSIBLE()) {
6047 if (IS_LABEL_SUFFIX(0)) {
6048 p->lstate = EXPR_END;
6049 tokfix(p);
6050 pylval.id = intern(tok(p), toklen(p));
6051 return tIDENTIFIER;
6052 }
6053 }
6054 if (p->lstate != EXPR_DOT) {
6055 const struct kwtable *kw;
6056
6057 /* See if it is a reserved word. */
6058 kw = mrb_reserved_word(tok(p), toklen(p));
6059 if (kw) {
6060 enum mrb_lex_state_enum state = p->lstate;
6061 pylval.num = p->lineno;
6062 p->lstate = kw->state;
6063 if (state == EXPR_FNAME) {
6064 pylval.id = intern_cstr(kw->name);
6065 return kw->id[0];
6066 }
6067 if (p->lstate == EXPR_BEG) {
6068 p->cmd_start = TRUE;
6069 }
6070 if (kw->id[0] == keyword_do) {
6071 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
6072 p->lpar_beg = 0;
6073 p->paren_nest--;
6074 return keyword_do_LAMBDA;
6075 }
6076 if (COND_P()) return keyword_do_cond;
6077 if (CMDARG_P() && state != EXPR_CMDARG)
6078 return keyword_do_block;
6079 if (state == EXPR_ENDARG || state == EXPR_BEG)
6080 return keyword_do_block;
6081 return keyword_do;
6082 }
6083 if (state == EXPR_BEG || state == EXPR_VALUE)
6084 return kw->id[0];
6085 else {
6086 if (kw->id[0] != kw->id[1])
6087 p->lstate = EXPR_BEG;
6088 return kw->id[1];
6089 }
6090 }
6091 }
6092
6093 if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
6094 if (cmd_state) {
6095 p->lstate = EXPR_CMDARG;
6096 }
6097 else {
6098 p->lstate = EXPR_ARG;
6099 }
6100 }
6101 else if (p->lstate == EXPR_FNAME) {
6102 p->lstate = EXPR_ENDFN;
6103 }
6104 else {
6105 p->lstate = EXPR_END;
6106 }
6107 }
6108 {
6109 mrb_sym ident = intern(tok(p), toklen(p));
6110
6111 pylval.id = ident;
6112 if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
6113 p->lstate = EXPR_END;
6114 }
6115 }
6116 return result;
6117 }
6118}
6119
6120static int
6121yylex(void *lval, parser_state *p)
6122{
6123 p->ylval = lval;
6124 return parser_yylex(p);
6125}
6126
6127static void
6128parser_init_cxt(parser_state *p, mrbc_context *cxt)
6129{
6130 if (!cxt) return;
6131 if (cxt->filename) mrb_parser_set_filename(p, cxt->filename);
6132 if (cxt->lineno) p->lineno = cxt->lineno;
6133 if (cxt->syms) {
6134 int i;
6135
6136 p->locals = cons(0,0);
6137 for (i=0; i<cxt->slen; i++) {
6138 local_add_f(p, cxt->syms[i]);
6139 }
6140 }
6141 p->capture_errors = cxt->capture_errors;
6142 p->no_optimize = cxt->no_optimize;
6143 p->on_eval = cxt->on_eval;
6144 if (cxt->partial_hook) {
6145 p->cxt = cxt;
6146 }
6147}
6148
6149static void
6150parser_update_cxt(parser_state *p, mrbc_context *cxt)
6151{
6152 node *n, *n0;
6153 int i = 0;
6154
6155 if (!cxt) return;
6156 if (intn(p->tree->car) != NODE_SCOPE) return;
6157 n0 = n = p->tree->cdr->car;
6158 while (n) {
6159 i++;
6160 n = n->cdr;
6161 }
6162 cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
6163 cxt->slen = i;
6164 for (i=0, n=n0; n; i++,n=n->cdr) {
6165 cxt->syms[i] = sym(n->car);
6166 }
6167}
6168
6169void mrb_codedump_all(mrb_state*, struct RProc*);
6170void mrb_parser_dump(mrb_state *mrb, node *tree, int offset);
6171
6172MRB_API void
6173mrb_parser_parse(parser_state *p, mrbc_context *c)
6174{
6175 struct mrb_jmpbuf buf1;
6176 p->jmp = &buf1;
6177
6178 MRB_TRY(p->jmp) {
6179 int n = 1;
6180
6181 p->cmd_start = TRUE;
6182 p->in_def = p->in_single = 0;
6183 p->nerr = p->nwarn = 0;
6184 p->lex_strterm = NULL;
6185
6186 parser_init_cxt(p, c);
6187
6188 if (p->mrb->jmp) {
6189 n = yyparse(p);
6190 }
6191 else {
6192 struct mrb_jmpbuf buf2;
6193
6194 p->mrb->jmp = &buf2;
6195 MRB_TRY(p->mrb->jmp) {
6196 n = yyparse(p);
6197 }
6198 MRB_CATCH(p->mrb->jmp) {
6199 p->nerr++;
6200 }
6201 MRB_END_EXC(p->mrb->jmp);
6202 p->mrb->jmp = 0;
6203 }
6204 if (n != 0 || p->nerr > 0) {
6205 p->tree = 0;
6206 return;
6207 }
6208 if (!p->tree) {
6209 p->tree = new_nil(p);
6210 }
6211 parser_update_cxt(p, c);
6212 if (c && c->dump_result) {
6213 mrb_parser_dump(p->mrb, p->tree, 0);
6214 }
6215 }
6216 MRB_CATCH(p->jmp) {
6217 yyerror(p, "memory allocation error");
6218 p->nerr++;
6219 p->tree = 0;
6220 return;
6221 }
6222 MRB_END_EXC(p->jmp);
6223}
6224
6225MRB_API parser_state*
6226mrb_parser_new(mrb_state *mrb)
6227{
6228 mrb_pool *pool;
6229 parser_state *p;
6230 static const parser_state parser_state_zero = { 0 };
6231
6232 pool = mrb_pool_open(mrb);
6233 if (!pool) return NULL;
6234 p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state));
6235 if (!p) return NULL;
6236
6237 *p = parser_state_zero;
6238 p->mrb = mrb;
6239 p->pool = pool;
6240
6241 p->s = p->send = NULL;
6242#ifndef MRB_DISABLE_STDIO
6243 p->f = NULL;
6244#endif
6245
6246 p->cmd_start = TRUE;
6247 p->in_def = p->in_single = 0;
6248
6249 p->capture_errors = FALSE;
6250 p->lineno = 1;
6251 p->column = 0;
6252#if defined(PARSER_TEST) || defined(PARSER_DEBUG)
6253 yydebug = 1;
6254#endif
6255 p->tsiz = MRB_PARSER_TOKBUF_SIZE;
6256 p->tokbuf = p->buf;
6257
6258 p->lex_strterm = NULL;
6259 p->all_heredocs = p->parsing_heredoc = NULL;
6260 p->lex_strterm_before_heredoc = NULL;
6261
6262 p->current_filename_index = -1;
6263 p->filename_table = NULL;
6264 p->filename_table_length = 0;
6265
6266 return p;
6267}
6268
6269MRB_API void
6270mrb_parser_free(parser_state *p) {
6271 if (p->tokbuf != p->buf) {
6272 mrb_free(p->mrb, p->tokbuf);
6273 }
6274 mrb_pool_close(p->pool);
6275}
6276
6277MRB_API mrbc_context*
6278mrbc_context_new(mrb_state *mrb)
6279{
6280 return (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context));
6281}
6282
6283MRB_API void
6284mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
6285{
6286 mrb_free(mrb, cxt->filename);
6287 mrb_free(mrb, cxt->syms);
6288 mrb_free(mrb, cxt);
6289}
6290
6291MRB_API const char*
6292mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
6293{
6294 if (s) {
6295 size_t len = strlen(s);
6296 char *p = (char *)mrb_malloc(mrb, len + 1);
6297
6298 memcpy(p, s, len + 1);
6299 if (c->filename) {
6300 mrb_free(mrb, c->filename);
6301 }
6302 c->filename = p;
6303 }
6304 return c->filename;
6305}
6306
6307MRB_API void
6308mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data)
6309{
6310 c->partial_hook = func;
6311 c->partial_data = data;
6312}
6313
6314MRB_API void
6315mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
6316{
6317 mrb_sym sym;
6318 size_t i;
6319 mrb_sym* new_table;
6320
6321 sym = mrb_intern_cstr(p->mrb, f);
6322 p->filename_sym = sym;
6323 p->lineno = (p->filename_table_length > 0)? 0 : 1;
6324
6325 for (i = 0; i < p->filename_table_length; ++i) {
6326 if (p->filename_table[i] == sym) {
6327 p->current_filename_index = (int)i;
6328 return;
6329 }
6330 }
6331
6332 if (p->filename_table_length == UINT16_MAX) {
6333 yyerror(p, "too many files to compile");
6334 return;
6335 }
6336 p->current_filename_index = p->filename_table_length++;
6337
6338 new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
6339 if (p->filename_table) {
6340 memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->current_filename_index);
6341 }
6342 p->filename_table = new_table;
6343 p->filename_table[p->filename_table_length - 1] = sym;
6344}
6345
6346MRB_API mrb_sym
6347mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
6348 if (idx >= p->filename_table_length) return 0;
6349 else {
6350 return p->filename_table[idx];
6351 }
6352}
6353
6354#ifndef MRB_DISABLE_STDIO
6355MRB_API parser_state*
6356mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
6357{
6358 parser_state *p;
6359
6360 p = mrb_parser_new(mrb);
6361 if (!p) return NULL;
6362 p->s = p->send = NULL;
6363 p->f = f;
6364
6365 mrb_parser_parse(p, c);
6366 return p;
6367}
6368#endif
6369
6370MRB_API parser_state*
6371mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
6372{
6373 parser_state *p;
6374
6375 p = mrb_parser_new(mrb);
6376 if (!p) return NULL;
6377 p->s = s;
6378 p->send = s + len;
6379
6380 mrb_parser_parse(p, c);
6381 return p;
6382}
6383
6384MRB_API parser_state*
6385mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
6386{
6387 return mrb_parse_nstring(mrb, s, strlen(s), c);
6388}
6389
6390MRB_API mrb_value
6391mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
6392{
6393 struct RClass *target = mrb->object_class;
6394 struct RProc *proc;
6395 mrb_value v;
6396 unsigned int keep = 0;
6397
6398 if (!p) {
6399 return mrb_undef_value();
6400 }
6401 if (!p->tree || p->nerr) {
6402 if (c) c->parser_nerr = p->nerr;
6403 if (p->capture_errors) {
6404 char buf[256];
6405
6406 strcpy(buf, "line ");
6407 dump_int(p->error_buffer[0].lineno, buf+5);
6408 strcat(buf, ": ");
6409 strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1);
6410 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
6411 mrb_parser_free(p);
6412 return mrb_undef_value();
6413 }
6414 else {
6415 if (mrb->exc == NULL) {
6416 mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error"));
6417 }
6418 mrb_parser_free(p);
6419 return mrb_undef_value();
6420 }
6421 }
6422 proc = mrb_generate_code(mrb, p);
6423 mrb_parser_free(p);
6424 if (proc == NULL) {
6425 if (mrb->exc == NULL) {
6426 mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error"));
6427 }
6428 return mrb_undef_value();
6429 }
6430 if (c) {
6431 if (c->dump_result) mrb_codedump_all(mrb, proc);
6432 if (c->no_exec) return mrb_obj_value(proc);
6433 if (c->target_class) {
6434 target = c->target_class;
6435 }
6436 if (c->keep_lv) {
6437 keep = c->slen + 1;
6438 }
6439 else {
6440 c->keep_lv = TRUE;
6441 }
6442 }
6443 MRB_PROC_SET_TARGET_CLASS(proc, target);
6444 if (mrb->c->ci) {
6445 mrb->c->ci->target_class = target;
6446 }
6447 v = mrb_top_run(mrb, proc, mrb_top_self(mrb), keep);
6448 if (mrb->exc) return mrb_nil_value();
6449 return v;
6450}
6451
6452#ifndef MRB_DISABLE_STDIO
6453MRB_API mrb_value
6454mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
6455{
6456 return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c);
6457}
6458
6459MRB_API mrb_value
6460mrb_load_file(mrb_state *mrb, FILE *f)
6461{
6462 return mrb_load_file_cxt(mrb, f, NULL);
6463}
6464#endif
6465
6466MRB_API mrb_value
6467mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
6468{
6469 return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
6470}
6471
6472MRB_API mrb_value
6473mrb_load_nstring(mrb_state *mrb, const char *s, size_t len)
6474{
6475 return mrb_load_nstring_cxt(mrb, s, len, NULL);
6476}
6477
6478MRB_API mrb_value
6479mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
6480{
6481 return mrb_load_nstring_cxt(mrb, s, strlen(s), c);
6482}
6483
6484MRB_API mrb_value
6485mrb_load_string(mrb_state *mrb, const char *s)
6486{
6487 return mrb_load_string_cxt(mrb, s, NULL);
6488}
6489
6490#ifndef MRB_DISABLE_STDIO
6491
6492static void
6493dump_prefix(node *tree, int offset)
6494{
6495 printf("%05d ", tree->lineno);
6496 while (offset--) {
6497 putc(' ', stdout);
6498 putc(' ', stdout);
6499 }
6500}
6501
6502static void
6503dump_recur(mrb_state *mrb, node *tree, int offset)
6504{
6505 while (tree) {
6506 mrb_parser_dump(mrb, tree->car, offset);
6507 tree = tree->cdr;
6508 }
6509}
6510
6511static void
6512dump_args(mrb_state *mrb, node *n, int offset)
6513{
6514 if (n->car) {
6515 dump_prefix(n, offset+1);
6516 printf("mandatory args:\n");
6517 dump_recur(mrb, n->car, offset+2);
6518 }
6519 n = n->cdr;
6520 if (n->car) {
6521 dump_prefix(n, offset+1);
6522 printf("optional args:\n");
6523 {
6524 node *n2 = n->car;
6525
6526 while (n2) {
6527 dump_prefix(n2, offset+2);
6528 printf("%s=\n", mrb_sym_name(mrb, sym(n2->car->car)));
6529 mrb_parser_dump(mrb, n2->car->cdr, offset+3);
6530 n2 = n2->cdr;
6531 }
6532 }
6533 }
6534 n = n->cdr;
6535 if (n->car) {
6536 dump_prefix(n, offset+1);
6537 printf("rest=*%s\n", mrb_sym_name(mrb, sym(n->car)));
6538 }
6539 n = n->cdr;
6540 if (n->car) {
6541 dump_prefix(n, offset+1);
6542 printf("post mandatory args:\n");
6543 dump_recur(mrb, n->car, offset+2);
6544 }
6545
6546 n = n->cdr;
6547 if (n) {
6548 mrb_assert(intn(n->car) == NODE_ARGS_TAIL);
6549 mrb_parser_dump(mrb, n, offset);
6550 }
6551}
6552
6553/*
6554 * This function restores the GC arena on return.
6555 * For this reason, if a process that further generates an object is
6556 * performed at the caller, the string pointer returned as the return
6557 * value may become invalid.
6558 */
6559static const char*
6560str_dump(mrb_state *mrb, const char *str, int len)
6561{
6562 mrb_int ai = mrb_gc_arena_save(mrb);
6563 mrb_value s;
6564# if INT_MAX > MRB_INT_MAX / 4
6565 /* check maximum length with "\xNN" charactor */
6566 if (len > MRB_INT_MAX / 4) {
6567 len = MRB_INT_MAX / 4;
6568 }
6569# endif
6570 s = mrb_str_new(mrb, str, (mrb_int)len);
6571 s = mrb_str_dump(mrb, s);
6572 mrb_gc_arena_restore(mrb, ai);
6573 return RSTRING_PTR(s);
6574}
6575#endif
6576
6577void
6578mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
6579{
6580#ifndef MRB_DISABLE_STDIO
6581 int nodetype;
6582
6583 if (!tree) return;
6584 again:
6585 dump_prefix(tree, offset);
6586 nodetype = intn(tree->car);
6587 tree = tree->cdr;
6588 switch (nodetype) {
6589 case NODE_BEGIN:
6590 printf("NODE_BEGIN:\n");
6591 dump_recur(mrb, tree, offset+1);
6592 break;
6593
6594 case NODE_RESCUE:
6595 printf("NODE_RESCUE:\n");
6596 if (tree->car) {
6597 dump_prefix(tree, offset+1);
6598 printf("body:\n");
6599 mrb_parser_dump(mrb, tree->car, offset+2);
6600 }
6601 tree = tree->cdr;
6602 if (tree->car) {
6603 node *n2 = tree->car;
6604
6605 dump_prefix(n2, offset+1);
6606 printf("rescue:\n");
6607 while (n2) {
6608 node *n3 = n2->car;
6609 if (n3->car) {
6610 dump_prefix(n2, offset+2);
6611 printf("handle classes:\n");
6612 dump_recur(mrb, n3->car, offset+3);
6613 }
6614 if (n3->cdr->car) {
6615 dump_prefix(n3, offset+2);
6616 printf("exc_var:\n");
6617 mrb_parser_dump(mrb, n3->cdr->car, offset+3);
6618 }
6619 if (n3->cdr->cdr->car) {
6620 dump_prefix(n3, offset+2);
6621 printf("rescue body:\n");
6622 mrb_parser_dump(mrb, n3->cdr->cdr->car, offset+3);
6623 }
6624 n2 = n2->cdr;
6625 }
6626 }
6627 tree = tree->cdr;
6628 if (tree->car) {
6629 dump_prefix(tree, offset+1);
6630 printf("else:\n");
6631 mrb_parser_dump(mrb, tree->car, offset+2);
6632 }
6633 break;
6634
6635 case NODE_ENSURE:
6636 printf("NODE_ENSURE:\n");
6637 dump_prefix(tree, offset+1);
6638 printf("body:\n");
6639 mrb_parser_dump(mrb, tree->car, offset+2);
6640 dump_prefix(tree, offset+1);
6641 printf("ensure:\n");
6642 mrb_parser_dump(mrb, tree->cdr->cdr, offset+2);
6643 break;
6644
6645 case NODE_LAMBDA:
6646 printf("NODE_LAMBDA:\n");
6647 dump_prefix(tree, offset);
6648 goto block;
6649
6650 case NODE_BLOCK:
6651 block:
6652 printf("NODE_BLOCK:\n");
6653 tree = tree->cdr;
6654 if (tree->car) {
6655 dump_args(mrb, tree->car, offset+1);
6656 }
6657 dump_prefix(tree, offset+1);
6658 printf("body:\n");
6659 mrb_parser_dump(mrb, tree->cdr->car, offset+2);
6660 break;
6661
6662 case NODE_IF:
6663 printf("NODE_IF:\n");
6664 dump_prefix(tree, offset+1);
6665 printf("cond:\n");
6666 mrb_parser_dump(mrb, tree->car, offset+2);
6667 dump_prefix(tree, offset+1);
6668 printf("then:\n");
6669 mrb_parser_dump(mrb, tree->cdr->car, offset+2);
6670 if (tree->cdr->cdr->car) {
6671 dump_prefix(tree, offset+1);
6672 printf("else:\n");
6673 mrb_parser_dump(mrb, tree->cdr->cdr->car, offset+2);
6674 }
6675 break;
6676
6677 case NODE_AND:
6678 printf("NODE_AND:\n");
6679 mrb_parser_dump(mrb, tree->car, offset+1);
6680 mrb_parser_dump(mrb, tree->cdr, offset+1);
6681 break;
6682
6683 case NODE_OR:
6684 printf("NODE_OR:\n");
6685 mrb_parser_dump(mrb, tree->car, offset+1);
6686 mrb_parser_dump(mrb, tree->cdr, offset+1);
6687 break;
6688
6689 case NODE_CASE:
6690 printf("NODE_CASE:\n");
6691 if (tree->car) {
6692 mrb_parser_dump(mrb, tree->car, offset+1);
6693 }
6694 tree = tree->cdr;
6695 while (tree) {
6696 dump_prefix(tree, offset+1);
6697 printf("case:\n");
6698 dump_recur(mrb, tree->car->car, offset+2);
6699 dump_prefix(tree, offset+1);
6700 printf("body:\n");
6701 mrb_parser_dump(mrb, tree->car->cdr, offset+2);
6702 tree = tree->cdr;
6703 }
6704 break;
6705
6706 case NODE_WHILE:
6707 printf("NODE_WHILE:\n");
6708 dump_prefix(tree, offset+1);
6709 printf("cond:\n");
6710 mrb_parser_dump(mrb, tree->car, offset+2);
6711 dump_prefix(tree, offset+1);
6712 printf("body:\n");
6713 mrb_parser_dump(mrb, tree->cdr, offset+2);
6714 break;
6715
6716 case NODE_UNTIL:
6717 printf("NODE_UNTIL:\n");
6718 dump_prefix(tree, offset+1);
6719 printf("cond:\n");
6720 mrb_parser_dump(mrb, tree->car, offset+2);
6721 dump_prefix(tree, offset+1);
6722 printf("body:\n");
6723 mrb_parser_dump(mrb, tree->cdr, offset+2);
6724 break;
6725
6726 case NODE_FOR:
6727 printf("NODE_FOR:\n");
6728 dump_prefix(tree, offset+1);
6729 printf("var:\n");
6730 {
6731 node *n2 = tree->car;
6732
6733 if (n2->car) {
6734 dump_prefix(n2, offset+2);
6735 printf("pre:\n");
6736 dump_recur(mrb, n2->car, offset+3);
6737 }
6738 n2 = n2->cdr;
6739 if (n2) {
6740 if (n2->car) {
6741 dump_prefix(n2, offset+2);
6742 printf("rest:\n");
6743 mrb_parser_dump(mrb, n2->car, offset+3);
6744 }
6745 n2 = n2->cdr;
6746 if (n2) {
6747 if (n2->car) {
6748 dump_prefix(n2, offset+2);
6749 printf("post:\n");
6750 dump_recur(mrb, n2->car, offset+3);
6751 }
6752 }
6753 }
6754 }
6755 tree = tree->cdr;
6756 dump_prefix(tree, offset+1);
6757 printf("in:\n");
6758 mrb_parser_dump(mrb, tree->car, offset+2);
6759 tree = tree->cdr;
6760 dump_prefix(tree, offset+1);
6761 printf("do:\n");
6762 mrb_parser_dump(mrb, tree->car, offset+2);
6763 break;
6764
6765 case NODE_SCOPE:
6766 printf("NODE_SCOPE:\n");
6767 {
6768 node *n2 = tree->car;
6769 mrb_bool first_lval = TRUE;
6770
6771 if (n2 && (n2->car || n2->cdr)) {
6772 dump_prefix(n2, offset+1);
6773 printf("local variables:\n");
6774 dump_prefix(n2, offset+2);
6775 while (n2) {
6776 if (n2->car) {
6777 if (!first_lval) printf(", ");
6778 printf("%s", mrb_sym_name(mrb, sym(n2->car)));
6779 first_lval = FALSE;
6780 }
6781 n2 = n2->cdr;
6782 }
6783 printf("\n");
6784 }
6785 }
6786 tree = tree->cdr;
6787 offset++;
6788 goto again;
6789
6790 case NODE_FCALL:
6791 case NODE_CALL:
6792 case NODE_SCALL:
6793 switch (nodetype) {
6794 case NODE_FCALL:
6795 printf("NODE_FCALL:\n"); break;
6796 case NODE_CALL:
6797 printf("NODE_CALL(.):\n"); break;
6798 case NODE_SCALL:
6799 printf("NODE_SCALL(&.):\n"); break;
6800 default:
6801 break;
6802 }
6803 mrb_parser_dump(mrb, tree->car, offset+1);
6804 dump_prefix(tree, offset+1);
6805 printf("method='%s' (%d)\n",
6806 mrb_sym_dump(mrb, sym(tree->cdr->car)),
6807 intn(tree->cdr->car));
6808 tree = tree->cdr->cdr->car;
6809 if (tree) {
6810 dump_prefix(tree, offset+1);
6811 printf("args:\n");
6812 dump_recur(mrb, tree->car, offset+2);
6813 if (tree->cdr) {
6814 dump_prefix(tree, offset+1);
6815 printf("block:\n");
6816 mrb_parser_dump(mrb, tree->cdr, offset+2);
6817 }
6818 }
6819 break;
6820
6821 case NODE_DOT2:
6822 printf("NODE_DOT2:\n");
6823 mrb_parser_dump(mrb, tree->car, offset+1);
6824 mrb_parser_dump(mrb, tree->cdr, offset+1);
6825 break;
6826
6827 case NODE_DOT3:
6828 printf("NODE_DOT3:\n");
6829 mrb_parser_dump(mrb, tree->car, offset+1);
6830 mrb_parser_dump(mrb, tree->cdr, offset+1);
6831 break;
6832
6833 case NODE_COLON2:
6834 printf("NODE_COLON2:\n");
6835 mrb_parser_dump(mrb, tree->car, offset+1);
6836 dump_prefix(tree, offset+1);
6837 printf("::%s\n", mrb_sym_name(mrb, sym(tree->cdr)));
6838 break;
6839
6840 case NODE_COLON3:
6841 printf("NODE_COLON3: ::%s\n", mrb_sym_name(mrb, sym(tree)));
6842 break;
6843
6844 case NODE_ARRAY:
6845 printf("NODE_ARRAY:\n");
6846 dump_recur(mrb, tree, offset+1);
6847 break;
6848
6849 case NODE_HASH:
6850 printf("NODE_HASH:\n");
6851 while (tree) {
6852 dump_prefix(tree, offset+1);
6853 printf("key:\n");
6854 mrb_parser_dump(mrb, tree->car->car, offset+2);
6855 dump_prefix(tree, offset+1);
6856 printf("value:\n");
6857 mrb_parser_dump(mrb, tree->car->cdr, offset+2);
6858 tree = tree->cdr;
6859 }
6860 break;
6861
6862 case NODE_KW_HASH:
6863 printf("NODE_KW_HASH:\n");
6864 while (tree) {
6865 dump_prefix(tree, offset+1);
6866 printf("key:\n");
6867 mrb_parser_dump(mrb, tree->car->car, offset+2);
6868 dump_prefix(tree, offset+1);
6869 printf("value:\n");
6870 mrb_parser_dump(mrb, tree->car->cdr, offset+2);
6871 tree = tree->cdr;
6872 }
6873 break;
6874
6875 case NODE_SPLAT:
6876 printf("NODE_SPLAT:\n");
6877 mrb_parser_dump(mrb, tree, offset+1);
6878 break;
6879
6880 case NODE_ASGN:
6881 printf("NODE_ASGN:\n");
6882 dump_prefix(tree, offset+1);
6883 printf("lhs:\n");
6884 mrb_parser_dump(mrb, tree->car, offset+2);
6885 dump_prefix(tree, offset+1);
6886 printf("rhs:\n");
6887 mrb_parser_dump(mrb, tree->cdr, offset+2);
6888 break;
6889
6890 case NODE_MASGN:
6891 printf("NODE_MASGN:\n");
6892 dump_prefix(tree, offset+1);
6893 printf("mlhs:\n");
6894 {
6895 node *n2 = tree->car;
6896
6897 if (n2->car) {
6898 dump_prefix(tree, offset+2);
6899 printf("pre:\n");
6900 dump_recur(mrb, n2->car, offset+3);
6901 }
6902 n2 = n2->cdr;
6903 if (n2) {
6904 if (n2->car) {
6905 dump_prefix(n2, offset+2);
6906 printf("rest:\n");
6907 if (n2->car == (node*)-1) {
6908 dump_prefix(n2, offset+2);
6909 printf("(empty)\n");
6910 }
6911 else {
6912 mrb_parser_dump(mrb, n2->car, offset+3);
6913 }
6914 }
6915 n2 = n2->cdr;
6916 if (n2) {
6917 if (n2->car) {
6918 dump_prefix(n2, offset+2);
6919 printf("post:\n");
6920 dump_recur(mrb, n2->car, offset+3);
6921 }
6922 }
6923 }
6924 }
6925 dump_prefix(tree, offset+1);
6926 printf("rhs:\n");
6927 mrb_parser_dump(mrb, tree->cdr, offset+2);
6928 break;
6929
6930 case NODE_OP_ASGN:
6931 printf("NODE_OP_ASGN:\n");
6932 dump_prefix(tree, offset+1);
6933 printf("lhs:\n");
6934 mrb_parser_dump(mrb, tree->car, offset+2);
6935 tree = tree->cdr;
6936 dump_prefix(tree, offset+1);
6937 printf("op='%s' (%d)\n", mrb_sym_name(mrb, sym(tree->car)), intn(tree->car));
6938 tree = tree->cdr;
6939 mrb_parser_dump(mrb, tree->car, offset+1);
6940 break;
6941
6942 case NODE_SUPER:
6943 printf("NODE_SUPER:\n");
6944 if (tree) {
6945 dump_prefix(tree, offset+1);
6946 printf("args:\n");
6947 dump_recur(mrb, tree->car, offset+2);
6948 if (tree->cdr) {
6949 dump_prefix(tree, offset+1);
6950 printf("block:\n");
6951 mrb_parser_dump(mrb, tree->cdr, offset+2);
6952 }
6953 }
6954 break;
6955
6956 case NODE_ZSUPER:
6957 printf("NODE_ZSUPER\n");
6958 break;
6959
6960 case NODE_RETURN:
6961 printf("NODE_RETURN:\n");
6962 mrb_parser_dump(mrb, tree, offset+1);
6963 break;
6964
6965 case NODE_YIELD:
6966 printf("NODE_YIELD:\n");
6967 dump_recur(mrb, tree, offset+1);
6968 break;
6969
6970 case NODE_BREAK:
6971 printf("NODE_BREAK:\n");
6972 mrb_parser_dump(mrb, tree, offset+1);
6973 break;
6974
6975 case NODE_NEXT:
6976 printf("NODE_NEXT:\n");
6977 mrb_parser_dump(mrb, tree, offset+1);
6978 break;
6979
6980 case NODE_REDO:
6981 printf("NODE_REDO\n");
6982 break;
6983
6984 case NODE_RETRY:
6985 printf("NODE_RETRY\n");
6986 break;
6987
6988 case NODE_LVAR:
6989 printf("NODE_LVAR %s\n", mrb_sym_name(mrb, sym(tree)));
6990 break;
6991
6992 case NODE_GVAR:
6993 printf("NODE_GVAR %s\n", mrb_sym_name(mrb, sym(tree)));
6994 break;
6995
6996 case NODE_IVAR:
6997 printf("NODE_IVAR %s\n", mrb_sym_name(mrb, sym(tree)));
6998 break;
6999
7000 case NODE_CVAR:
7001 printf("NODE_CVAR %s\n", mrb_sym_name(mrb, sym(tree)));
7002 break;
7003
7004 case NODE_NVAR:
7005 printf("NODE_NVAR %d\n", intn(tree));
7006 break;
7007
7008 case NODE_CONST:
7009 printf("NODE_CONST %s\n", mrb_sym_name(mrb, sym(tree)));
7010 break;
7011
7012 case NODE_MATCH:
7013 printf("NODE_MATCH:\n");
7014 dump_prefix(tree, offset + 1);
7015 printf("lhs:\n");
7016 mrb_parser_dump(mrb, tree->car, offset + 2);
7017 dump_prefix(tree, offset + 1);
7018 printf("rhs:\n");
7019 mrb_parser_dump(mrb, tree->cdr, offset + 2);
7020 break;
7021
7022 case NODE_BACK_REF:
7023 printf("NODE_BACK_REF: $%c\n", intn(tree));
7024 break;
7025
7026 case NODE_NTH_REF:
7027 printf("NODE_NTH_REF: $%d\n", intn(tree));
7028 break;
7029
7030 case NODE_ARG:
7031 printf("NODE_ARG %s\n", mrb_sym_name(mrb, sym(tree)));
7032 break;
7033
7034 case NODE_BLOCK_ARG:
7035 printf("NODE_BLOCK_ARG:\n");
7036 mrb_parser_dump(mrb, tree, offset+1);
7037 break;
7038
7039 case NODE_INT:
7040 printf("NODE_INT %s base %d\n", (char*)tree->car, intn(tree->cdr->car));
7041 break;
7042
7043 case NODE_FLOAT:
7044 printf("NODE_FLOAT %s\n", (char*)tree);
7045 break;
7046
7047 case NODE_NEGATE:
7048 printf("NODE_NEGATE:\n");
7049 mrb_parser_dump(mrb, tree, offset+1);
7050 break;
7051
7052 case NODE_STR:
7053 printf("NODE_STR %s len %d\n", str_dump(mrb, (char*)tree->car, intn(tree->cdr)), intn(tree->cdr));
7054 break;
7055
7056 case NODE_DSTR:
7057 printf("NODE_DSTR:\n");
7058 dump_recur(mrb, tree, offset+1);
7059 break;
7060
7061 case NODE_XSTR:
7062 printf("NODE_XSTR %s len %d\n", str_dump(mrb, (char*)tree->car, intn(tree->cdr)), intn(tree->cdr));
7063 break;
7064
7065 case NODE_DXSTR:
7066 printf("NODE_DXSTR:\n");
7067 dump_recur(mrb, tree, offset+1);
7068 break;
7069
7070 case NODE_REGX:
7071 printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
7072 break;
7073
7074 case NODE_DREGX:
7075 printf("NODE_DREGX:\n");
7076 dump_recur(mrb, tree->car, offset+1);
7077 dump_prefix(tree, offset);
7078 printf("tail: %s\n", (char*)tree->cdr->cdr->car);
7079 if (tree->cdr->cdr->cdr->car) {
7080 dump_prefix(tree, offset);
7081 printf("opt: %s\n", (char*)tree->cdr->cdr->cdr->car);
7082 }
7083 if (tree->cdr->cdr->cdr->cdr) {
7084 dump_prefix(tree, offset);
7085 printf("enc: %s\n", (char*)tree->cdr->cdr->cdr->cdr);
7086 }
7087 break;
7088
7089 case NODE_SYM:
7090 printf("NODE_SYM :%s (%d)\n", mrb_sym_dump(mrb, sym(tree)),
7091 intn(tree));
7092 break;
7093
7094 case NODE_DSYM:
7095 printf("NODE_DSYM:\n");
7096 mrb_parser_dump(mrb, tree, offset+1);
7097 break;
7098
7099 case NODE_WORDS:
7100 printf("NODE_WORDS:\n");
7101 dump_recur(mrb, tree, offset+1);
7102 break;
7103
7104 case NODE_SYMBOLS:
7105 printf("NODE_SYMBOLS:\n");
7106 dump_recur(mrb, tree, offset+1);
7107 break;
7108
7109 case NODE_LITERAL_DELIM:
7110 printf("NODE_LITERAL_DELIM\n");
7111 break;
7112
7113 case NODE_SELF:
7114 printf("NODE_SELF\n");
7115 break;
7116
7117 case NODE_NIL:
7118 printf("NODE_NIL\n");
7119 break;
7120
7121 case NODE_TRUE:
7122 printf("NODE_TRUE\n");
7123 break;
7124
7125 case NODE_FALSE:
7126 printf("NODE_FALSE\n");
7127 break;
7128
7129 case NODE_ALIAS:
7130 printf("NODE_ALIAS %s %s:\n",
7131 mrb_sym_dump(mrb, sym(tree->car)),
7132 mrb_sym_dump(mrb, sym(tree->cdr)));
7133 break;
7134
7135 case NODE_UNDEF:
7136 printf("NODE_UNDEF");
7137 {
7138 node *t = tree;
7139 while (t) {
7140 printf(" %s", mrb_sym_dump(mrb, sym(t->car)));
7141 t = t->cdr;
7142 }
7143 }
7144 printf(":\n");
7145 break;
7146
7147 case NODE_CLASS:
7148 printf("NODE_CLASS:\n");
7149 if (tree->car->car == (node*)0) {
7150 dump_prefix(tree, offset+1);
7151 printf(":%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7152 }
7153 else if (tree->car->car == (node*)1) {
7154 dump_prefix(tree, offset+1);
7155 printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7156 }
7157 else {
7158 mrb_parser_dump(mrb, tree->car->car, offset+1);
7159 dump_prefix(tree, offset+1);
7160 printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7161 }
7162 if (tree->cdr->car) {
7163 dump_prefix(tree, offset+1);
7164 printf("super:\n");
7165 mrb_parser_dump(mrb, tree->cdr->car, offset+2);
7166 }
7167 dump_prefix(tree, offset+1);
7168 printf("body:\n");
7169 mrb_parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2);
7170 break;
7171
7172 case NODE_MODULE:
7173 printf("NODE_MODULE:\n");
7174 if (tree->car->car == (node*)0) {
7175 dump_prefix(tree, offset+1);
7176 printf(":%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7177 }
7178 else if (tree->car->car == (node*)1) {
7179 dump_prefix(tree, offset+1);
7180 printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7181 }
7182 else {
7183 mrb_parser_dump(mrb, tree->car->car, offset+1);
7184 dump_prefix(tree, offset+1);
7185 printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
7186 }
7187 dump_prefix(tree, offset+1);
7188 printf("body:\n");
7189 mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2);
7190 break;
7191
7192 case NODE_SCLASS:
7193 printf("NODE_SCLASS:\n");
7194 mrb_parser_dump(mrb, tree->car, offset+1);
7195 dump_prefix(tree, offset+1);
7196 printf("body:\n");
7197 mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2);
7198 break;
7199
7200 case NODE_DEF:
7201 printf("NODE_DEF:\n");
7202 dump_prefix(tree, offset+1);
7203 printf("%s\n", mrb_sym_dump(mrb, sym(tree->car)));
7204 tree = tree->cdr;
7205 {
7206 node *n2 = tree->car;
7207 mrb_bool first_lval = TRUE;
7208
7209 if (n2 && (n2->car || n2->cdr)) {
7210 dump_prefix(n2, offset+1);
7211 printf("local variables:\n");
7212 dump_prefix(n2, offset+2);
7213 while (n2) {
7214 if (n2->car) {
7215 if (!first_lval) printf(", ");
7216 printf("%s", mrb_sym_name(mrb, sym(n2->car)));
7217 first_lval = FALSE;
7218 }
7219 n2 = n2->cdr;
7220 }
7221 printf("\n");
7222 }
7223 }
7224 tree = tree->cdr;
7225 if (tree->car) {
7226 dump_args(mrb, tree->car, offset);
7227 }
7228 mrb_parser_dump(mrb, tree->cdr->car, offset+1);
7229 break;
7230
7231 case NODE_SDEF:
7232 printf("NODE_SDEF:\n");
7233 mrb_parser_dump(mrb, tree->car, offset+1);
7234 tree = tree->cdr;
7235 dump_prefix(tree, offset+1);
7236 printf(":%s\n", mrb_sym_dump(mrb, sym(tree->car)));
7237 tree = tree->cdr->cdr;
7238 if (tree->car) {
7239 dump_args(mrb, tree->car, offset+1);
7240 }
7241 tree = tree->cdr;
7242 mrb_parser_dump(mrb, tree->car, offset+1);
7243 break;
7244
7245 case NODE_POSTEXE:
7246 printf("NODE_POSTEXE:\n");
7247 mrb_parser_dump(mrb, tree, offset+1);
7248 break;
7249
7250 case NODE_HEREDOC:
7251 printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term);
7252 dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
7253 break;
7254
7255 case NODE_ARGS_TAIL:
7256 printf("NODE_ARGS_TAIL:\n");
7257 {
7258 node *kws = tree->car;
7259
7260 while (kws) {
7261 mrb_parser_dump(mrb, kws->car, offset+1);
7262 kws = kws->cdr;
7263 }
7264 }
7265 tree = tree->cdr;
7266 if (tree->car) {
7267 mrb_assert(intn(tree->car->car) == NODE_KW_REST_ARGS);
7268 mrb_parser_dump(mrb, tree->car, offset+1);
7269 }
7270 tree = tree->cdr;
7271 if (tree->car) {
7272 dump_prefix(tree, offset+1);
7273 printf("block='%s'\n", mrb_sym_name(mrb, sym(tree->car)));
7274 }
7275 break;
7276
7277 case NODE_KW_ARG:
7278 printf("NODE_KW_ARG %s:\n", mrb_sym_name(mrb, sym(tree->car)));
7279 mrb_parser_dump(mrb, tree->cdr->car, offset + 1);
7280 break;
7281
7282 case NODE_KW_REST_ARGS:
7283 printf("NODE_KW_REST_ARGS %s\n", mrb_sym_name(mrb, sym(tree)));
7284 break;
7285
7286 default:
7287 printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
7288 break;
7289 }
7290#endif
7291}
Note: See TracBrowser for help on using the repository browser.