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