source: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-compiler/core/parse.y@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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