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