source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-compiler/core/parse.y@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

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