Merge pull request #1039 from crimsonwoods/fix_the_type_of_opcode
[mruby.git] / src / parse.y
blob29ea34c59e32dca8fd4208048a025c5b0c64eff9
1 /*
2 ** parse.y - mruby parser
3 **
4 ** See Copyright Notice in mruby.h
5 */
7 %{
8 #undef PARSER_DEBUG
10 #define YYDEBUG 1
11 #define YYERROR_VERBOSE 1
13 * Force yacc to use our memory management. This is a little evil because
14 * the macros assume that "parser_state *p" is in scope
16 #define YYMALLOC(n) mrb_malloc(p->mrb, (n))
17 #define YYFREE(o) mrb_free(p->mrb, (o))
18 #define YYSTACK_USE_ALLOCA 0
20 #include "mruby.h"
21 #include "mruby/compile.h"
22 #include "mruby/proc.h"
23 #include "node.h"
25 #include <errno.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <stdlib.h>
30 #define YYLEX_PARAM p
32 typedef mrb_ast_node node;
33 typedef struct mrb_parser_state parser_state;
34 typedef struct mrb_parser_heredoc_info parser_heredoc_info;
36 static int yylex(void *lval, parser_state *p);
37 static void yyerror(parser_state *p, const char *s);
38 static void yywarn(parser_state *p, const char *s);
39 static void yywarning(parser_state *p, const char *s);
40 static void backref_error(parser_state *p, node *n);
42 #define identchar(c) (isalnum(c) || (c) == '_' || !isascii(c))
44 typedef unsigned int stack_type;
46 #define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
47 #define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
48 #define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
49 #define BITSTACK_SET_P(stack) ((stack)&1)
51 #define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n))
52 #define COND_POP() BITSTACK_POP(p->cond_stack)
53 #define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack)
54 #define COND_P() BITSTACK_SET_P(p->cond_stack)
56 #define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n))
57 #define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack)
58 #define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
59 #define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
61 #define sym(x) ((mrb_sym)(intptr_t)(x))
62 #define nsym(x) ((node*)(intptr_t)(x))
64 static inline mrb_sym
65 intern_gen(parser_state *p, const char *s)
67 return mrb_intern(p->mrb, s);
69 #define intern(s) intern_gen(p,(s))
71 static inline mrb_sym
72 intern_gen2(parser_state *p, const char *s, size_t len)
74 return mrb_intern2(p->mrb, s, len);
76 #define intern2(s,len) intern_gen2(p,(s),(len))
78 static inline mrb_sym
79 intern_gen_c(parser_state *p, const char c)
81 return mrb_intern2(p->mrb, &c, 1);
83 #define intern_c(c) intern_gen_c(p,(c))
85 static void
86 cons_free_gen(parser_state *p, node *cons)
88 cons->cdr = p->cells;
89 p->cells = cons;
91 #define cons_free(c) cons_free_gen(p, (c))
93 static void*
94 parser_palloc(parser_state *p, size_t size)
96 void *m = mrb_pool_alloc(p->pool, size);
98 if (!m) {
99 longjmp(p->jmp, 1);
101 return m;
104 static node*
105 cons_gen(parser_state *p, node *car, node *cdr)
107 node *c;
109 if (p->cells) {
110 c = p->cells;
111 p->cells = p->cells->cdr;
113 else {
114 c = (node *)parser_palloc(p, sizeof(mrb_ast_node));
117 c->car = car;
118 c->cdr = cdr;
119 c->lineno = p->lineno;
120 return c;
122 #define cons(a,b) cons_gen(p,(a),(b))
124 static node*
125 list1_gen(parser_state *p, node *a)
127 return cons(a, 0);
129 #define list1(a) list1_gen(p, (a))
131 static node*
132 list2_gen(parser_state *p, node *a, node *b)
134 return cons(a, cons(b,0));
136 #define list2(a,b) list2_gen(p, (a),(b))
138 static node*
139 list3_gen(parser_state *p, node *a, node *b, node *c)
141 return cons(a, cons(b, cons(c,0)));
143 #define list3(a,b,c) list3_gen(p, (a),(b),(c))
145 static node*
146 list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
148 return cons(a, cons(b, cons(c, cons(d, 0))));
150 #define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
152 static node*
153 list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
155 return cons(a, cons(b, cons(c, cons(d, cons(e, 0)))));
157 #define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
159 static node*
160 list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
162 return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
164 #define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
166 static node*
167 append_gen(parser_state *p, node *a, node *b)
169 node *c = a;
171 if (!a) return b;
172 while (c->cdr) {
173 c = c->cdr;
175 if (b) {
176 c->cdr = b;
178 return a;
180 #define append(a,b) append_gen(p,(a),(b))
181 #define push(a,b) append_gen(p,(a),list1(b))
183 static char*
184 parser_strndup(parser_state *p, const char *s, size_t len)
186 char *b = (char *)parser_palloc(p, len+1);
188 memcpy(b, s, len);
189 b[len] = '\0';
190 return b;
192 #define strndup(s,len) parser_strndup(p, s, len)
194 static char*
195 parser_strdup(parser_state *p, const char *s)
197 return parser_strndup(p, s, strlen(s));
199 #undef strdup
200 #define strdup(s) parser_strdup(p, s)
202 // xxx -----------------------------
204 static node*
205 local_switch(parser_state *p)
207 node *prev = p->locals;
209 p->locals = cons(0, 0);
210 return prev;
213 static void
214 local_resume(parser_state *p, node *prev)
216 p->locals = prev;
219 static void
220 local_nest(parser_state *p)
222 p->locals = cons(0, p->locals);
225 static void
226 local_unnest(parser_state *p)
228 p->locals = p->locals->cdr;
231 static int
232 local_var_p(parser_state *p, mrb_sym sym)
234 node *l = p->locals;
236 while (l) {
237 node *n = l->car;
238 while (n) {
239 if (sym(n->car) == sym) return 1;
240 n = n->cdr;
242 l = l->cdr;
244 return 0;
247 static void
248 local_add_f(parser_state *p, mrb_sym sym)
250 p->locals->car = push(p->locals->car, nsym(sym));
253 static void
254 local_add(parser_state *p, mrb_sym sym)
256 if (!local_var_p(p, sym)) {
257 local_add_f(p, sym);
261 // (:scope (vars..) (prog...))
262 static node*
263 new_scope(parser_state *p, node *body)
265 return cons((node*)NODE_SCOPE, cons(p->locals->car, body));
268 // (:begin prog...)
269 static node*
270 new_begin(parser_state *p, node *body)
272 if (body)
273 return list2((node*)NODE_BEGIN, body);
274 return cons((node*)NODE_BEGIN, 0);
277 #define newline_node(n) (n)
279 // (:rescue body rescue else)
280 static node*
281 new_rescue(parser_state *p, node *body, node *resq, node *els)
283 return list4((node*)NODE_RESCUE, body, resq, els);
286 // (:ensure body ensure)
287 static node*
288 new_ensure(parser_state *p, node *a, node *b)
290 return cons((node*)NODE_ENSURE, cons(a, cons(0, b)));
293 // (:nil)
294 static node*
295 new_nil(parser_state *p)
297 return list1((node*)NODE_NIL);
300 // (:true)
301 static node*
302 new_true(parser_state *p)
304 return list1((node*)NODE_TRUE);
307 // (:false)
308 static node*
309 new_false(parser_state *p)
311 return list1((node*)NODE_FALSE);
314 // (:alias new old)
315 static node*
316 new_alias(parser_state *p, mrb_sym a, mrb_sym b)
318 return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
321 // (:if cond then else)
322 static node*
323 new_if(parser_state *p, node *a, node *b, node *c)
325 return list4((node*)NODE_IF, a, b, c);
328 // (:unless cond then else)
329 static node*
330 new_unless(parser_state *p, node *a, node *b, node *c)
332 return list4((node*)NODE_IF, a, c, b);
335 // (:while cond body)
336 static node*
337 new_while(parser_state *p, node *a, node *b)
339 return cons((node*)NODE_WHILE, cons(a, b));
342 // (:until cond body)
343 static node*
344 new_until(parser_state *p, node *a, node *b)
346 return cons((node*)NODE_UNTIL, cons(a, b));
349 // (:for var obj body)
350 static node*
351 new_for(parser_state *p, node *v, node *o, node *b)
353 return list4((node*)NODE_FOR, v, o, b);
356 // (:case a ((when ...) body) ((when...) body))
357 static node*
358 new_case(parser_state *p, node *a, node *b)
360 node *n = list2((node*)NODE_CASE, a);
361 node *n2 = n;
363 while (n2->cdr) {
364 n2 = n2->cdr;
366 n2->cdr = b;
367 return n;
370 // (:postexe a)
371 static node*
372 new_postexe(parser_state *p, node *a)
374 return cons((node*)NODE_POSTEXE, a);
377 // (:self)
378 static node*
379 new_self(parser_state *p)
381 return list1((node*)NODE_SELF);
384 // (:call a b c)
385 static node*
386 new_call(parser_state *p, node *a, mrb_sym b, node *c)
388 return list4((node*)NODE_CALL, a, nsym(b), c);
391 // (:fcall self mid args)
392 static node*
393 new_fcall(parser_state *p, mrb_sym b, node *c)
395 return list4((node*)NODE_FCALL, new_self(p), nsym(b), c);
398 #if 0
399 // (:vcall self mid)
400 static node*
401 new_vcall(parser_state *p, mrb_sym b)
403 return list3((node*)NODE_VCALL, new_self(p), (node*)b);
405 #endif
407 // (:super . c)
408 static node*
409 new_super(parser_state *p, node *c)
411 return cons((node*)NODE_SUPER, c);
414 // (:zsuper)
415 static node*
416 new_zsuper(parser_state *p)
418 return list1((node*)NODE_ZSUPER);
421 // (:yield . c)
422 static node*
423 new_yield(parser_state *p, node *c)
425 if (c) {
426 if (c->cdr) {
427 yyerror(p, "both block arg and actual block given");
429 return cons((node*)NODE_YIELD, c->car);
431 return cons((node*)NODE_YIELD, 0);
434 // (:return . c)
435 static node*
436 new_return(parser_state *p, node *c)
438 return cons((node*)NODE_RETURN, c);
441 // (:break . c)
442 static node*
443 new_break(parser_state *p, node *c)
445 return cons((node*)NODE_BREAK, c);
448 // (:next . c)
449 static node*
450 new_next(parser_state *p, node *c)
452 return cons((node*)NODE_NEXT, c);
455 // (:redo)
456 static node*
457 new_redo(parser_state *p)
459 return list1((node*)NODE_REDO);
462 // (:retry)
463 static node*
464 new_retry(parser_state *p)
466 return list1((node*)NODE_RETRY);
469 // (:dot2 a b)
470 static node*
471 new_dot2(parser_state *p, node *a, node *b)
473 return cons((node*)NODE_DOT2, cons(a, b));
476 // (:dot3 a b)
477 static node*
478 new_dot3(parser_state *p, node *a, node *b)
480 return cons((node*)NODE_DOT3, cons(a, b));
483 // (:colon2 b c)
484 static node*
485 new_colon2(parser_state *p, node *b, mrb_sym c)
487 return cons((node*)NODE_COLON2, cons(b, nsym(c)));
490 // (:colon3 . c)
491 static node*
492 new_colon3(parser_state *p, mrb_sym c)
494 return cons((node*)NODE_COLON3, nsym(c));
497 // (:and a b)
498 static node*
499 new_and(parser_state *p, node *a, node *b)
501 return cons((node*)NODE_AND, cons(a, b));
504 // (:or a b)
505 static node*
506 new_or(parser_state *p, node *a, node *b)
508 return cons((node*)NODE_OR, cons(a, b));
511 // (:array a...)
512 static node*
513 new_array(parser_state *p, node *a)
515 return cons((node*)NODE_ARRAY, a);
518 // (:splat . a)
519 static node*
520 new_splat(parser_state *p, node *a)
522 return cons((node*)NODE_SPLAT, a);
525 // (:hash (k . v) (k . v)...)
526 static node*
527 new_hash(parser_state *p, node *a)
529 return cons((node*)NODE_HASH, a);
532 // (:sym . a)
533 static node*
534 new_sym(parser_state *p, mrb_sym sym)
536 return cons((node*)NODE_SYM, nsym(sym));
539 static mrb_sym
540 new_strsym(parser_state *p, node* str)
542 const char *s = (const char*)str->cdr->car;
543 size_t len = (size_t)str->cdr->cdr;
545 return mrb_intern2(p->mrb, s, len);
548 // (:lvar . a)
549 static node*
550 new_lvar(parser_state *p, mrb_sym sym)
552 return cons((node*)NODE_LVAR, nsym(sym));
555 // (:gvar . a)
556 static node*
557 new_gvar(parser_state *p, mrb_sym sym)
559 return cons((node*)NODE_GVAR, nsym(sym));
562 // (:ivar . a)
563 static node*
564 new_ivar(parser_state *p, mrb_sym sym)
566 return cons((node*)NODE_IVAR, nsym(sym));
569 // (:cvar . a)
570 static node*
571 new_cvar(parser_state *p, mrb_sym sym)
573 return cons((node*)NODE_CVAR, nsym(sym));
576 // (:const . a)
577 static node*
578 new_const(parser_state *p, mrb_sym sym)
580 return cons((node*)NODE_CONST, nsym(sym));
583 // (:undef a...)
584 static node*
585 new_undef(parser_state *p, mrb_sym sym)
587 return list2((node*)NODE_UNDEF, nsym(sym));
590 // (:class class super body)
591 static node*
592 new_class(parser_state *p, node *c, node *s, node *b)
594 return list4((node*)NODE_CLASS, c, s, cons(p->locals->car, b));
597 // (:sclass obj body)
598 static node*
599 new_sclass(parser_state *p, node *o, node *b)
601 return list3((node*)NODE_SCLASS, o, cons(p->locals->car, b));
604 // (:module module body)
605 static node*
606 new_module(parser_state *p, node *m, node *b)
608 return list3((node*)NODE_MODULE, m, cons(p->locals->car, b));
611 // (:def m lv (arg . body))
612 static node*
613 new_def(parser_state *p, mrb_sym m, node *a, node *b)
615 return list5((node*)NODE_DEF, nsym(m), p->locals->car, a, b);
618 // (:sdef obj m lv (arg . body))
619 static node*
620 new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
622 return list6((node*)NODE_SDEF, o, nsym(m), p->locals->car, a, b);
625 // (:arg . sym)
626 static node*
627 new_arg(parser_state *p, mrb_sym sym)
629 return cons((node*)NODE_ARG, nsym(sym));
632 // (m o r m2 b)
633 // m: (a b c)
634 // o: ((a . e1) (b . e2))
635 // r: a
636 // m2: (a b c)
637 // b: a
638 static node*
639 new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
641 node *n;
643 n = cons(m2, nsym(blk));
644 n = cons(nsym(rest), n);
645 n = cons(opt, n);
646 return cons(m, n);
649 // (:block_arg . a)
650 static node*
651 new_block_arg(parser_state *p, node *a)
653 return cons((node*)NODE_BLOCK_ARG, a);
656 // (:block arg body)
657 static node*
658 new_block(parser_state *p, node *a, node *b)
660 return list4((node*)NODE_BLOCK, p->locals->car, a, b);
663 // (:lambda arg body)
664 static node*
665 new_lambda(parser_state *p, node *a, node *b)
667 return list4((node*)NODE_LAMBDA, p->locals->car, a, b);
670 // (:asgn lhs rhs)
671 static node*
672 new_asgn(parser_state *p, node *a, node *b)
674 return cons((node*)NODE_ASGN, cons(a, b));
677 // (:masgn mlhs=(pre rest post) mrhs)
678 static node*
679 new_masgn(parser_state *p, node *a, node *b)
681 return cons((node*)NODE_MASGN, cons(a, b));
684 // (:asgn lhs rhs)
685 static node*
686 new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
688 return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
691 // (:int . i)
692 static node*
693 new_int(parser_state *p, const char *s, int base)
695 return list3((node*)NODE_INT, (node*)strdup(s), (node*)(intptr_t)base);
698 // (:float . i)
699 static node*
700 new_float(parser_state *p, const char *s)
702 return cons((node*)NODE_FLOAT, (node*)strdup(s));
705 // (:str . (s . len))
706 static node*
707 new_str(parser_state *p, const char *s, int len)
709 return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
712 // (:dstr . a)
713 static node*
714 new_dstr(parser_state *p, node *a)
716 return cons((node*)NODE_DSTR, a);
719 // (:str . (s . len))
720 static node*
721 new_xstr(parser_state *p, const char *s, int len)
723 return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
726 // (:xstr . a)
727 static node*
728 new_dxstr(parser_state *p, node *a)
730 return cons((node*)NODE_DXSTR, a);
733 // (:dsym . a)
734 static node*
735 new_dsym(parser_state *p, node *a)
737 return cons((node*)NODE_DSYM, new_dstr(p, a));
740 // (:str . (a . a))
741 static node*
742 new_regx(parser_state *p, const char *p1, const char* p2)
744 return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2));
747 // (:dregx . a)
748 static node*
749 new_dregx(parser_state *p, node *a, node *b)
751 return cons((node*)NODE_DREGX, cons(a, b));
754 // (:backref . n)
755 static node*
756 new_back_ref(parser_state *p, int n)
758 return cons((node*)NODE_BACK_REF, (node*)(intptr_t)n);
761 // (:nthref . n)
762 static node*
763 new_nth_ref(parser_state *p, int n)
765 return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
768 // (:heredoc . a)
769 static node*
770 new_heredoc(parser_state *p)
772 parser_heredoc_info *inf = parser_palloc(p, sizeof(parser_heredoc_info));
773 return cons((node*)NODE_HEREDOC, (node*)inf);
776 static void
777 new_bv(parser_state *p, mrb_sym id)
781 static node*
782 new_literal_delim(parser_state *p)
784 return cons((node*)NODE_LITERAL_DELIM, 0);
787 // (:words . a)
788 static node*
789 new_words(parser_state *p, node *a)
791 return cons((node*)NODE_WORDS, a);
794 // (:symbols . a)
795 static node*
796 new_symbols(parser_state *p, node *a)
798 return cons((node*)NODE_SYMBOLS, a);
801 // xxx -----------------------------
803 // (:call a op)
804 static node*
805 call_uni_op(parser_state *p, node *recv, char *m)
807 return new_call(p, recv, intern(m), 0);
810 // (:call a op b)
811 static node*
812 call_bin_op(parser_state *p, node *recv, char *m, node *arg1)
814 return new_call(p, recv, intern(m), list1(list1(arg1)));
817 static void
818 args_with_block(parser_state *p, node *a, node *b)
820 if (b) {
821 if (a->cdr) {
822 yyerror(p, "both block arg and actual block given");
824 a->cdr = b;
828 static void
829 call_with_block(parser_state *p, node *a, node *b)
831 node *n;
833 if (a->car == (node*)NODE_SUPER ||
834 a->car == (node*)NODE_ZSUPER) {
835 if (!a->cdr) a->cdr = cons(0, b);
836 else {
837 args_with_block(p, a->cdr, b);
840 else {
841 n = a->cdr->cdr->cdr;
842 if (!n->car) n->car = cons(0, b);
843 else {
844 args_with_block(p, n->car, b);
849 static node*
850 negate_lit(parser_state *p, node *n)
852 return cons((node*)NODE_NEGATE, n);
855 static node*
856 cond(node *n)
858 return n;
861 static node*
862 ret_args(parser_state *p, node *n)
864 if (n->cdr) {
865 yyerror(p, "block argument should not be given");
867 if (!n->car->cdr) return n->car->car;
868 return new_array(p, n->car);
871 static void
872 assignable(parser_state *p, node *lhs)
874 if ((int)(intptr_t)lhs->car == NODE_LVAR) {
875 local_add(p, sym(lhs->cdr));
879 static node*
880 var_reference(parser_state *p, node *lhs)
882 node *n;
884 if ((int)(intptr_t)lhs->car == NODE_LVAR) {
885 if (!local_var_p(p, sym(lhs->cdr))) {
886 n = new_fcall(p, sym(lhs->cdr), 0);
887 cons_free(lhs);
888 return n;
892 return lhs;
895 typedef enum mrb_string_type string_type;
897 static node*
898 new_strterm(parser_state *p, string_type type, int term, int paren)
900 return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term)));
903 static void
904 end_strterm(parser_state *p)
906 cons_free(p->lex_strterm->cdr->cdr);
907 cons_free(p->lex_strterm->cdr);
908 cons_free(p->lex_strterm);
909 p->lex_strterm = NULL;
912 parser_heredoc_info *
913 parsing_heredoc_inf(parser_state *p)
915 node *nd = p->parsing_heredoc;
916 if (nd == NULL)
917 return NULL;
918 /* assert(nd->car->car == NODE_HEREDOC); */
919 return (parser_heredoc_info*)nd->car->cdr;
922 static void
923 heredoc_end(parser_state *p)
925 p->parsing_heredoc = p->parsing_heredoc->cdr;
926 if (p->parsing_heredoc == NULL) {
927 p->lstate = EXPR_BEG;
928 p->cmd_start = TRUE;
929 end_strterm(p);
930 p->heredoc_end_now = TRUE;
931 } else {
932 /* next heredoc */
933 p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type;
936 #define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func))
938 // xxx -----------------------------
942 %pure_parser
943 %parse-param {parser_state *p}
944 %lex-param {parser_state *p}
946 %union {
947 node *nd;
948 mrb_sym id;
949 int num;
950 unsigned int stack;
951 const struct vtable *vars;
954 %token
955 keyword_class
956 keyword_module
957 keyword_def
958 keyword_undef
959 keyword_begin
960 keyword_rescue
961 keyword_ensure
962 keyword_end
963 keyword_if
964 keyword_unless
965 keyword_then
966 keyword_elsif
967 keyword_else
968 keyword_case
969 keyword_when
970 keyword_while
971 keyword_until
972 keyword_for
973 keyword_break
974 keyword_next
975 keyword_redo
976 keyword_retry
977 keyword_in
978 keyword_do
979 keyword_do_cond
980 keyword_do_block
981 keyword_do_LAMBDA
982 keyword_return
983 keyword_yield
984 keyword_super
985 keyword_self
986 keyword_nil
987 keyword_true
988 keyword_false
989 keyword_and
990 keyword_or
991 keyword_not
992 modifier_if
993 modifier_unless
994 modifier_while
995 modifier_until
996 modifier_rescue
997 keyword_alias
998 keyword_BEGIN
999 keyword_END
1000 keyword__LINE__
1001 keyword__FILE__
1002 keyword__ENCODING__
1004 %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
1005 %token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
1006 %token <nd> tSTRING tSTRING_PART tSTRING_MID
1007 %token <nd> tNTH_REF tBACK_REF
1008 %token <num> tREGEXP_END
1010 %type <nd> singleton string string_rep string_interp xstring regexp
1011 %type <nd> literal numeric cpath symbol
1012 %type <nd> top_compstmt top_stmts top_stmt
1013 %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
1014 %type <nd> expr_value arg_value primary_value
1015 %type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
1016 %type <nd> args call_args opt_call_args
1017 %type <nd> paren_args opt_paren_args variable
1018 %type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
1019 %type <nd> command_asgn mrhs superclass block_call block_command
1020 %type <nd> f_block_optarg f_block_opt
1021 %type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
1022 %type <nd> assoc_list assocs assoc undef_list backref for_var
1023 %type <nd> block_param opt_block_param block_param_def f_opt
1024 %type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
1025 %type <nd> brace_block cmd_brace_block do_block lhs none f_bad_arg
1026 %type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
1027 %type <id> fsym sym basic_symbol operation operation2 operation3
1028 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
1029 %type <nd> heredoc words symbols
1031 %token tUPLUS /* unary+ */
1032 %token tUMINUS /* unary- */
1033 %token tPOW /* ** */
1034 %token tCMP /* <=> */
1035 %token tEQ /* == */
1036 %token tEQQ /* === */
1037 %token tNEQ /* != */
1038 %token tGEQ /* >= */
1039 %token tLEQ /* <= */
1040 %token tANDOP tOROP /* && and || */
1041 %token tMATCH tNMATCH /* =~ and !~ */
1042 %token tDOT2 tDOT3 /* .. and ... */
1043 %token tAREF tASET /* [] and []= */
1044 %token tLSHFT tRSHFT /* << and >> */
1045 %token tCOLON2 /* :: */
1046 %token tCOLON3 /* :: at EXPR_BEG */
1047 %token <id> tOP_ASGN /* +=, -= etc. */
1048 %token tASSOC /* => */
1049 %token tLPAREN /* ( */
1050 %token tLPAREN_ARG /* ( */
1051 %token tRPAREN /* ) */
1052 %token tLBRACK /* [ */
1053 %token tLBRACE /* { */
1054 %token tLBRACE_ARG /* { */
1055 %token tSTAR /* * */
1056 %token tAMPER /* & */
1057 %token tLAMBDA /* -> */
1058 %token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
1059 %token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
1060 %token <nd> tHEREDOC_BEG /* <<, <<- */
1061 %token tHEREDOC_END tLITERAL_DELIM
1064 * precedence table
1067 %nonassoc tLOWEST
1068 %nonassoc tLBRACE_ARG
1070 %nonassoc modifier_if modifier_unless modifier_while modifier_until
1071 %left keyword_or keyword_and
1072 %right keyword_not
1073 %right '=' tOP_ASGN
1074 %left modifier_rescue
1075 %right '?' ':'
1076 %nonassoc tDOT2 tDOT3
1077 %left tOROP
1078 %left tANDOP
1079 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
1080 %left '>' tGEQ '<' tLEQ
1081 %left '|' '^'
1082 %left '&'
1083 %left tLSHFT tRSHFT
1084 %left '+' '-'
1085 %left '*' '/' '%'
1086 %right tUMINUS_NUM tUMINUS
1087 %right tPOW
1088 %right '!' '~' tUPLUS
1090 %nonassoc idNULL
1091 %nonassoc idRespond_to
1092 %nonassoc idIFUNC
1093 %nonassoc idCFUNC
1094 %nonassoc id_core_set_method_alias
1095 %nonassoc id_core_set_variable_alias
1096 %nonassoc id_core_undef_method
1097 %nonassoc id_core_define_method
1098 %nonassoc id_core_define_singleton_method
1099 %nonassoc id_core_set_postexe
1101 %token tLAST_TOKEN
1104 program : {
1105 p->lstate = EXPR_BEG;
1106 if (!p->locals) p->locals = cons(0,0);
1108 top_compstmt
1110 p->tree = new_scope(p, $2);
1114 top_compstmt : top_stmts opt_terms
1116 $$ = $1;
1120 top_stmts : none
1122 $$ = new_begin(p, 0);
1124 | top_stmt
1126 $$ = new_begin(p, $1);
1128 | top_stmts terms top_stmt
1130 $$ = push($1, newline_node($3));
1132 | error top_stmt
1134 $$ = new_begin(p, 0);
1138 top_stmt : stmt
1139 | keyword_BEGIN
1141 $<nd>$ = local_switch(p);
1143 '{' top_compstmt '}'
1145 yyerror(p, "BEGIN not supported");
1146 local_resume(p, $<nd>2);
1147 $$ = 0;
1151 bodystmt : compstmt
1152 opt_rescue
1153 opt_else
1154 opt_ensure
1156 if ($2) {
1157 $$ = new_rescue(p, $1, $2, $3);
1159 else if ($3) {
1160 yywarn(p, "else without rescue is useless");
1161 $$ = push($1, $3);
1163 else {
1164 $$ = $1;
1166 if ($4) {
1167 if ($$) {
1168 $$ = new_ensure(p, $$, $4);
1170 else {
1171 $$ = push($4, new_nil(p));
1177 compstmt : stmts opt_terms
1179 $$ = $1;
1183 stmts : none
1185 $$ = new_begin(p, 0);
1187 | stmt
1189 $$ = new_begin(p, $1);
1191 | stmts terms stmt
1193 $$ = push($1, newline_node($3));
1195 | error stmt
1197 $$ = new_begin(p, $2);
1201 stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
1203 $$ = new_alias(p, $2, $4);
1205 | keyword_undef undef_list
1207 $$ = $2;
1209 | stmt modifier_if expr_value
1211 $$ = new_if(p, cond($3), $1, 0);
1213 | stmt modifier_unless expr_value
1215 $$ = new_unless(p, cond($3), $1, 0);
1217 | stmt modifier_while expr_value
1219 $$ = new_while(p, cond($3), $1);
1221 | stmt modifier_until expr_value
1223 $$ = new_until(p, cond($3), $1);
1225 | stmt modifier_rescue stmt
1227 $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0);
1229 | keyword_END '{' compstmt '}'
1231 yyerror(p, "END not suported");
1232 $$ = new_postexe(p, $3);
1234 | command_asgn
1235 | mlhs '=' command_call
1237 $$ = new_masgn(p, $1, $3);
1239 | var_lhs tOP_ASGN command_call
1241 $$ = new_op_asgn(p, $1, $2, $3);
1243 | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
1245 $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
1247 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
1249 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1251 | primary_value '.' tCONSTANT tOP_ASGN command_call
1253 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1255 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
1257 yyerror(p, "constant re-assignment");
1258 $$ = 0;
1260 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
1262 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1264 | backref tOP_ASGN command_call
1266 backref_error(p, $1);
1267 $$ = new_begin(p, 0);
1269 | lhs '=' mrhs
1271 $$ = new_asgn(p, $1, new_array(p, $3));
1273 | mlhs '=' arg_value
1275 $$ = new_masgn(p, $1, $3);
1277 | mlhs '=' mrhs
1279 $$ = new_masgn(p, $1, new_array(p, $3));
1281 | expr
1284 command_asgn : lhs '=' command_call
1286 $$ = new_asgn(p, $1, $3);
1288 | lhs '=' command_asgn
1290 $$ = new_asgn(p, $1, $3);
1295 expr : command_call
1296 | expr keyword_and expr
1298 $$ = new_and(p, $1, $3);
1300 | expr keyword_or expr
1302 $$ = new_or(p, $1, $3);
1304 | keyword_not opt_nl expr
1306 $$ = call_uni_op(p, cond($3), "!");
1308 | '!' command_call
1310 $$ = call_uni_op(p, cond($2), "!");
1312 | arg
1315 expr_value : expr
1317 if (!$1) $$ = new_nil(p);
1318 else $$ = $1;
1322 command_call : command
1323 | block_command
1326 block_command : block_call
1327 | block_call dot_or_colon operation2 command_args
1330 cmd_brace_block : tLBRACE_ARG
1332 local_nest(p);
1334 opt_block_param
1335 compstmt
1338 $$ = new_block(p, $3, $4);
1339 local_unnest(p);
1343 command : operation command_args %prec tLOWEST
1345 $$ = new_fcall(p, $1, $2);
1347 | operation command_args cmd_brace_block
1349 args_with_block(p, $2, $3);
1350 $$ = new_fcall(p, $1, $2);
1352 | primary_value '.' operation2 command_args %prec tLOWEST
1354 $$ = new_call(p, $1, $3, $4);
1356 | primary_value '.' operation2 command_args cmd_brace_block
1358 args_with_block(p, $4, $5);
1359 $$ = new_call(p, $1, $3, $4);
1361 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
1363 $$ = new_call(p, $1, $3, $4);
1365 | primary_value tCOLON2 operation2 command_args cmd_brace_block
1367 args_with_block(p, $4, $5);
1368 $$ = new_call(p, $1, $3, $4);
1370 | keyword_super command_args
1372 $$ = new_super(p, $2);
1374 | keyword_yield command_args
1376 $$ = new_yield(p, $2);
1378 | keyword_return call_args
1380 $$ = new_return(p, ret_args(p, $2));
1382 | keyword_break call_args
1384 $$ = new_break(p, ret_args(p, $2));
1386 | keyword_next call_args
1388 $$ = new_next(p, ret_args(p, $2));
1392 mlhs : mlhs_basic
1394 $$ = $1;
1396 | tLPAREN mlhs_inner rparen
1398 $$ = $2;
1402 mlhs_inner : mlhs_basic
1403 | tLPAREN mlhs_inner rparen
1405 $$ = list1($2);
1409 mlhs_basic : mlhs_list
1411 $$ = list1($1);
1413 | mlhs_list mlhs_item
1415 $$ = list1(push($1,$2));
1417 | mlhs_list tSTAR mlhs_node
1419 $$ = list2($1, $3);
1421 | mlhs_list tSTAR mlhs_node ',' mlhs_post
1423 $$ = list3($1, $3, $5);
1425 | mlhs_list tSTAR
1427 $$ = list2($1, new_nil(p));
1429 | mlhs_list tSTAR ',' mlhs_post
1431 $$ = list3($1, new_nil(p), $4);
1433 | tSTAR mlhs_node
1435 $$ = list2(0, $2);
1437 | tSTAR mlhs_node ',' mlhs_post
1439 $$ = list3(0, $2, $4);
1441 | tSTAR
1443 $$ = list2(0, new_nil(p));
1445 | tSTAR ',' mlhs_post
1447 $$ = list3(0, new_nil(p), $3);
1451 mlhs_item : mlhs_node
1452 | tLPAREN mlhs_inner rparen
1454 $$ = $2;
1458 mlhs_list : mlhs_item ','
1460 $$ = list1($1);
1462 | mlhs_list mlhs_item ','
1464 $$ = push($1, $2);
1468 mlhs_post : mlhs_item
1470 $$ = list1($1);
1472 | mlhs_list mlhs_item
1474 $$ = push($1, $2);
1478 mlhs_node : variable
1480 assignable(p, $1);
1482 | primary_value '[' opt_call_args rbracket
1484 $$ = new_call(p, $1, intern2("[]",2), $3);
1486 | primary_value '.' tIDENTIFIER
1488 $$ = new_call(p, $1, $3, 0);
1490 | primary_value tCOLON2 tIDENTIFIER
1492 $$ = new_call(p, $1, $3, 0);
1494 | primary_value '.' tCONSTANT
1496 $$ = new_call(p, $1, $3, 0);
1498 | primary_value tCOLON2 tCONSTANT
1500 if (p->in_def || p->in_single)
1501 yyerror(p, "dynamic constant assignment");
1502 $$ = new_colon2(p, $1, $3);
1504 | tCOLON3 tCONSTANT
1506 if (p->in_def || p->in_single)
1507 yyerror(p, "dynamic constant assignment");
1508 $$ = new_colon3(p, $2);
1510 | backref
1512 backref_error(p, $1);
1513 $$ = 0;
1517 lhs : variable
1519 assignable(p, $1);
1521 | primary_value '[' opt_call_args rbracket
1523 $$ = new_call(p, $1, intern2("[]",2), $3);
1525 | primary_value '.' tIDENTIFIER
1527 $$ = new_call(p, $1, $3, 0);
1529 | primary_value tCOLON2 tIDENTIFIER
1531 $$ = new_call(p, $1, $3, 0);
1533 | primary_value '.' tCONSTANT
1535 $$ = new_call(p, $1, $3, 0);
1537 | primary_value tCOLON2 tCONSTANT
1539 if (p->in_def || p->in_single)
1540 yyerror(p, "dynamic constant assignment");
1541 $$ = new_colon2(p, $1, $3);
1543 | tCOLON3 tCONSTANT
1545 if (p->in_def || p->in_single)
1546 yyerror(p, "dynamic constant assignment");
1547 $$ = new_colon3(p, $2);
1549 | backref
1551 backref_error(p, $1);
1552 $$ = 0;
1556 cname : tIDENTIFIER
1558 yyerror(p, "class/module name must be CONSTANT");
1560 | tCONSTANT
1563 cpath : tCOLON3 cname
1565 $$ = cons((node*)1, nsym($2));
1567 | cname
1569 $$ = cons((node*)0, nsym($1));
1571 | primary_value tCOLON2 cname
1573 $$ = cons($1, nsym($3));
1577 fname : tIDENTIFIER
1578 | tCONSTANT
1579 | tFID
1580 | op
1582 p->lstate = EXPR_ENDFN;
1583 $$ = $1;
1585 | reswords
1587 p->lstate = EXPR_ENDFN;
1588 $$ = $<id>1;
1592 fsym : fname
1593 | basic_symbol
1596 undef_list : fsym
1598 $$ = new_undef(p, $1);
1600 | undef_list ',' {p->lstate = EXPR_FNAME;} fsym
1602 $$ = push($1, nsym($4));
1606 op : '|' { $$ = intern_c('|'); }
1607 | '^' { $$ = intern_c('^'); }
1608 | '&' { $$ = intern_c('&'); }
1609 | tCMP { $$ = intern2("<=>",3); }
1610 | tEQ { $$ = intern2("==",2); }
1611 | tEQQ { $$ = intern2("===",3); }
1612 | tMATCH { $$ = intern2("=~",2); }
1613 | tNMATCH { $$ = intern2("!~",2); }
1614 | '>' { $$ = intern_c('>'); }
1615 | tGEQ { $$ = intern2(">=",2); }
1616 | '<' { $$ = intern_c('<'); }
1617 | tLEQ { $$ = intern2("<=",2); }
1618 | tNEQ { $$ = intern2("!=",2); }
1619 | tLSHFT { $$ = intern2("<<",2); }
1620 | tRSHFT { $$ = intern2(">>",2); }
1621 | '+' { $$ = intern_c('+'); }
1622 | '-' { $$ = intern_c('-'); }
1623 | '*' { $$ = intern_c('*'); }
1624 | tSTAR { $$ = intern_c('*'); }
1625 | '/' { $$ = intern_c('/'); }
1626 | '%' { $$ = intern_c('%'); }
1627 | tPOW { $$ = intern2("**",2); }
1628 | '!' { $$ = intern_c('!'); }
1629 | '~' { $$ = intern_c('~'); }
1630 | tUPLUS { $$ = intern2("+@",2); }
1631 | tUMINUS { $$ = intern2("-@",2); }
1632 | tAREF { $$ = intern2("[]",2); }
1633 | tASET { $$ = intern2("[]=",3); }
1634 | '`' { $$ = intern_c('`'); }
1637 reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
1638 | keyword_BEGIN | keyword_END
1639 | keyword_alias | keyword_and | keyword_begin
1640 | keyword_break | keyword_case | keyword_class | keyword_def
1641 | keyword_do | keyword_else | keyword_elsif
1642 | keyword_end | keyword_ensure | keyword_false
1643 | keyword_for | keyword_in | keyword_module | keyword_next
1644 | keyword_nil | keyword_not | keyword_or | keyword_redo
1645 | keyword_rescue | keyword_retry | keyword_return | keyword_self
1646 | keyword_super | keyword_then | keyword_true | keyword_undef
1647 | keyword_when | keyword_yield | keyword_if | keyword_unless
1648 | keyword_while | keyword_until
1651 arg : lhs '=' arg
1653 $$ = new_asgn(p, $1, $3);
1655 | lhs '=' arg modifier_rescue arg
1657 $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
1659 | var_lhs tOP_ASGN arg
1661 $$ = new_op_asgn(p, $1, $2, $3);
1663 | var_lhs tOP_ASGN arg modifier_rescue arg
1665 $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
1667 | primary_value '[' opt_call_args rbracket tOP_ASGN arg
1669 $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6);
1671 | primary_value '.' tIDENTIFIER tOP_ASGN arg
1673 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1675 | primary_value '.' tCONSTANT tOP_ASGN arg
1677 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1679 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
1681 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1683 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
1685 yyerror(p, "constant re-assignment");
1686 $$ = new_begin(p, 0);
1688 | tCOLON3 tCONSTANT tOP_ASGN arg
1690 yyerror(p, "constant re-assignment");
1691 $$ = new_begin(p, 0);
1693 | backref tOP_ASGN arg
1695 backref_error(p, $1);
1696 $$ = new_begin(p, 0);
1698 | arg tDOT2 arg
1700 $$ = new_dot2(p, $1, $3);
1702 | arg tDOT3 arg
1704 $$ = new_dot3(p, $1, $3);
1706 | arg '+' arg
1708 $$ = call_bin_op(p, $1, "+", $3);
1710 | arg '-' arg
1712 $$ = call_bin_op(p, $1, "-", $3);
1714 | arg '*' arg
1716 $$ = call_bin_op(p, $1, "*", $3);
1718 | arg '/' arg
1720 $$ = call_bin_op(p, $1, "/", $3);
1722 | arg '%' arg
1724 $$ = call_bin_op(p, $1, "%", $3);
1726 | arg tPOW arg
1728 $$ = call_bin_op(p, $1, "**", $3);
1730 | tUMINUS_NUM tINTEGER tPOW arg
1732 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
1734 | tUMINUS_NUM tFLOAT tPOW arg
1736 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
1738 | tUPLUS arg
1740 $$ = call_uni_op(p, $2, "+@");
1742 | tUMINUS arg
1744 $$ = call_uni_op(p, $2, "-@");
1746 | arg '|' arg
1748 $$ = call_bin_op(p, $1, "|", $3);
1750 | arg '^' arg
1752 $$ = call_bin_op(p, $1, "^", $3);
1754 | arg '&' arg
1756 $$ = call_bin_op(p, $1, "&", $3);
1758 | arg tCMP arg
1760 $$ = call_bin_op(p, $1, "<=>", $3);
1762 | arg '>' arg
1764 $$ = call_bin_op(p, $1, ">", $3);
1766 | arg tGEQ arg
1768 $$ = call_bin_op(p, $1, ">=", $3);
1770 | arg '<' arg
1772 $$ = call_bin_op(p, $1, "<", $3);
1774 | arg tLEQ arg
1776 $$ = call_bin_op(p, $1, "<=", $3);
1778 | arg tEQ arg
1780 $$ = call_bin_op(p, $1, "==", $3);
1782 | arg tEQQ arg
1784 $$ = call_bin_op(p, $1, "===", $3);
1786 | arg tNEQ arg
1788 $$ = call_bin_op(p, $1, "!=", $3);
1790 | arg tMATCH arg
1792 $$ = call_bin_op(p, $1, "=~", $3);
1793 #if 0
1794 if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
1795 $$ = reg_named_capture_assign($1->nd_lit, $$);
1797 #endif
1799 | arg tNMATCH arg
1801 $$ = call_bin_op(p, $1, "!~", $3);
1803 | '!' arg
1805 $$ = call_uni_op(p, cond($2), "!");
1807 | '~' arg
1809 $$ = call_uni_op(p, cond($2), "~");
1811 | arg tLSHFT arg
1813 $$ = call_bin_op(p, $1, "<<", $3);
1815 | arg tRSHFT arg
1817 $$ = call_bin_op(p, $1, ">>", $3);
1819 | arg tANDOP arg
1821 $$ = new_and(p, $1, $3);
1823 | arg tOROP arg
1825 $$ = new_or(p, $1, $3);
1827 | arg '?' arg opt_nl ':' arg
1829 $$ = new_if(p, cond($1), $3, $6);
1831 | primary
1833 $$ = $1;
1837 arg_value : arg
1839 $$ = $1;
1840 if (!$$) $$ = new_nil(p);
1844 aref_args : none
1845 | args trailer
1847 $$ = $1;
1849 | args ',' assocs trailer
1851 $$ = push($1, new_hash(p, $3));
1853 | assocs trailer
1855 $$ = cons(new_hash(p, $1), 0);
1859 paren_args : '(' opt_call_args rparen
1861 $$ = $2;
1865 opt_paren_args : none
1866 | paren_args
1869 opt_call_args : none
1870 | call_args
1871 | args ','
1873 $$ = cons($1,0);
1875 | args ',' assocs ','
1877 $$ = cons(push($1, new_hash(p, $3)), 0);
1879 | assocs ','
1881 $$ = cons(list1(new_hash(p, $1)), 0);
1885 call_args : command
1887 $$ = cons(list1($1), 0);
1889 | args opt_block_arg
1891 $$ = cons($1, $2);
1893 | assocs opt_block_arg
1895 $$ = cons(list1(new_hash(p, $1)), $2);
1897 | args ',' assocs opt_block_arg
1899 $$ = cons(push($1, new_hash(p, $3)), $4);
1901 | block_arg
1903 $$ = cons(0, $1);
1907 command_args : {
1908 $<stack>$ = p->cmdarg_stack;
1909 CMDARG_PUSH(1);
1911 call_args
1913 p->cmdarg_stack = $<stack>1;
1914 $$ = $2;
1918 block_arg : tAMPER arg_value
1920 $$ = new_block_arg(p, $2);
1924 opt_block_arg : ',' block_arg
1926 $$ = $2;
1928 | none
1930 $$ = 0;
1934 args : arg_value
1936 $$ = cons($1, 0);
1938 | tSTAR arg_value
1940 $$ = cons(new_splat(p, $2), 0);
1942 | args ',' arg_value
1944 $$ = push($1, $3);
1946 | args ',' tSTAR arg_value
1948 $$ = push($1, new_splat(p, $4));
1952 mrhs : args ',' arg_value
1954 $$ = push($1, $3);
1956 | args ',' tSTAR arg_value
1958 $$ = push($1, new_splat(p, $4));
1960 | tSTAR arg_value
1962 $$ = list1(new_splat(p, $2));
1966 primary : literal
1967 | string
1968 | xstring
1969 | regexp
1970 | heredoc
1971 | var_ref
1972 | backref
1973 | tFID
1975 $$ = new_fcall(p, $1, 0);
1977 | keyword_begin
1979 $<stack>1 = p->cmdarg_stack;
1980 p->cmdarg_stack = 0;
1982 bodystmt
1983 keyword_end
1985 p->cmdarg_stack = $<stack>1;
1986 $$ = $3;
1988 | tLPAREN_ARG expr {p->lstate = EXPR_ENDARG;} rparen
1990 $$ = $2;
1992 | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
1994 $$ = 0;
1996 | tLPAREN compstmt ')'
1998 $$ = $2;
2000 | primary_value tCOLON2 tCONSTANT
2002 $$ = new_colon2(p, $1, $3);
2004 | tCOLON3 tCONSTANT
2006 $$ = new_colon3(p, $2);
2008 | tLBRACK aref_args ']'
2010 $$ = new_array(p, $2);
2012 | tLBRACE assoc_list '}'
2014 $$ = new_hash(p, $2);
2016 | keyword_return
2018 $$ = new_return(p, 0);
2020 | keyword_yield '(' call_args rparen
2022 $$ = new_yield(p, $3);
2024 | keyword_yield '(' rparen
2026 $$ = new_yield(p, 0);
2028 | keyword_yield
2030 $$ = new_yield(p, 0);
2032 | keyword_not '(' expr rparen
2034 $$ = call_uni_op(p, cond($3), "!");
2036 | keyword_not '(' rparen
2038 $$ = call_uni_op(p, new_nil(p), "!");
2040 | operation brace_block
2042 $$ = new_fcall(p, $1, cons(0, $2));
2044 | method_call
2045 | method_call brace_block
2047 call_with_block(p, $1, $2);
2048 $$ = $1;
2050 | tLAMBDA
2052 local_nest(p);
2053 $<num>$ = p->lpar_beg;
2054 p->lpar_beg = ++p->paren_nest;
2056 f_larglist
2057 lambda_body
2059 p->lpar_beg = $<num>2;
2060 $$ = new_lambda(p, $3, $4);
2061 local_unnest(p);
2063 | keyword_if expr_value then
2064 compstmt
2065 if_tail
2066 keyword_end
2068 $$ = new_if(p, cond($2), $4, $5);
2070 | keyword_unless expr_value then
2071 compstmt
2072 opt_else
2073 keyword_end
2075 $$ = new_unless(p, cond($2), $4, $5);
2077 | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();}
2078 compstmt
2079 keyword_end
2081 $$ = new_while(p, cond($3), $6);
2083 | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();}
2084 compstmt
2085 keyword_end
2087 $$ = new_until(p, cond($3), $6);
2089 | keyword_case expr_value opt_terms
2090 case_body
2091 keyword_end
2093 $$ = new_case(p, $2, $4);
2095 | keyword_case opt_terms case_body keyword_end
2097 $$ = new_case(p, 0, $3);
2099 | keyword_for for_var keyword_in
2100 {COND_PUSH(1);}
2101 expr_value do
2102 {COND_POP();}
2103 compstmt
2104 keyword_end
2106 $$ = new_for(p, $2, $5, $8);
2108 | keyword_class cpath superclass
2110 if (p->in_def || p->in_single)
2111 yyerror(p, "class definition in method body");
2112 $<nd>$ = local_switch(p);
2114 bodystmt
2115 keyword_end
2117 $$ = new_class(p, $2, $3, $5);
2118 local_resume(p, $<nd>4);
2120 | keyword_class tLSHFT expr
2122 $<num>$ = p->in_def;
2123 p->in_def = 0;
2125 term
2127 $<nd>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single);
2128 p->in_single = 0;
2130 bodystmt
2131 keyword_end
2133 $$ = new_sclass(p, $3, $7);
2134 local_resume(p, $<nd>6->car);
2135 p->in_def = $<num>4;
2136 p->in_single = (int)(intptr_t)$<nd>6->cdr;
2138 | keyword_module cpath
2140 if (p->in_def || p->in_single)
2141 yyerror(p, "module definition in method body");
2142 $<nd>$ = local_switch(p);
2144 bodystmt
2145 keyword_end
2147 $$ = new_module(p, $2, $4);
2148 local_resume(p, $<nd>3);
2150 | keyword_def fname
2152 p->in_def++;
2153 $<nd>$ = local_switch(p);
2155 f_arglist
2156 bodystmt
2157 keyword_end
2159 $$ = new_def(p, $2, $4, $5);
2160 local_resume(p, $<nd>3);
2161 p->in_def--;
2163 | keyword_def singleton dot_or_colon {p->lstate = EXPR_FNAME;} fname
2165 p->in_single++;
2166 p->lstate = EXPR_ENDFN; /* force for args */
2167 $<nd>$ = local_switch(p);
2169 f_arglist
2170 bodystmt
2171 keyword_end
2173 $$ = new_sdef(p, $2, $5, $7, $8);
2174 local_resume(p, $<nd>6);
2175 p->in_single--;
2177 | keyword_break
2179 $$ = new_break(p, 0);
2181 | keyword_next
2183 $$ = new_next(p, 0);
2185 | keyword_redo
2187 $$ = new_redo(p);
2189 | keyword_retry
2191 $$ = new_retry(p);
2195 primary_value : primary
2197 $$ = $1;
2198 if (!$$) $$ = new_nil(p);
2202 then : term
2203 | keyword_then
2204 | term keyword_then
2207 do : term
2208 | keyword_do_cond
2211 if_tail : opt_else
2212 | keyword_elsif expr_value then
2213 compstmt
2214 if_tail
2216 $$ = new_if(p, cond($2), $4, $5);
2220 opt_else : none
2221 | keyword_else compstmt
2223 $$ = $2;
2227 for_var : lhs
2229 $$ = list1(list1($1));
2231 | mlhs
2234 f_marg : f_norm_arg
2236 $$ = new_arg(p, $1);
2238 | tLPAREN f_margs rparen
2240 $$ = new_masgn(p, $2, 0);
2244 f_marg_list : f_marg
2246 $$ = list1($1);
2248 | f_marg_list ',' f_marg
2250 $$ = push($1, $3);
2254 f_margs : f_marg_list
2256 $$ = list3($1,0,0);
2258 | f_marg_list ',' tSTAR f_norm_arg
2260 $$ = list3($1, new_arg(p, $4), 0);
2262 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
2264 $$ = list3($1, new_arg(p, $4), $6);
2266 | f_marg_list ',' tSTAR
2268 $$ = list3($1, (node*)-1, 0);
2270 | f_marg_list ',' tSTAR ',' f_marg_list
2272 $$ = list3($1, (node*)-1, $5);
2274 | tSTAR f_norm_arg
2276 $$ = list3(0, new_arg(p, $2), 0);
2278 | tSTAR f_norm_arg ',' f_marg_list
2280 $$ = list3(0, new_arg(p, $2), $4);
2282 | tSTAR
2284 $$ = list3(0, (node*)-1, 0);
2286 | tSTAR ',' f_marg_list
2288 $$ = list3(0, (node*)-1, $3);
2292 block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
2294 $$ = new_args(p, $1, $3, $5, 0, $6);
2296 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2298 $$ = new_args(p, $1, $3, $5, $7, $8);
2300 | f_arg ',' f_block_optarg opt_f_block_arg
2302 $$ = new_args(p, $1, $3, 0, 0, $4);
2304 | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
2306 $$ = new_args(p, $1, $3, 0, $5, $6);
2308 | f_arg ',' f_rest_arg opt_f_block_arg
2310 $$ = new_args(p, $1, 0, $3, 0, $4);
2312 | f_arg ','
2314 $$ = new_args(p, $1, 0, 1, 0, 0);
2316 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
2318 $$ = new_args(p, $1, 0, $3, $5, $6);
2320 | f_arg opt_f_block_arg
2322 $$ = new_args(p, $1, 0, 0, 0, $2);
2324 | f_block_optarg ',' f_rest_arg opt_f_block_arg
2326 $$ = new_args(p, 0, $1, $3, 0, $4);
2328 | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2330 $$ = new_args(p, 0, $1, $3, $5, $6);
2332 | f_block_optarg opt_f_block_arg
2334 $$ = new_args(p, 0, $1, 0, 0, $2);
2336 | f_block_optarg ',' f_arg opt_f_block_arg
2338 $$ = new_args(p, 0, $1, 0, $3, $4);
2340 | f_rest_arg opt_f_block_arg
2342 $$ = new_args(p, 0, 0, $1, 0, $2);
2344 | f_rest_arg ',' f_arg opt_f_block_arg
2346 $$ = new_args(p, 0, 0, $1, $3, $4);
2348 | f_block_arg
2350 $$ = new_args(p, 0, 0, 0, 0, $1);
2354 opt_block_param : none
2355 | block_param_def
2357 p->cmd_start = TRUE;
2358 $$ = $1;
2362 block_param_def : '|' opt_bv_decl '|'
2364 local_add_f(p, 0);
2365 $$ = 0;
2367 | tOROP
2369 local_add_f(p, 0);
2370 $$ = 0;
2372 | '|' block_param opt_bv_decl '|'
2374 $$ = $2;
2379 opt_bv_decl : opt_nl
2381 $$ = 0;
2383 | opt_nl ';' bv_decls opt_nl
2385 $$ = 0;
2389 bv_decls : bvar
2390 | bv_decls ',' bvar
2393 bvar : tIDENTIFIER
2395 local_add_f(p, $1);
2396 new_bv(p, $1);
2398 | f_bad_arg
2401 f_larglist : '(' f_args opt_bv_decl ')'
2403 $$ = $2;
2405 | f_args
2407 $$ = $1;
2411 lambda_body : tLAMBEG compstmt '}'
2413 $$ = $2;
2415 | keyword_do_LAMBDA compstmt keyword_end
2417 $$ = $2;
2421 do_block : keyword_do_block
2423 local_nest(p);
2425 opt_block_param
2426 compstmt
2427 keyword_end
2429 $$ = new_block(p,$3,$4);
2430 local_unnest(p);
2434 block_call : command do_block
2436 if ($1->car == (node*)NODE_YIELD) {
2437 yyerror(p, "block given to yield");
2439 else {
2440 call_with_block(p, $1, $2);
2442 $$ = $1;
2444 | block_call dot_or_colon operation2 opt_paren_args
2446 $$ = new_call(p, $1, $3, $4);
2448 | block_call dot_or_colon operation2 opt_paren_args brace_block
2450 $$ = new_call(p, $1, $3, $4);
2451 call_with_block(p, $$, $5);
2453 | block_call dot_or_colon operation2 command_args do_block
2455 $$ = new_call(p, $1, $3, $4);
2456 call_with_block(p, $$, $5);
2460 method_call : operation paren_args
2462 $$ = new_fcall(p, $1, $2);
2464 | primary_value '.' operation2 opt_paren_args
2466 $$ = new_call(p, $1, $3, $4);
2468 | primary_value tCOLON2 operation2 paren_args
2470 $$ = new_call(p, $1, $3, $4);
2472 | primary_value tCOLON2 operation3
2474 $$ = new_call(p, $1, $3, 0);
2476 | primary_value '.' paren_args
2478 $$ = new_call(p, $1, intern2("call",4), $3);
2480 | primary_value tCOLON2 paren_args
2482 $$ = new_call(p, $1, intern2("call",4), $3);
2484 | keyword_super paren_args
2486 $$ = new_super(p, $2);
2488 | keyword_super
2490 $$ = new_zsuper(p);
2492 | primary_value '[' opt_call_args rbracket
2494 $$ = new_call(p, $1, intern2("[]",2), $3);
2498 brace_block : '{'
2500 local_nest(p);
2502 opt_block_param
2503 compstmt '}'
2505 $$ = new_block(p,$3,$4);
2506 local_unnest(p);
2508 | keyword_do
2510 local_nest(p);
2512 opt_block_param
2513 compstmt keyword_end
2515 $$ = new_block(p,$3,$4);
2516 local_unnest(p);
2520 case_body : keyword_when args then
2521 compstmt
2522 cases
2524 $$ = cons(cons($2, $4), $5);
2528 cases : opt_else
2530 if ($1) {
2531 $$ = cons(cons(0, $1), 0);
2533 else {
2534 $$ = 0;
2537 | case_body
2540 opt_rescue : keyword_rescue exc_list exc_var then
2541 compstmt
2542 opt_rescue
2544 $$ = list1(list3($2, $3, $5));
2545 if ($6) $$ = append($$, $6);
2547 | none
2550 exc_list : arg_value
2552 $$ = list1($1);
2554 | mrhs
2555 | none
2558 exc_var : tASSOC lhs
2560 $$ = $2;
2562 | none
2565 opt_ensure : keyword_ensure compstmt
2567 $$ = $2;
2569 | none
2572 literal : numeric
2573 | symbol
2574 | words
2575 | symbols
2578 string : tCHAR
2579 | tSTRING
2580 | tSTRING_BEG tSTRING
2582 $$ = $2;
2584 | tSTRING_BEG string_rep tSTRING
2586 $$ = new_dstr(p, push($2, $3));
2590 string_rep : string_interp
2591 | string_rep string_interp
2593 $$ = append($1, $2);
2597 string_interp : tSTRING_MID
2599 $$ = list1($1);
2601 | tSTRING_PART
2603 $<nd>$ = p->lex_strterm;
2604 p->lex_strterm = NULL;
2606 compstmt
2609 p->lex_strterm = $<nd>2;
2610 $$ = list2($1, $3);
2612 | tLITERAL_DELIM
2614 $$ = list1(new_literal_delim(p));
2618 xstring : tXSTRING_BEG tXSTRING
2620 $$ = $2;
2622 | tXSTRING_BEG string_rep tXSTRING
2624 $$ = new_dxstr(p, push($2, $3));
2628 regexp : tREGEXP_BEG tREGEXP
2630 $$ = $2;
2632 | tREGEXP_BEG string_rep tREGEXP
2634 $$ = new_dregx(p, $2, $3);
2638 heredoc : tHEREDOC_BEG
2641 opt_heredoc_bodies : none
2642 | heredoc_bodies
2645 heredoc_bodies : heredoc_body
2646 | heredoc_bodies heredoc_body
2649 heredoc_body : tHEREDOC_END
2651 parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0));
2652 heredoc_end(p);
2654 | string_rep tHEREDOC_END
2656 parsing_heredoc_inf(p)->doc = $1;
2657 heredoc_end(p);
2661 words : tWORDS_BEG tSTRING
2663 $$ = new_words(p, list1($2));
2665 | tWORDS_BEG string_rep tSTRING
2667 $$ = new_words(p, push($2, $3));
2672 symbol : basic_symbol
2674 $$ = new_sym(p, $1);
2676 | tSYMBEG tSTRING_BEG string_interp tSTRING
2678 p->lstate = EXPR_END;
2679 $$ = new_dsym(p, push($3, $4));
2683 basic_symbol : tSYMBEG sym
2685 p->lstate = EXPR_END;
2686 $$ = $2;
2690 sym : fname
2691 | tIVAR
2692 | tGVAR
2693 | tCVAR
2694 | tSTRING
2696 $$ = new_strsym(p, $1);
2698 | tSTRING_BEG tSTRING
2700 $$ = new_strsym(p, $2);
2704 symbols : tSYMBOLS_BEG tSTRING
2706 $$ = new_symbols(p, list1($2));
2708 | tSYMBOLS_BEG string_rep tSTRING
2710 $$ = new_symbols(p, push($2, $3));
2714 numeric : tINTEGER
2715 | tFLOAT
2716 | tUMINUS_NUM tINTEGER %prec tLOWEST
2718 $$ = negate_lit(p, $2);
2720 | tUMINUS_NUM tFLOAT %prec tLOWEST
2722 $$ = negate_lit(p, $2);
2726 variable : tIDENTIFIER
2728 $$ = new_lvar(p, $1);
2730 | tIVAR
2732 $$ = new_ivar(p, $1);
2734 | tGVAR
2736 $$ = new_gvar(p, $1);
2738 | tCVAR
2740 $$ = new_cvar(p, $1);
2742 | tCONSTANT
2744 $$ = new_const(p, $1);
2748 var_lhs : variable
2750 assignable(p, $1);
2754 var_ref : variable
2756 $$ = var_reference(p, $1);
2758 | keyword_nil
2760 $$ = new_nil(p);
2762 | keyword_self
2764 $$ = new_self(p);
2766 | keyword_true
2768 $$ = new_true(p);
2770 | keyword_false
2772 $$ = new_false(p);
2774 | keyword__FILE__
2776 if (!p->filename) {
2777 p->filename = "(null)";
2779 $$ = new_str(p, p->filename, strlen(p->filename));
2781 | keyword__LINE__
2783 char buf[16];
2785 snprintf(buf, sizeof(buf), "%d", p->lineno);
2786 $$ = new_int(p, buf, 10);
2790 backref : tNTH_REF
2791 | tBACK_REF
2794 superclass : term
2796 $$ = 0;
2798 | '<'
2800 p->lstate = EXPR_BEG;
2801 p->cmd_start = TRUE;
2803 expr_value term
2805 $$ = $3;
2807 | error term
2809 yyerrok;
2810 $$ = 0;
2814 f_arglist : '(' f_args rparen
2816 $$ = $2;
2817 p->lstate = EXPR_BEG;
2818 p->cmd_start = TRUE;
2820 | f_args term
2822 $$ = $1;
2826 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
2828 $$ = new_args(p, $1, $3, $5, 0, $6);
2830 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2832 $$ = new_args(p, $1, $3, $5, $7, $8);
2834 | f_arg ',' f_optarg opt_f_block_arg
2836 $$ = new_args(p, $1, $3, 0, 0, $4);
2838 | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
2840 $$ = new_args(p, $1, $3, 0, $5, $6);
2842 | f_arg ',' f_rest_arg opt_f_block_arg
2844 $$ = new_args(p, $1, 0, $3, 0, $4);
2846 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
2848 $$ = new_args(p, $1, 0, $3, $5, $6);
2850 | f_arg opt_f_block_arg
2852 $$ = new_args(p, $1, 0, 0, 0, $2);
2854 | f_optarg ',' f_rest_arg opt_f_block_arg
2856 $$ = new_args(p, 0, $1, $3, 0, $4);
2858 | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2860 $$ = new_args(p, 0, $1, $3, $5, $6);
2862 | f_optarg opt_f_block_arg
2864 $$ = new_args(p, 0, $1, 0, 0, $2);
2866 | f_optarg ',' f_arg opt_f_block_arg
2868 $$ = new_args(p, 0, $1, 0, $3, $4);
2870 | f_rest_arg opt_f_block_arg
2872 $$ = new_args(p, 0, 0, $1, 0, $2);
2874 | f_rest_arg ',' f_arg opt_f_block_arg
2876 $$ = new_args(p, 0, 0, $1, $3, $4);
2878 | f_block_arg
2880 $$ = new_args(p, 0, 0, 0, 0, $1);
2882 | /* none */
2884 local_add_f(p, 0);
2885 $$ = new_args(p, 0, 0, 0, 0, 0);
2889 f_bad_arg : tCONSTANT
2891 yyerror(p, "formal argument cannot be a constant");
2892 $$ = 0;
2894 | tIVAR
2896 yyerror(p, "formal argument cannot be an instance variable");
2897 $$ = 0;
2899 | tGVAR
2901 yyerror(p, "formal argument cannot be a global variable");
2902 $$ = 0;
2904 | tCVAR
2906 yyerror(p, "formal argument cannot be a class variable");
2907 $$ = 0;
2911 f_norm_arg : f_bad_arg
2913 $$ = 0;
2915 | tIDENTIFIER
2917 local_add_f(p, $1);
2918 $$ = $1;
2922 f_arg_item : f_norm_arg
2924 $$ = new_arg(p, $1);
2926 | tLPAREN f_margs rparen
2928 $$ = new_masgn(p, $2, 0);
2932 f_arg : f_arg_item
2934 $$ = list1($1);
2936 | f_arg ',' f_arg_item
2938 $$ = push($1, $3);
2942 f_opt : tIDENTIFIER '=' arg_value
2944 local_add_f(p, $1);
2945 $$ = cons(nsym($1), $3);
2949 f_block_opt : tIDENTIFIER '=' primary_value
2951 local_add_f(p, $1);
2952 $$ = cons(nsym($1), $3);
2956 f_block_optarg : f_block_opt
2958 $$ = list1($1);
2960 | f_block_optarg ',' f_block_opt
2962 $$ = push($1, $3);
2966 f_optarg : f_opt
2968 $$ = list1($1);
2970 | f_optarg ',' f_opt
2972 $$ = push($1, $3);
2976 restarg_mark : '*'
2977 | tSTAR
2980 f_rest_arg : restarg_mark tIDENTIFIER
2982 local_add_f(p, $2);
2983 $$ = $2;
2985 | restarg_mark
2987 local_add_f(p, 0);
2988 $$ = -1;
2992 blkarg_mark : '&'
2993 | tAMPER
2996 f_block_arg : blkarg_mark tIDENTIFIER
2998 local_add_f(p, $2);
2999 $$ = $2;
3003 opt_f_block_arg : ',' f_block_arg
3005 $$ = $2;
3007 | none
3009 local_add_f(p, 0);
3010 $$ = 0;
3014 singleton : var_ref
3016 $$ = $1;
3017 if (!$$) $$ = new_nil(p);
3019 | '(' {p->lstate = EXPR_BEG;} expr rparen
3021 if ($3 == 0) {
3022 yyerror(p, "can't define singleton method for ().");
3024 else {
3025 switch ((enum node_type)(int)(intptr_t)$3->car) {
3026 case NODE_STR:
3027 case NODE_DSTR:
3028 case NODE_XSTR:
3029 case NODE_DXSTR:
3030 case NODE_DREGX:
3031 case NODE_MATCH:
3032 case NODE_FLOAT:
3033 case NODE_ARRAY:
3034 case NODE_HEREDOC:
3035 yyerror(p, "can't define singleton method for literals");
3036 default:
3037 break;
3040 $$ = $3;
3044 assoc_list : none
3045 | assocs trailer
3047 $$ = $1;
3051 assocs : assoc
3053 $$ = list1($1);
3055 | assocs ',' assoc
3057 $$ = push($1, $3);
3061 assoc : arg_value tASSOC arg_value
3063 $$ = cons($1, $3);
3065 | tLABEL arg_value
3067 $$ = cons(new_sym(p, $1), $2);
3071 operation : tIDENTIFIER
3072 | tCONSTANT
3073 | tFID
3076 operation2 : tIDENTIFIER
3077 | tCONSTANT
3078 | tFID
3079 | op
3082 operation3 : tIDENTIFIER
3083 | tFID
3084 | op
3087 dot_or_colon : '.'
3088 | tCOLON2
3091 opt_terms : /* none */
3092 | terms
3095 opt_nl : /* none */
3096 | nl
3099 rparen : opt_nl ')'
3102 rbracket : opt_nl ']'
3105 trailer : /* none */
3106 | nl
3107 | ','
3110 term : ';' {yyerrok;}
3111 | nl
3114 nl : '\n'
3116 p->lineno++;
3117 p->column = 0;
3119 opt_heredoc_bodies
3121 terms : term
3122 | terms ';' {yyerrok;}
3125 none : /* none */
3127 $$ = 0;
3131 #define yylval (*((YYSTYPE*)(p->ylval)))
3133 static void
3134 yyerror(parser_state *p, const char *s)
3136 char* c;
3137 int n;
3139 if (! p->capture_errors) {
3140 #ifdef ENABLE_STDIO
3141 if (p->filename) {
3142 fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
3144 else {
3145 fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
3147 #endif
3149 else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) {
3150 n = strlen(s);
3151 c = (char *)parser_palloc(p, n + 1);
3152 memcpy(c, s, n + 1);
3153 p->error_buffer[p->nerr].message = c;
3154 p->error_buffer[p->nerr].lineno = p->lineno;
3155 p->error_buffer[p->nerr].column = p->column;
3157 p->nerr++;
3160 static void
3161 yyerror_i(parser_state *p, const char *fmt, int i)
3163 char buf[256];
3165 snprintf(buf, sizeof(buf), fmt, i);
3166 yyerror(p, buf);
3169 static void
3170 yywarn(parser_state *p, const char *s)
3172 char* c;
3173 int n;
3175 if (! p->capture_errors) {
3176 #ifdef ENABLE_STDIO
3177 if (p->filename) {
3178 fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
3180 else {
3181 fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
3183 #endif
3185 else if (p->nwarn < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) {
3186 n = strlen(s);
3187 c = (char *)parser_palloc(p, n + 1);
3188 memcpy(c, s, n + 1);
3189 p->warn_buffer[p->nwarn].message = c;
3190 p->warn_buffer[p->nwarn].lineno = p->lineno;
3191 p->warn_buffer[p->nwarn].column = p->column;
3193 p->nwarn++;
3196 static void
3197 yywarning(parser_state *p, const char *s)
3199 yywarn(p, s);
3202 static void
3203 yywarning_s(parser_state *p, const char *fmt, const char *s)
3205 char buf[256];
3207 snprintf(buf, sizeof(buf), fmt, s);
3208 yywarning(p, buf);
3211 static void
3212 backref_error(parser_state *p, node *n)
3214 int c;
3216 c = (int)(intptr_t)n->car;
3218 if (c == NODE_NTH_REF) {
3219 yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr);
3220 } else if (c == NODE_BACK_REF) {
3221 yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
3222 } else {
3223 mrb_bug("Internal error in backref_error() : n=>car == %d", c);
3227 static int peeks(parser_state *p, const char *s);
3228 static int skips(parser_state *p, const char *s);
3230 static inline int
3231 nextc(parser_state *p)
3233 int c;
3235 if (p->pb) {
3236 node *tmp;
3238 c = (int)(intptr_t)p->pb->car;
3239 tmp = p->pb;
3240 p->pb = p->pb->cdr;
3241 cons_free(tmp);
3243 else {
3244 if (p->f) {
3245 if (feof(p->f)) return -1;
3246 c = fgetc(p->f);
3247 if (c == EOF) return -1;
3249 else if (!p->s || p->s >= p->send) {
3250 return -1;
3252 else {
3253 c = (unsigned char)*p->s++;
3256 p->column++;
3257 return c;
3260 static void
3261 pushback(parser_state *p, int c)
3263 if (c < 0) return;
3264 p->column--;
3265 p->pb = cons((node*)(intptr_t)c, p->pb);
3268 static void
3269 skip(parser_state *p, char term)
3271 int c;
3273 for (;;) {
3274 c = nextc(p);
3275 if (c < 0) break;
3276 if (c == term) break;
3280 static int
3281 peek_n(parser_state *p, int c, int n)
3283 node *list = 0;
3284 int c0;
3286 do {
3287 c0 = nextc(p);
3288 if (c0 < 0) return FALSE;
3289 list = push(list, (node*)(intptr_t)c0);
3290 } while(n--);
3291 if (p->pb) {
3292 p->pb = push(p->pb, (node*)list);
3294 else {
3295 p->pb = list;
3297 if (c0 == c) return TRUE;
3298 return FALSE;
3300 #define peek(p,c) peek_n((p), (c), 0)
3302 static int
3303 peeks(parser_state *p, const char *s)
3305 int len = strlen(s);
3307 if (p->f) {
3308 int n = 0;
3309 while (*s) {
3310 if (!peek_n(p, *s++, n++)) return FALSE;
3312 return TRUE;
3314 else if (p->s && p->s + len >= p->send) {
3315 if (memcmp(p->s, s, len) == 0) return TRUE;
3317 return FALSE;
3320 static int
3321 skips(parser_state *p, const char *s)
3323 int c;
3325 for (;;) {
3326 // skip until first char
3327 for (;;) {
3328 c = nextc(p);
3329 if (c < 0) return c;
3330 if (c == *s) break;
3332 s++;
3333 if (peeks(p, s)) {
3334 int len = strlen(s);
3336 while (len--) {
3337 nextc(p);
3339 return TRUE;
3341 else{
3342 s--;
3345 return FALSE;
3349 static int
3350 newtok(parser_state *p)
3352 p->bidx = 0;
3353 return p->column - 1;
3356 static void
3357 tokadd(parser_state *p, int c)
3359 if (p->bidx < MRB_PARSER_BUF_SIZE) {
3360 p->buf[p->bidx++] = c;
3364 static int
3365 toklast(parser_state *p)
3367 return p->buf[p->bidx-1];
3370 static void
3371 tokfix(parser_state *p)
3373 if (p->bidx >= MRB_PARSER_BUF_SIZE) {
3374 yyerror(p, "string too long (truncated)");
3376 p->buf[p->bidx] = '\0';
3379 static const char*
3380 tok(parser_state *p)
3382 return p->buf;
3385 static int
3386 toklen(parser_state *p)
3388 return p->bidx;
3391 #define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG)
3392 #define IS_END() (p->lstate == EXPR_END || p->lstate == EXPR_ENDARG || p->lstate == EXPR_ENDFN)
3393 #define IS_BEG() (p->lstate == EXPR_BEG || p->lstate == EXPR_MID || p->lstate == EXPR_VALUE || p->lstate == EXPR_CLASS)
3394 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
3395 #define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
3396 #define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
3398 static int
3399 scan_oct(const int *start, int len, int *retlen)
3401 const int *s = start;
3402 int retval = 0;
3404 /* assert(len <= 3) */
3405 while (len-- && *s >= '0' && *s <= '7') {
3406 retval <<= 3;
3407 retval |= *s++ - '0';
3409 *retlen = s - start;
3411 return retval;
3414 static int
3415 scan_hex(const int *start, int len, int *retlen)
3417 static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
3418 register const int *s = start;
3419 register int retval = 0;
3420 char *tmp;
3422 /* assert(len <= 2) */
3423 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
3424 retval <<= 4;
3425 retval |= (tmp - hexdigit) & 15;
3426 s++;
3428 *retlen = s - start;
3430 return retval;
3433 static int
3434 read_escape(parser_state *p)
3436 int c;
3438 switch (c = nextc(p)) {
3439 case '\\': /* Backslash */
3440 return c;
3442 case 'n': /* newline */
3443 return '\n';
3445 case 't': /* horizontal tab */
3446 return '\t';
3448 case 'r': /* carriage-return */
3449 return '\r';
3451 case 'f': /* form-feed */
3452 return '\f';
3454 case 'v': /* vertical tab */
3455 return '\13';
3457 case 'a': /* alarm(bell) */
3458 return '\007';
3460 case 'e': /* escape */
3461 return 033;
3463 case '0': case '1': case '2': case '3': /* octal constant */
3464 case '4': case '5': case '6': case '7':
3466 int buf[3];
3467 int i;
3469 buf[0] = c;
3470 for (i=1; i<3; i++) {
3471 buf[i] = nextc(p);
3472 if (buf[i] == -1) goto eof;
3473 if (buf[i] < '0' || '7' < buf[i]) {
3474 pushback(p, buf[i]);
3475 break;
3478 c = scan_oct(buf, i, &i);
3480 return c;
3482 case 'x': /* hex constant */
3484 int buf[2];
3485 int i;
3487 for (i=0; i<2; i++) {
3488 buf[i] = nextc(p);
3489 if (buf[i] == -1) goto eof;
3490 if (!isxdigit(buf[i])) {
3491 pushback(p, buf[i]);
3492 break;
3495 c = scan_hex(buf, i, &i);
3496 if (i == 0) {
3497 yyerror(p, "Invalid escape character syntax");
3498 return 0;
3501 return c;
3503 case 'b': /* backspace */
3504 return '\010';
3506 case 's': /* space */
3507 return ' ';
3509 case 'M':
3510 if ((c = nextc(p)) != '-') {
3511 yyerror(p, "Invalid escape character syntax");
3512 pushback(p, c);
3513 return '\0';
3515 if ((c = nextc(p)) == '\\') {
3516 return read_escape(p) | 0x80;
3518 else if (c == -1) goto eof;
3519 else {
3520 return ((c & 0xff) | 0x80);
3523 case 'C':
3524 if ((c = nextc(p)) != '-') {
3525 yyerror(p, "Invalid escape character syntax");
3526 pushback(p, c);
3527 return '\0';
3529 case 'c':
3530 if ((c = nextc(p))== '\\') {
3531 c = read_escape(p);
3533 else if (c == '?')
3534 return 0177;
3535 else if (c == -1) goto eof;
3536 return c & 0x9f;
3538 eof:
3539 case -1:
3540 yyerror(p, "Invalid escape character syntax");
3541 return '\0';
3543 default:
3544 return c;
3549 static int
3550 parse_string(parser_state *p)
3552 int c;
3553 string_type type = (string_type)(intptr_t)p->lex_strterm->car;
3554 int nest_level = (intptr_t)p->lex_strterm->cdr->car;
3555 int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
3556 int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
3557 parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
3559 newtok(p);
3560 while ((c = nextc(p)) != end || nest_level != 0) {
3561 if (hinf && (c == '\n' || c == -1)) {
3562 int line_head;
3563 tokadd(p, '\n');
3564 tokfix(p);
3565 p->lineno++;
3566 p->column = 0;
3567 line_head = hinf->line_head;
3568 hinf->line_head = TRUE;
3569 if (line_head) {
3570 /* check whether end of heredoc */
3571 const char *s = tok(p);
3572 int len = toklen(p);
3573 if (hinf->allow_indent) {
3574 while (ISSPACE(*s) && len > 0) {
3575 ++s;
3576 --len;
3579 if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
3580 return tHEREDOC_END;
3583 if (c == -1) {
3584 char buf[256];
3585 snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term);
3586 yyerror(p, buf);
3587 return 0;
3589 yylval.nd = new_str(p, tok(p), toklen(p));
3590 return tSTRING_MID;
3592 if (c == -1) {
3593 yyerror(p, "unterminated string meets end of file");
3594 return 0;
3596 else if (c == beg) {
3597 nest_level++;
3598 p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
3600 else if (c == end) {
3601 nest_level--;
3602 p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
3604 else if (c == '\\') {
3605 c = nextc(p);
3606 if (type & STR_FUNC_EXPAND) {
3607 if (c == end || c == beg) {
3608 tokadd(p, c);
3610 else if ((c == '\n') && (type & STR_FUNC_ARRAY)) {
3611 p->lineno++;
3612 p->column = 0;
3613 tokadd(p, '\n');
3615 else {
3616 pushback(p, c);
3618 if(type & STR_FUNC_REGEXP)
3619 tokadd(p, '\\');
3621 tokadd(p, read_escape(p));
3622 if (hinf)
3623 hinf->line_head = FALSE;
3625 } else {
3626 if (c != beg && c != end) {
3627 switch (c) {
3628 case '\n':
3629 p->lineno++;
3630 p->column = 0;
3631 break;
3633 case '\\':
3634 break;
3636 default:
3637 if (! ISSPACE(c))
3638 tokadd(p, '\\');
3641 tokadd(p, c);
3643 continue;
3645 else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
3646 c = nextc(p);
3647 if (c == '{') {
3648 tokfix(p);
3649 p->lstate = EXPR_BEG;
3650 p->cmd_start = TRUE;
3651 yylval.nd = new_str(p, tok(p), toklen(p));
3652 if (hinf)
3653 hinf->line_head = FALSE;
3654 return tSTRING_PART;
3656 tokadd(p, '#');
3657 pushback(p, c);
3658 continue;
3660 if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
3661 if (toklen(p) == 0) {
3662 do {
3663 if (c == '\n') {
3664 p->lineno++;
3665 p->column = 0;
3667 } while (ISSPACE(c = nextc(p)));
3668 pushback(p, c);
3669 return tLITERAL_DELIM;
3670 } else {
3671 pushback(p, c);
3672 tokfix(p);
3673 yylval.nd = new_str(p, tok(p), toklen(p));
3674 return tSTRING_MID;
3678 tokadd(p, c);
3682 tokfix(p);
3683 p->lstate = EXPR_END;
3684 end_strterm(p);
3686 if (type & STR_FUNC_XQUOTE) {
3687 yylval.nd = new_xstr(p, tok(p), toklen(p));
3688 return tXSTRING;
3691 if (type & STR_FUNC_REGEXP) {
3692 int f = 0;
3693 int c;
3694 char *s = strndup(tok(p), toklen(p));
3695 char flag[4] = { '\0' };
3697 newtok(p);
3698 while (c = nextc(p), ISALPHA(c)) {
3699 switch (c) {
3700 case 'i': f |= 1; break;
3701 case 'x': f |= 2; break;
3702 case 'm': f |= 4; break;
3703 default: tokadd(p, c); break;
3706 pushback(p, c);
3707 if (toklen(p)) {
3708 char msg[128];
3709 tokfix(p);
3710 snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
3711 toklen(p) > 1 ? "s" : "", tok(p));
3712 yyerror(p, msg);
3714 if (f & 1) strcat(flag, "i");
3715 if (f & 2) strcat(flag, "x");
3716 if (f & 4) strcat(flag, "m");
3717 yylval.nd = new_regx(p, s, strdup(flag));
3719 return tREGEXP;
3722 yylval.nd = new_str(p, tok(p), toklen(p));
3723 return tSTRING;
3727 static int
3728 heredoc_identifier(parser_state *p)
3730 int c;
3731 int type = str_heredoc;
3732 int indent = FALSE;
3733 int quote = FALSE;
3734 node *newnode;
3735 parser_heredoc_info *info;
3737 c = nextc(p);
3738 if (ISSPACE(c) || c == '=') {
3739 pushback(p, c);
3740 return 0;
3742 if (c == '-') {
3743 indent = TRUE;
3744 c = nextc(p);
3746 if (c == '\'' || c == '"') {
3747 int term = c;
3748 if (c == '\'')
3749 quote = TRUE;
3750 newtok(p);
3751 while ((c = nextc(p)) != -1 && c != term) {
3752 if (c == '\n') {
3753 c = -1;
3754 break;
3756 tokadd(p, c);
3758 if (c == -1) {
3759 yyerror(p, "unterminated here document identifier");
3760 return 0;
3762 } else {
3763 if (! identchar(c)) {
3764 pushback(p, c);
3765 if (indent) pushback(p, '-');
3766 return 0;
3768 newtok(p);
3769 do {
3770 tokadd(p, c);
3771 } while ((c = nextc(p)) != -1 && identchar(c));
3772 pushback(p, c);
3774 tokfix(p);
3775 newnode = new_heredoc(p);
3776 info = (parser_heredoc_info*)newnode->cdr;
3777 info->term = strndup(tok(p), toklen(p));
3778 info->term_len = toklen(p);
3779 if (! quote)
3780 type |= STR_FUNC_EXPAND;
3781 info->type = type;
3782 info->allow_indent = indent;
3783 info->line_head = TRUE;
3784 info->doc = NULL;
3785 p->heredocs = push(p->heredocs, newnode);
3786 if (p->parsing_heredoc == NULL) {
3787 node *n = p->heredocs;
3788 while (n->cdr)
3789 n = n->cdr;
3790 p->parsing_heredoc = n;
3792 p->heredoc_starts_nextline = TRUE;
3793 p->lstate = EXPR_END;
3795 yylval.nd = newnode;
3796 return tHEREDOC_BEG;
3799 static int
3800 arg_ambiguous(parser_state *p)
3802 yywarning(p, "ambiguous first argument; put parentheses or even spaces");
3803 return 1;
3806 #include "lex.def"
3808 static int
3809 parser_yylex(parser_state *p)
3811 register int c;
3812 int space_seen = 0;
3813 int cmd_state;
3814 enum mrb_lex_state_enum last_state;
3815 int token_column;
3817 if (p->lex_strterm) {
3818 if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
3819 if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline))
3820 return parse_string(p);
3822 else
3823 return parse_string(p);
3825 cmd_state = p->cmd_start;
3826 p->cmd_start = FALSE;
3827 retry:
3828 last_state = p->lstate;
3829 switch (c = nextc(p)) {
3830 case '\0': /* NUL */
3831 case '\004': /* ^D */
3832 case '\032': /* ^Z */
3833 case -1: /* end of script. */
3834 return 0;
3836 /* white spaces */
3837 case ' ': case '\t': case '\f': case '\r':
3838 case '\13': /* '\v' */
3839 space_seen = 1;
3840 goto retry;
3842 case '#': /* it's a comment */
3843 skip(p, '\n');
3844 /* fall through */
3845 case '\n':
3846 p->heredoc_starts_nextline = FALSE;
3847 if (p->parsing_heredoc != NULL) {
3848 p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
3849 goto normal_newline;
3851 switch (p->lstate) {
3852 case EXPR_BEG:
3853 case EXPR_FNAME:
3854 case EXPR_DOT:
3855 case EXPR_CLASS:
3856 case EXPR_VALUE:
3857 p->lineno++;
3858 p->column = 0;
3859 goto retry;
3860 default:
3861 break;
3863 while ((c = nextc(p))) {
3864 switch (c) {
3865 case ' ': case '\t': case '\f': case '\r':
3866 case '\13': /* '\v' */
3867 space_seen = 1;
3868 break;
3869 case '.':
3870 if ((c = nextc(p)) != '.') {
3871 pushback(p, c);
3872 pushback(p, '.');
3873 goto retry;
3875 case -1: /* EOF */
3876 goto normal_newline;
3877 default:
3878 pushback(p, c);
3879 goto normal_newline;
3882 normal_newline:
3883 p->cmd_start = TRUE;
3884 p->lstate = EXPR_BEG;
3885 return '\n';
3887 case '*':
3888 if ((c = nextc(p)) == '*') {
3889 if ((c = nextc(p)) == '=') {
3890 yylval.id = intern2("**",2);
3891 p->lstate = EXPR_BEG;
3892 return tOP_ASGN;
3894 pushback(p, c);
3895 c = tPOW;
3897 else {
3898 if (c == '=') {
3899 yylval.id = intern_c('*');
3900 p->lstate = EXPR_BEG;
3901 return tOP_ASGN;
3903 pushback(p, c);
3904 if (IS_SPCARG(c)) {
3905 yywarning(p, "`*' interpreted as argument prefix");
3906 c = tSTAR;
3908 else if (IS_BEG()) {
3909 c = tSTAR;
3911 else {
3912 c = '*';
3915 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3916 p->lstate = EXPR_ARG;
3917 } else {
3918 p->lstate = EXPR_BEG;
3920 return c;
3922 case '!':
3923 c = nextc(p);
3924 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3925 p->lstate = EXPR_ARG;
3926 if (c == '@') {
3927 return '!';
3930 else {
3931 p->lstate = EXPR_BEG;
3933 if (c == '=') {
3934 return tNEQ;
3936 if (c == '~') {
3937 return tNMATCH;
3939 pushback(p, c);
3940 return '!';
3942 case '=':
3943 if (p->column == 1) {
3944 if (peeks(p, "begin\n")) {
3945 skips(p, "\n=end\n");
3946 goto retry;
3949 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3950 p->lstate = EXPR_ARG;
3951 } else {
3952 p->lstate = EXPR_BEG;
3954 if ((c = nextc(p)) == '=') {
3955 if ((c = nextc(p)) == '=') {
3956 return tEQQ;
3958 pushback(p, c);
3959 return tEQ;
3961 if (c == '~') {
3962 return tMATCH;
3964 else if (c == '>') {
3965 return tASSOC;
3967 pushback(p, c);
3968 return '=';
3970 case '<':
3971 last_state = p->lstate;
3972 c = nextc(p);
3973 if (c == '<' &&
3974 p->lstate != EXPR_DOT &&
3975 p->lstate != EXPR_CLASS &&
3976 !IS_END() &&
3977 (!IS_ARG() || space_seen)) {
3978 int token = heredoc_identifier(p);
3979 if (token)
3980 return token;
3982 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3983 p->lstate = EXPR_ARG;
3984 } else {
3985 p->lstate = EXPR_BEG;
3986 if (p->lstate == EXPR_CLASS) {
3987 p->cmd_start = TRUE;
3990 if (c == '=') {
3991 if ((c = nextc(p)) == '>') {
3992 return tCMP;
3994 pushback(p, c);
3995 return tLEQ;
3997 if (c == '<') {
3998 if ((c = nextc(p)) == '=') {
3999 yylval.id = intern2("<<",2);
4000 p->lstate = EXPR_BEG;
4001 return tOP_ASGN;
4003 pushback(p, c);
4004 return tLSHFT;
4006 pushback(p, c);
4007 return '<';
4009 case '>':
4010 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4011 p->lstate = EXPR_ARG;
4012 } else {
4013 p->lstate = EXPR_BEG;
4015 if ((c = nextc(p)) == '=') {
4016 return tGEQ;
4018 if (c == '>') {
4019 if ((c = nextc(p)) == '=') {
4020 yylval.id = intern2(">>",2);
4021 p->lstate = EXPR_BEG;
4022 return tOP_ASGN;
4024 pushback(p, c);
4025 return tRSHFT;
4027 pushback(p, c);
4028 return '>';
4030 case '"':
4031 p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
4032 return tSTRING_BEG;
4034 case '\'':
4035 p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
4036 return parse_string(p);
4038 case '`':
4039 if (p->lstate == EXPR_FNAME) {
4040 p->lstate = EXPR_ENDFN;
4041 return '`';
4043 if (p->lstate == EXPR_DOT) {
4044 if (cmd_state)
4045 p->lstate = EXPR_CMDARG;
4046 else
4047 p->lstate = EXPR_ARG;
4048 return '`';
4050 p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
4051 return tXSTRING_BEG;
4053 case '?':
4054 if (IS_END()) {
4055 p->lstate = EXPR_VALUE;
4056 return '?';
4058 c = nextc(p);
4059 if (c == -1) {
4060 yyerror(p, "incomplete character syntax");
4061 return 0;
4063 if (isspace(c)) {
4064 if (!IS_ARG()) {
4065 int c2;
4066 switch (c) {
4067 case ' ':
4068 c2 = 's';
4069 break;
4070 case '\n':
4071 c2 = 'n';
4072 break;
4073 case '\t':
4074 c2 = 't';
4075 break;
4076 case '\v':
4077 c2 = 'v';
4078 break;
4079 case '\r':
4080 c2 = 'r';
4081 break;
4082 case '\f':
4083 c2 = 'f';
4084 break;
4085 default:
4086 c2 = 0;
4087 break;
4089 if (c2) {
4090 char buf[256];
4091 snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
4092 yyerror(p, buf);
4095 ternary:
4096 pushback(p, c);
4097 p->lstate = EXPR_VALUE;
4098 return '?';
4100 token_column = newtok(p);
4101 // need support UTF-8 if configured
4102 if ((isalnum(c) || c == '_')) {
4103 int c2 = nextc(p);
4104 pushback(p, c2);
4105 if ((isalnum(c2) || c2 == '_')) {
4106 goto ternary;
4109 if (c == '\\') {
4110 c = nextc(p);
4111 if (c == 'u') {
4112 #if 0
4113 tokadd_utf8(p);
4114 #endif
4116 else {
4117 pushback(p, c);
4118 c = read_escape(p);
4119 tokadd(p, c);
4122 else {
4123 tokadd(p, c);
4125 tokfix(p);
4126 yylval.nd = new_str(p, tok(p), toklen(p));
4127 p->lstate = EXPR_END;
4128 return tCHAR;
4130 case '&':
4131 if ((c = nextc(p)) == '&') {
4132 p->lstate = EXPR_BEG;
4133 if ((c = nextc(p)) == '=') {
4134 yylval.id = intern2("&&",2);
4135 p->lstate = EXPR_BEG;
4136 return tOP_ASGN;
4138 pushback(p, c);
4139 return tANDOP;
4141 else if (c == '=') {
4142 yylval.id = intern_c('&');
4143 p->lstate = EXPR_BEG;
4144 return tOP_ASGN;
4146 pushback(p, c);
4147 if (IS_SPCARG(c)) {
4148 yywarning(p, "`&' interpreted as argument prefix");
4149 c = tAMPER;
4151 else if (IS_BEG()) {
4152 c = tAMPER;
4154 else {
4155 c = '&';
4157 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4158 p->lstate = EXPR_ARG;
4159 } else {
4160 p->lstate = EXPR_BEG;
4162 return c;
4164 case '|':
4165 if ((c = nextc(p)) == '|') {
4166 p->lstate = EXPR_BEG;
4167 if ((c = nextc(p)) == '=') {
4168 yylval.id = intern2("||",2);
4169 p->lstate = EXPR_BEG;
4170 return tOP_ASGN;
4172 pushback(p, c);
4173 return tOROP;
4175 if (c == '=') {
4176 yylval.id = intern_c('|');
4177 p->lstate = EXPR_BEG;
4178 return tOP_ASGN;
4180 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4181 p->lstate = EXPR_ARG;
4183 else {
4184 p->lstate = EXPR_BEG;
4186 pushback(p, c);
4187 return '|';
4189 case '+':
4190 c = nextc(p);
4191 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4192 p->lstate = EXPR_ARG;
4193 if (c == '@') {
4194 return tUPLUS;
4196 pushback(p, c);
4197 return '+';
4199 if (c == '=') {
4200 yylval.id = intern_c('+');
4201 p->lstate = EXPR_BEG;
4202 return tOP_ASGN;
4204 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
4205 p->lstate = EXPR_BEG;
4206 pushback(p, c);
4207 if (c != -1 && ISDIGIT(c)) {
4208 c = '+';
4209 goto start_num;
4211 return tUPLUS;
4213 p->lstate = EXPR_BEG;
4214 pushback(p, c);
4215 return '+';
4217 case '-':
4218 c = nextc(p);
4219 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4220 p->lstate = EXPR_ARG;
4221 if (c == '@') {
4222 return tUMINUS;
4224 pushback(p, c);
4225 return '-';
4227 if (c == '=') {
4228 yylval.id = intern_c('-');
4229 p->lstate = EXPR_BEG;
4230 return tOP_ASGN;
4232 if (c == '>') {
4233 p->lstate = EXPR_ENDFN;
4234 return tLAMBDA;
4236 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
4237 p->lstate = EXPR_BEG;
4238 pushback(p, c);
4239 if (c != -1 && ISDIGIT(c)) {
4240 return tUMINUS_NUM;
4242 return tUMINUS;
4244 p->lstate = EXPR_BEG;
4245 pushback(p, c);
4246 return '-';
4248 case '.':
4249 p->lstate = EXPR_BEG;
4250 if ((c = nextc(p)) == '.') {
4251 if ((c = nextc(p)) == '.') {
4252 return tDOT3;
4254 pushback(p, c);
4255 return tDOT2;
4257 pushback(p, c);
4258 if (c != -1 && ISDIGIT(c)) {
4259 yyerror(p, "no .<digit> floating literal anymore; put 0 before dot");
4261 p->lstate = EXPR_DOT;
4262 return '.';
4264 start_num:
4265 case '0': case '1': case '2': case '3': case '4':
4266 case '5': case '6': case '7': case '8': case '9':
4268 int is_float, seen_point, seen_e, nondigit;
4270 is_float = seen_point = seen_e = nondigit = 0;
4271 p->lstate = EXPR_END;
4272 token_column = newtok(p);
4273 if (c == '-' || c == '+') {
4274 tokadd(p, c);
4275 c = nextc(p);
4277 if (c == '0') {
4278 #define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0)
4279 int start = toklen(p);
4280 c = nextc(p);
4281 if (c == 'x' || c == 'X') {
4282 /* hexadecimal */
4283 c = nextc(p);
4284 if (c != -1 && ISXDIGIT(c)) {
4285 do {
4286 if (c == '_') {
4287 if (nondigit) break;
4288 nondigit = c;
4289 continue;
4291 if (!ISXDIGIT(c)) break;
4292 nondigit = 0;
4293 tokadd(p, tolower(c));
4294 } while ((c = nextc(p)) != -1);
4296 pushback(p, c);
4297 tokfix(p);
4298 if (toklen(p) == start) {
4299 no_digits();
4301 else if (nondigit) goto trailing_uc;
4302 yylval.nd = new_int(p, tok(p), 16);
4303 return tINTEGER;
4305 if (c == 'b' || c == 'B') {
4306 /* binary */
4307 c = nextc(p);
4308 if (c == '0' || c == '1') {
4309 do {
4310 if (c == '_') {
4311 if (nondigit) break;
4312 nondigit = c;
4313 continue;
4315 if (c != '0' && c != '1') break;
4316 nondigit = 0;
4317 tokadd(p, c);
4318 } while ((c = nextc(p)) != -1);
4320 pushback(p, c);
4321 tokfix(p);
4322 if (toklen(p) == start) {
4323 no_digits();
4325 else if (nondigit) goto trailing_uc;
4326 yylval.nd = new_int(p, tok(p), 2);
4327 return tINTEGER;
4329 if (c == 'd' || c == 'D') {
4330 /* decimal */
4331 c = nextc(p);
4332 if (c != -1 && ISDIGIT(c)) {
4333 do {
4334 if (c == '_') {
4335 if (nondigit) break;
4336 nondigit = c;
4337 continue;
4339 if (!ISDIGIT(c)) break;
4340 nondigit = 0;
4341 tokadd(p, c);
4342 } while ((c = nextc(p)) != -1);
4344 pushback(p, c);
4345 tokfix(p);
4346 if (toklen(p) == start) {
4347 no_digits();
4349 else if (nondigit) goto trailing_uc;
4350 yylval.nd = new_int(p, tok(p), 10);
4351 return tINTEGER;
4353 if (c == '_') {
4354 /* 0_0 */
4355 goto octal_number;
4357 if (c == 'o' || c == 'O') {
4358 /* prefixed octal */
4359 c = nextc(p);
4360 if (c == -1 || c == '_' || !ISDIGIT(c)) {
4361 no_digits();
4364 if (c >= '0' && c <= '7') {
4365 /* octal */
4366 octal_number:
4367 do {
4368 if (c == '_') {
4369 if (nondigit) break;
4370 nondigit = c;
4371 continue;
4373 if (c < '0' || c > '9') break;
4374 if (c > '7') goto invalid_octal;
4375 nondigit = 0;
4376 tokadd(p, c);
4377 } while ((c = nextc(p)) != -1);
4379 if (toklen(p) > start) {
4380 pushback(p, c);
4381 tokfix(p);
4382 if (nondigit) goto trailing_uc;
4383 yylval.nd = new_int(p, tok(p), 8);
4384 return tINTEGER;
4386 if (nondigit) {
4387 pushback(p, c);
4388 goto trailing_uc;
4391 if (c > '7' && c <= '9') {
4392 invalid_octal:
4393 yyerror(p, "Invalid octal digit");
4395 else if (c == '.' || c == 'e' || c == 'E') {
4396 tokadd(p, '0');
4398 else {
4399 pushback(p, c);
4400 yylval.nd = new_int(p, "0", 10);
4401 return tINTEGER;
4405 for (;;) {
4406 switch (c) {
4407 case '0': case '1': case '2': case '3': case '4':
4408 case '5': case '6': case '7': case '8': case '9':
4409 nondigit = 0;
4410 tokadd(p, c);
4411 break;
4413 case '.':
4414 if (nondigit) goto trailing_uc;
4415 if (seen_point || seen_e) {
4416 goto decode_num;
4418 else {
4419 int c0 = nextc(p);
4420 if (c0 == -1 || !ISDIGIT(c0)) {
4421 pushback(p, c0);
4422 goto decode_num;
4424 c = c0;
4426 tokadd(p, '.');
4427 tokadd(p, c);
4428 is_float++;
4429 seen_point++;
4430 nondigit = 0;
4431 break;
4433 case 'e':
4434 case 'E':
4435 if (nondigit) {
4436 pushback(p, c);
4437 c = nondigit;
4438 goto decode_num;
4440 if (seen_e) {
4441 goto decode_num;
4443 tokadd(p, c);
4444 seen_e++;
4445 is_float++;
4446 nondigit = c;
4447 c = nextc(p);
4448 if (c != '-' && c != '+') continue;
4449 tokadd(p, c);
4450 nondigit = c;
4451 break;
4453 case '_': /* `_' in number just ignored */
4454 if (nondigit) goto decode_num;
4455 nondigit = c;
4456 break;
4458 default:
4459 goto decode_num;
4461 c = nextc(p);
4464 decode_num:
4465 pushback(p, c);
4466 if (nondigit) {
4467 trailing_uc:
4468 yyerror_i(p, "trailing `%c' in number", nondigit);
4470 tokfix(p);
4471 if (is_float) {
4472 double d;
4473 char *endp;
4475 errno = 0;
4476 d = strtod(tok(p), &endp);
4477 if (d == 0 && endp == tok(p)) {
4478 yywarning_s(p, "corrupted float value %s", tok(p));
4480 else if (errno == ERANGE) {
4481 yywarning_s(p, "float %s out of range", tok(p));
4482 errno = 0;
4484 yylval.nd = new_float(p, tok(p));
4485 return tFLOAT;
4487 yylval.nd = new_int(p, tok(p), 10);
4488 return tINTEGER;
4491 case ')':
4492 case ']':
4493 p->paren_nest--;
4494 case '}':
4495 COND_LEXPOP();
4496 CMDARG_LEXPOP();
4497 if (c == ')')
4498 p->lstate = EXPR_ENDFN;
4499 else
4500 p->lstate = EXPR_ENDARG;
4501 return c;
4503 case ':':
4504 c = nextc(p);
4505 if (c == ':') {
4506 if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) {
4507 p->lstate = EXPR_BEG;
4508 return tCOLON3;
4510 p->lstate = EXPR_DOT;
4511 return tCOLON2;
4513 if (IS_END() || ISSPACE(c)) {
4514 pushback(p, c);
4515 p->lstate = EXPR_BEG;
4516 return ':';
4518 pushback(p, c);
4519 p->lstate = EXPR_FNAME;
4520 return tSYMBEG;
4522 case '/':
4523 if (IS_BEG()) {
4524 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
4525 return tREGEXP_BEG;
4527 if ((c = nextc(p)) == '=') {
4528 yylval.id = intern_c('/');
4529 p->lstate = EXPR_BEG;
4530 return tOP_ASGN;
4532 pushback(p, c);
4533 if (IS_SPCARG(c)) {
4534 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
4535 return tREGEXP_BEG;
4537 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4538 p->lstate = EXPR_ARG;
4539 } else {
4540 p->lstate = EXPR_BEG;
4542 return '/';
4544 case '^':
4545 if ((c = nextc(p)) == '=') {
4546 yylval.id = intern_c('^');
4547 p->lstate = EXPR_BEG;
4548 return tOP_ASGN;
4550 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4551 p->lstate = EXPR_ARG;
4552 } else {
4553 p->lstate = EXPR_BEG;
4555 pushback(p, c);
4556 return '^';
4558 case ';':
4559 p->lstate = EXPR_BEG;
4560 return ';';
4562 case ',':
4563 p->lstate = EXPR_BEG;
4564 return ',';
4566 case '~':
4567 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4568 if ((c = nextc(p)) != '@') {
4569 pushback(p, c);
4571 p->lstate = EXPR_ARG;
4573 else {
4574 p->lstate = EXPR_BEG;
4576 return '~';
4578 case '(':
4579 if (IS_BEG()) {
4580 c = tLPAREN;
4582 else if (IS_SPCARG(-1)) {
4583 c = tLPAREN_ARG;
4585 p->paren_nest++;
4586 COND_PUSH(0);
4587 CMDARG_PUSH(0);
4588 p->lstate = EXPR_BEG;
4589 return c;
4591 case '[':
4592 p->paren_nest++;
4593 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4594 p->lstate = EXPR_ARG;
4595 if ((c = nextc(p)) == ']') {
4596 if ((c = nextc(p)) == '=') {
4597 return tASET;
4599 pushback(p, c);
4600 return tAREF;
4602 pushback(p, c);
4603 return '[';
4605 else if (IS_BEG()) {
4606 c = tLBRACK;
4608 else if (IS_ARG() && space_seen) {
4609 c = tLBRACK;
4611 p->lstate = EXPR_BEG;
4612 COND_PUSH(0);
4613 CMDARG_PUSH(0);
4614 return c;
4616 case '{':
4617 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
4618 p->lstate = EXPR_BEG;
4619 p->lpar_beg = 0;
4620 p->paren_nest--;
4621 COND_PUSH(0);
4622 CMDARG_PUSH(0);
4623 return tLAMBEG;
4625 if (IS_ARG() || p->lstate == EXPR_END || p->lstate == EXPR_ENDFN)
4626 c = '{'; /* block (primary) */
4627 else if (p->lstate == EXPR_ENDARG)
4628 c = tLBRACE_ARG; /* block (expr) */
4629 else
4630 c = tLBRACE; /* hash */
4631 COND_PUSH(0);
4632 CMDARG_PUSH(0);
4633 p->lstate = EXPR_BEG;
4634 return c;
4636 case '\\':
4637 c = nextc(p);
4638 if (c == '\n') {
4639 p->lineno++;
4640 p->column = 0;
4641 space_seen = 1;
4642 goto retry; /* skip \\n */
4644 pushback(p, c);
4645 return '\\';
4647 case '%':
4648 if (IS_BEG()) {
4649 int term;
4650 int paren;
4652 c = nextc(p);
4653 quotation:
4654 if (c == -1 || !ISALNUM(c)) {
4655 term = c;
4656 c = 'Q';
4658 else {
4659 term = nextc(p);
4660 if (isalnum(term)) {
4661 yyerror(p, "unknown type of %string");
4662 return 0;
4665 if (c == -1 || term == -1) {
4666 yyerror(p, "unterminated quoted string meets end of file");
4667 return 0;
4669 paren = term;
4670 if (term == '(') term = ')';
4671 else if (term == '[') term = ']';
4672 else if (term == '{') term = '}';
4673 else if (term == '<') term = '>';
4674 else paren = 0;
4676 switch (c) {
4677 case 'Q':
4678 p->lex_strterm = new_strterm(p, str_dquote, term, paren);
4679 return tSTRING_BEG;
4681 case 'q':
4682 p->lex_strterm = new_strterm(p, str_squote, term, paren);
4683 return parse_string(p);
4685 case 'W':
4686 p->lex_strterm = new_strterm(p, str_dword, term, paren);
4687 return tWORDS_BEG;
4689 case 'w':
4690 p->lex_strterm = new_strterm(p, str_sword, term, paren);
4691 return tWORDS_BEG;
4693 case 'x':
4694 p->lex_strterm = new_strterm(p, str_xquote, term, paren);
4695 return tXSTRING_BEG;
4697 case 'r':
4698 p->lex_strterm = new_strterm(p, str_regexp, term, paren);
4699 return tREGEXP_BEG;
4701 case 's':
4702 p->lex_strterm = new_strterm(p, str_ssym, term, paren);
4703 return tSYMBEG;
4705 case 'I':
4706 p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
4707 return tSYMBOLS_BEG;
4709 case 'i':
4710 p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
4711 return tSYMBOLS_BEG;
4713 default:
4714 yyerror(p, "unknown type of %string");
4715 return 0;
4718 if ((c = nextc(p)) == '=') {
4719 yylval.id = intern_c('%');
4720 p->lstate = EXPR_BEG;
4721 return tOP_ASGN;
4723 if (IS_SPCARG(c)) {
4724 goto quotation;
4726 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4727 p->lstate = EXPR_ARG;
4728 } else {
4729 p->lstate = EXPR_BEG;
4731 pushback(p, c);
4732 return '%';
4734 case '$':
4735 p->lstate = EXPR_END;
4736 token_column = newtok(p);
4737 c = nextc(p);
4738 switch (c) {
4739 case '_': /* $_: last read line string */
4740 c = nextc(p);
4741 pushback(p, c);
4742 c = '_';
4743 /* fall through */
4744 case '~': /* $~: match-data */
4745 case '*': /* $*: argv */
4746 case '$': /* $$: pid */
4747 case '?': /* $?: last status */
4748 case '!': /* $!: error string */
4749 case '@': /* $@: error position */
4750 case '/': /* $/: input record separator */
4751 case '\\': /* $\: output record separator */
4752 case ';': /* $;: field separator */
4753 case ',': /* $,: output field separator */
4754 case '.': /* $.: last read line number */
4755 case '=': /* $=: ignorecase */
4756 case ':': /* $:: load path */
4757 case '<': /* $<: reading filename */
4758 case '>': /* $>: default output handle */
4759 case '\"': /* $": already loaded files */
4760 tokadd(p, '$');
4761 tokadd(p, c);
4762 tokfix(p);
4763 yylval.id = intern(tok(p));
4764 return tGVAR;
4766 case '-':
4767 tokadd(p, '$');
4768 tokadd(p, c);
4769 c = nextc(p);
4770 pushback(p, c);
4771 gvar:
4772 tokfix(p);
4773 yylval.id = intern(tok(p));
4774 return tGVAR;
4776 case '&': /* $&: last match */
4777 case '`': /* $`: string before last match */
4778 case '\'': /* $': string after last match */
4779 case '+': /* $+: string matches last pattern */
4780 if (last_state == EXPR_FNAME) {
4781 tokadd(p, '$');
4782 tokadd(p, c);
4783 goto gvar;
4785 yylval.nd = new_back_ref(p, c);
4786 return tBACK_REF;
4788 case '1': case '2': case '3':
4789 case '4': case '5': case '6':
4790 case '7': case '8': case '9':
4791 do {
4792 tokadd(p, c);
4793 c = nextc(p);
4794 } while (c != -1 && isdigit(c));
4795 pushback(p, c);
4796 if (last_state == EXPR_FNAME) goto gvar;
4797 tokfix(p);
4798 yylval.nd = new_nth_ref(p, atoi(tok(p)));
4799 return tNTH_REF;
4801 default:
4802 if (!identchar(c)) {
4803 pushback(p, c);
4804 return '$';
4806 case '0':
4807 tokadd(p, '$');
4809 break;
4811 case '@':
4812 c = nextc(p);
4813 token_column = newtok(p);
4814 tokadd(p, '@');
4815 if (c == '@') {
4816 tokadd(p, '@');
4817 c = nextc(p);
4819 if (c != -1 && isdigit(c)) {
4820 if (p->bidx == 1) {
4821 yyerror_i(p, "`@%c' is not allowed as an instance variable name", c);
4823 else {
4824 yyerror_i(p, "`@@%c' is not allowed as a class variable name", c);
4826 return 0;
4828 if (!identchar(c)) {
4829 pushback(p, c);
4830 return '@';
4832 break;
4834 case '_':
4835 token_column = newtok(p);
4836 break;
4838 default:
4839 if (!identchar(c)) {
4840 yyerror_i(p, "Invalid char `\\x%02X' in expression", c);
4841 goto retry;
4844 token_column = newtok(p);
4845 break;
4848 do {
4849 tokadd(p, c);
4850 c = nextc(p);
4851 if (c < 0) break;
4852 } while (identchar(c));
4853 if (token_column == 0 && toklen(p) == 7 && (c < 0 || c == '\n') &&
4854 strncmp(tok(p), "__END__", toklen(p)) == 0)
4855 return -1;
4857 switch (tok(p)[0]) {
4858 case '@': case '$':
4859 pushback(p, c);
4860 break;
4861 default:
4862 if ((c == '!' || c == '?') && !peek(p, '=')) {
4863 tokadd(p, c);
4865 else {
4866 pushback(p, c);
4869 tokfix(p);
4871 int result = 0;
4873 last_state = p->lstate;
4874 switch (tok(p)[0]) {
4875 case '$':
4876 p->lstate = EXPR_END;
4877 result = tGVAR;
4878 break;
4879 case '@':
4880 p->lstate = EXPR_END;
4881 if (tok(p)[1] == '@')
4882 result = tCVAR;
4883 else
4884 result = tIVAR;
4885 break;
4887 default:
4888 if (toklast(p) == '!' || toklast(p) == '?') {
4889 result = tFID;
4891 else {
4892 if (p->lstate == EXPR_FNAME) {
4893 if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
4894 (!peek(p, '=') || (peek_n(p, '>', 1)))) {
4895 result = tIDENTIFIER;
4896 tokadd(p, c);
4897 tokfix(p);
4899 else {
4900 pushback(p, c);
4903 if (result == 0 && isupper((int)tok(p)[0])) {
4904 result = tCONSTANT;
4906 else {
4907 result = tIDENTIFIER;
4911 if (IS_LABEL_POSSIBLE()) {
4912 if (IS_LABEL_SUFFIX(0)) {
4913 p->lstate = EXPR_BEG;
4914 nextc(p);
4915 tokfix(p);
4916 yylval.id = intern(tok(p));
4917 return tLABEL;
4920 if (p->lstate != EXPR_DOT) {
4921 const struct kwtable *kw;
4923 /* See if it is a reserved word. */
4924 kw = mrb_reserved_word(tok(p), toklen(p));
4925 if (kw) {
4926 enum mrb_lex_state_enum state = p->lstate;
4927 p->lstate = kw->state;
4928 if (state == EXPR_FNAME) {
4929 yylval.id = intern(kw->name);
4930 return kw->id[0];
4932 if (p->lstate == EXPR_BEG) {
4933 p->cmd_start = TRUE;
4935 if (kw->id[0] == keyword_do) {
4936 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
4937 p->lpar_beg = 0;
4938 p->paren_nest--;
4939 return keyword_do_LAMBDA;
4941 if (COND_P()) return keyword_do_cond;
4942 if (CMDARG_P() && state != EXPR_CMDARG)
4943 return keyword_do_block;
4944 if (state == EXPR_ENDARG || state == EXPR_BEG)
4945 return keyword_do_block;
4946 return keyword_do;
4948 if (state == EXPR_BEG || state == EXPR_VALUE)
4949 return kw->id[0];
4950 else {
4951 if (kw->id[0] != kw->id[1])
4952 p->lstate = EXPR_BEG;
4953 return kw->id[1];
4958 if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
4959 if (cmd_state) {
4960 p->lstate = EXPR_CMDARG;
4962 else {
4963 p->lstate = EXPR_ARG;
4966 else if (p->lstate == EXPR_FNAME) {
4967 p->lstate = EXPR_ENDFN;
4969 else {
4970 p->lstate = EXPR_END;
4974 mrb_sym ident = intern(tok(p));
4976 yylval.id = ident;
4977 #if 0
4978 if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
4979 p->lstate = EXPR_END;
4981 #endif
4983 return result;
4987 static int
4988 yylex(void *lval, parser_state *p)
4990 int t;
4992 p->ylval = lval;
4993 t = parser_yylex(p);
4995 return t;
4998 static void
4999 parser_init_cxt(parser_state *p, mrbc_context *cxt)
5001 if (!cxt) return;
5002 if (cxt->lineno) p->lineno = cxt->lineno;
5003 if (cxt->filename) p->filename = cxt->filename;
5004 if (cxt->syms) {
5005 int i;
5007 p->locals = cons(0,0);
5008 for (i=0; i<cxt->slen; i++) {
5009 local_add_f(p, cxt->syms[i]);
5012 p->capture_errors = cxt->capture_errors;
5015 static void
5016 parser_update_cxt(parser_state *p, mrbc_context *cxt)
5018 node *n, *n0;
5019 int i = 0;
5021 if (!cxt) return;
5022 if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
5023 n0 = n = p->tree->cdr->car;
5024 while (n) {
5025 i++;
5026 n = n->cdr;
5028 cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
5029 cxt->slen = i;
5030 for (i=0, n=n0; n; i++,n=n->cdr) {
5031 cxt->syms[i] = sym(n->car);
5035 void codedump_all(mrb_state*, int);
5036 void parser_dump(mrb_state *mrb, node *tree, int offset);
5038 void
5039 mrb_parser_parse(parser_state *p, mrbc_context *c)
5041 if (setjmp(p->jmp) != 0) {
5042 yyerror(p, "memory allocation error");
5043 p->nerr++;
5044 p->tree = 0;
5045 return;
5048 p->cmd_start = TRUE;
5049 p->in_def = p->in_single = FALSE;
5050 p->nerr = p->nwarn = 0;
5051 p->lex_strterm = NULL;
5053 parser_init_cxt(p, c);
5054 yyparse(p);
5055 if (!p->tree) {
5056 p->tree = new_nil(p);
5058 parser_update_cxt(p, c);
5059 if (c && c->dump_result) {
5060 parser_dump(p->mrb, p->tree, 0);
5064 parser_state*
5065 mrb_parser_new(mrb_state *mrb)
5067 mrb_pool *pool;
5068 parser_state *p;
5069 static const parser_state parser_state_zero = { 0 };
5071 pool = mrb_pool_open(mrb);
5072 if (!pool) return 0;
5073 p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state));
5074 if (!p) return 0;
5076 *p = parser_state_zero;
5077 p->mrb = mrb;
5078 p->pool = pool;
5079 p->in_def = p->in_single = 0;
5081 p->s = p->send = NULL;
5082 p->f = NULL;
5084 p->cmd_start = TRUE;
5085 p->in_def = p->in_single = FALSE;
5087 p->capture_errors = 0;
5088 p->lineno = 1;
5089 p->column = 0;
5090 #if defined(PARSER_TEST) || defined(PARSER_DEBUG)
5091 yydebug = 1;
5092 #endif
5094 p->lex_strterm = NULL;
5095 p->heredocs = p->parsing_heredoc = NULL;
5097 return p;
5100 void
5101 mrb_parser_free(parser_state *p) {
5102 mrb_pool_close(p->pool);
5105 mrbc_context*
5106 mrbc_context_new(mrb_state *mrb)
5108 mrbc_context *c;
5110 c = (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context));
5111 return c;
5114 void
5115 mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
5117 mrb_free(mrb, cxt->syms);
5118 mrb_free(mrb, cxt);
5121 const char*
5122 mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
5124 if (s) {
5125 int len = strlen(s);
5126 char *p = (char *)mrb_alloca(mrb, len + 1);
5128 memcpy(p, s, len + 1);
5129 c->filename = p;
5130 c->lineno = 1;
5132 return c->filename;
5135 parser_state*
5136 mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
5138 parser_state *p;
5140 p = mrb_parser_new(mrb);
5141 if (!p) return 0;
5142 p->s = p->send = NULL;
5143 p->f = f;
5145 mrb_parser_parse(p, c);
5146 return p;
5149 parser_state*
5150 mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
5152 parser_state *p;
5154 p = mrb_parser_new(mrb);
5155 if (!p) return 0;
5156 p->s = s;
5157 p->send = s + len;
5159 mrb_parser_parse(p, c);
5160 return p;
5163 parser_state*
5164 mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
5166 return mrb_parse_nstring(mrb, s, strlen(s), c);
5169 static mrb_value
5170 load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
5172 int n;
5173 mrb_value v;
5175 if (!p) {
5176 return mrb_undef_value();
5178 if (!p->tree || p->nerr) {
5179 if (p->capture_errors) {
5180 char buf[256];
5182 n = snprintf(buf, sizeof(buf), "line %d: %s\n",
5183 p->error_buffer[0].lineno, p->error_buffer[0].message);
5184 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
5185 mrb_parser_free(p);
5186 return mrb_undef_value();
5188 else {
5189 static const char msg[] = "syntax error";
5190 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
5191 mrb_parser_free(p);
5192 return mrb_undef_value();
5195 n = mrb_generate_code(mrb, p);
5196 mrb_parser_free(p);
5197 if (n < 0) {
5198 static const char msg[] = "codegen error";
5199 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
5200 return mrb_nil_value();
5202 if (c) {
5203 if (c->dump_result) codedump_all(mrb, n);
5204 if (c->no_exec) return mrb_fixnum_value(n);
5206 v = mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
5207 if (mrb->exc) return mrb_nil_value();
5208 return v;
5211 mrb_value
5212 mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
5214 return load_exec(mrb, mrb_parse_file(mrb, f, c), c);
5217 mrb_value
5218 mrb_load_file(mrb_state *mrb, FILE *f)
5220 return mrb_load_file_cxt(mrb, f, NULL);
5223 mrb_value
5224 mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
5226 return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
5229 mrb_value
5230 mrb_load_nstring(mrb_state *mrb, const char *s, int len)
5232 return mrb_load_nstring_cxt(mrb, s, len, NULL);
5235 mrb_value
5236 mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
5238 return mrb_load_nstring_cxt(mrb, s, strlen(s), c);
5241 mrb_value
5242 mrb_load_string(mrb_state *mrb, const char *s)
5244 return mrb_load_string_cxt(mrb, s, NULL);
5247 #ifdef ENABLE_STDIO
5249 static void
5250 dump_prefix(int offset)
5252 while (offset--) {
5253 putc(' ', stdout);
5254 putc(' ', stdout);
5258 static void
5259 dump_recur(mrb_state *mrb, node *tree, int offset)
5261 while (tree) {
5262 parser_dump(mrb, tree->car, offset);
5263 tree = tree->cdr;
5267 #endif
5269 void
5270 parser_dump(mrb_state *mrb, node *tree, int offset)
5272 #ifdef ENABLE_STDIO
5273 int n;
5275 if (!tree) return;
5276 again:
5277 dump_prefix(offset);
5278 n = (int)(intptr_t)tree->car;
5279 tree = tree->cdr;
5280 switch (n) {
5281 case NODE_BEGIN:
5282 printf("NODE_BEGIN:\n");
5283 dump_recur(mrb, tree, offset+1);
5284 break;
5286 case NODE_RESCUE:
5287 printf("NODE_RESCUE:\n");
5288 if (tree->car) {
5289 dump_prefix(offset+1);
5290 printf("body:\n");
5291 parser_dump(mrb, tree->car, offset+2);
5293 tree = tree->cdr;
5294 if (tree->car) {
5295 node *n2 = tree->car;
5297 dump_prefix(offset+1);
5298 printf("rescue:\n");
5299 while (n2) {
5300 node *n3 = n2->car;
5301 if (n3->car) {
5302 dump_prefix(offset+2);
5303 printf("handle classes:\n");
5304 dump_recur(mrb, n3->car, offset+3);
5306 if (n3->cdr->car) {
5307 dump_prefix(offset+2);
5308 printf("exc_var:\n");
5309 parser_dump(mrb, n3->cdr->car, offset+3);
5311 if (n3->cdr->cdr->car) {
5312 dump_prefix(offset+2);
5313 printf("rescue body:\n");
5314 parser_dump(mrb, n3->cdr->cdr->car, offset+3);
5316 n2 = n2->cdr;
5319 tree = tree->cdr;
5320 if (tree->car) {
5321 dump_prefix(offset+1);
5322 printf("else:\n");
5323 parser_dump(mrb, tree->car, offset+2);
5325 break;
5327 case NODE_ENSURE:
5328 printf("NODE_ENSURE:\n");
5329 dump_prefix(offset+1);
5330 printf("body:\n");
5331 parser_dump(mrb, tree->car, offset+2);
5332 dump_prefix(offset+1);
5333 printf("ensure:\n");
5334 parser_dump(mrb, tree->cdr->cdr, offset+2);
5335 break;
5337 case NODE_LAMBDA:
5338 printf("NODE_BLOCK:\n");
5339 goto block;
5341 case NODE_BLOCK:
5342 block:
5343 printf("NODE_BLOCK:\n");
5344 tree = tree->cdr;
5345 if (tree->car) {
5346 node *n = tree->car;
5348 if (n->car) {
5349 dump_prefix(offset+1);
5350 printf("mandatory args:\n");
5351 dump_recur(mrb, n->car, offset+2);
5353 n = n->cdr;
5354 if (n->car) {
5355 dump_prefix(offset+1);
5356 printf("optional args:\n");
5358 node *n2 = n->car;
5360 while (n2) {
5361 dump_prefix(offset+2);
5362 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5363 parser_dump(mrb, n2->car->cdr, 0);
5364 n2 = n2->cdr;
5368 n = n->cdr;
5369 if (n->car) {
5370 dump_prefix(offset+1);
5371 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5373 n = n->cdr;
5374 if (n->car) {
5375 dump_prefix(offset+1);
5376 printf("post mandatory args:\n");
5377 dump_recur(mrb, n->car, offset+2);
5379 n = n->cdr;
5380 if (n) {
5381 dump_prefix(offset+1);
5382 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5385 dump_prefix(offset+1);
5386 printf("body:\n");
5387 parser_dump(mrb, tree->cdr->car, offset+2);
5388 break;
5390 case NODE_IF:
5391 printf("NODE_IF:\n");
5392 dump_prefix(offset+1);
5393 printf("cond:\n");
5394 parser_dump(mrb, tree->car, offset+2);
5395 dump_prefix(offset+1);
5396 printf("then:\n");
5397 parser_dump(mrb, tree->cdr->car, offset+2);
5398 if (tree->cdr->cdr->car) {
5399 dump_prefix(offset+1);
5400 printf("else:\n");
5401 parser_dump(mrb, tree->cdr->cdr->car, offset+2);
5403 break;
5405 case NODE_AND:
5406 printf("NODE_AND:\n");
5407 parser_dump(mrb, tree->car, offset+1);
5408 parser_dump(mrb, tree->cdr, offset+1);
5409 break;
5411 case NODE_OR:
5412 printf("NODE_OR:\n");
5413 parser_dump(mrb, tree->car, offset+1);
5414 parser_dump(mrb, tree->cdr, offset+1);
5415 break;
5417 case NODE_CASE:
5418 printf("NODE_CASE:\n");
5419 if (tree->car) {
5420 parser_dump(mrb, tree->car, offset+1);
5422 tree = tree->cdr;
5423 while (tree) {
5424 dump_prefix(offset+1);
5425 printf("case:\n");
5426 dump_recur(mrb, tree->car->car, offset+2);
5427 dump_prefix(offset+1);
5428 printf("body:\n");
5429 parser_dump(mrb, tree->car->cdr, offset+2);
5430 tree = tree->cdr;
5432 break;
5434 case NODE_WHILE:
5435 printf("NODE_WHILE:\n");
5436 dump_prefix(offset+1);
5437 printf("cond:\n");
5438 parser_dump(mrb, tree->car, offset+2);
5439 dump_prefix(offset+1);
5440 printf("body:\n");
5441 parser_dump(mrb, tree->cdr, offset+2);
5442 break;
5444 case NODE_UNTIL:
5445 printf("NODE_UNTIL:\n");
5446 dump_prefix(offset+1);
5447 printf("cond:\n");
5448 parser_dump(mrb, tree->car, offset+2);
5449 dump_prefix(offset+1);
5450 printf("body:\n");
5451 parser_dump(mrb, tree->cdr, offset+2);
5452 break;
5454 case NODE_FOR:
5455 printf("NODE_FOR:\n");
5456 dump_prefix(offset+1);
5457 printf("var:\n");
5459 node *n2 = tree->car;
5461 if (n2->car) {
5462 dump_prefix(offset+2);
5463 printf("pre:\n");
5464 dump_recur(mrb, n2->car, offset+3);
5466 n2 = n2->cdr;
5467 if (n2) {
5468 if (n2->car) {
5469 dump_prefix(offset+2);
5470 printf("rest:\n");
5471 parser_dump(mrb, n2->car, offset+3);
5473 n2 = n2->cdr;
5474 if (n2) {
5475 if (n2->car) {
5476 dump_prefix(offset+2);
5477 printf("post:\n");
5478 dump_recur(mrb, n2->car, offset+3);
5483 tree = tree->cdr;
5484 dump_prefix(offset+1);
5485 printf("in:\n");
5486 parser_dump(mrb, tree->car, offset+2);
5487 tree = tree->cdr;
5488 dump_prefix(offset+1);
5489 printf("do:\n");
5490 parser_dump(mrb, tree->car, offset+2);
5491 break;
5493 case NODE_SCOPE:
5494 printf("NODE_SCOPE:\n");
5496 node *n2 = tree->car;
5498 if (n2 && (n2->car || n2->cdr)) {
5499 dump_prefix(offset+1);
5500 printf("local variables:\n");
5501 dump_prefix(offset+2);
5502 while (n2) {
5503 if (n2->car) {
5504 if (n2 != tree->car) printf(", ");
5505 printf("%s", mrb_sym2name(mrb, sym(n2->car)));
5507 n2 = n2->cdr;
5509 printf("\n");
5512 tree = tree->cdr;
5513 offset++;
5514 goto again;
5516 case NODE_FCALL:
5517 case NODE_CALL:
5518 printf("NODE_CALL:\n");
5519 parser_dump(mrb, tree->car, offset+1);
5520 dump_prefix(offset+1);
5521 printf("method='%s' (%d)\n",
5522 mrb_sym2name(mrb, sym(tree->cdr->car)),
5523 (int)(intptr_t)tree->cdr->car);
5524 tree = tree->cdr->cdr->car;
5525 if (tree) {
5526 dump_prefix(offset+1);
5527 printf("args:\n");
5528 dump_recur(mrb, tree->car, offset+2);
5529 if (tree->cdr) {
5530 dump_prefix(offset+1);
5531 printf("block:\n");
5532 parser_dump(mrb, tree->cdr, offset+2);
5535 break;
5537 case NODE_DOT2:
5538 printf("NODE_DOT2:\n");
5539 parser_dump(mrb, tree->car, offset+1);
5540 parser_dump(mrb, tree->cdr, offset+1);
5541 break;
5543 case NODE_DOT3:
5544 printf("NODE_DOT3:\n");
5545 parser_dump(mrb, tree->car, offset+1);
5546 parser_dump(mrb, tree->cdr, offset+1);
5547 break;
5549 case NODE_COLON2:
5550 printf("NODE_COLON2:\n");
5551 parser_dump(mrb, tree->car, offset+1);
5552 dump_prefix(offset+1);
5553 printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr)));
5554 break;
5556 case NODE_COLON3:
5557 printf("NODE_COLON3:\n");
5558 dump_prefix(offset+1);
5559 printf("::%s\n", mrb_sym2name(mrb, sym(tree)));
5560 break;
5562 case NODE_ARRAY:
5563 printf("NODE_ARRAY:\n");
5564 dump_recur(mrb, tree, offset+1);
5565 break;
5567 case NODE_HASH:
5568 printf("NODE_HASH:\n");
5569 while (tree) {
5570 dump_prefix(offset+1);
5571 printf("key:\n");
5572 parser_dump(mrb, tree->car->car, offset+2);
5573 dump_prefix(offset+1);
5574 printf("value:\n");
5575 parser_dump(mrb, tree->car->cdr, offset+2);
5576 tree = tree->cdr;
5578 break;
5580 case NODE_SPLAT:
5581 printf("NODE_SPLAT:\n");
5582 parser_dump(mrb, tree, offset+1);
5583 break;
5585 case NODE_ASGN:
5586 printf("NODE_ASGN:\n");
5587 dump_prefix(offset+1);
5588 printf("lhs:\n");
5589 parser_dump(mrb, tree->car, offset+2);
5590 dump_prefix(offset+1);
5591 printf("rhs:\n");
5592 parser_dump(mrb, tree->cdr, offset+2);
5593 break;
5595 case NODE_MASGN:
5596 printf("NODE_MASGN:\n");
5597 dump_prefix(offset+1);
5598 printf("mlhs:\n");
5600 node *n2 = tree->car;
5602 if (n2->car) {
5603 dump_prefix(offset+2);
5604 printf("pre:\n");
5605 dump_recur(mrb, n2->car, offset+3);
5607 n2 = n2->cdr;
5608 if (n2) {
5609 if (n2->car) {
5610 dump_prefix(offset+2);
5611 printf("rest:\n");
5612 if (n2->car == (node*)-1) {
5613 dump_prefix(offset+2);
5614 printf("(empty)\n");
5616 else {
5617 parser_dump(mrb, n2->car, offset+3);
5620 n2 = n2->cdr;
5621 if (n2) {
5622 if (n2->car) {
5623 dump_prefix(offset+2);
5624 printf("post:\n");
5625 dump_recur(mrb, n2->car, offset+3);
5630 dump_prefix(offset+1);
5631 printf("rhs:\n");
5632 parser_dump(mrb, tree->cdr, offset+2);
5633 break;
5635 case NODE_OP_ASGN:
5636 printf("NODE_OP_ASGN:\n");
5637 dump_prefix(offset+1);
5638 printf("lhs:\n");
5639 parser_dump(mrb, tree->car, offset+2);
5640 tree = tree->cdr;
5641 dump_prefix(offset+1);
5642 printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
5643 tree = tree->cdr;
5644 parser_dump(mrb, tree->car, offset+1);
5645 break;
5647 case NODE_SUPER:
5648 printf("NODE_SUPER:\n");
5649 if (tree) {
5650 dump_prefix(offset+1);
5651 printf("args:\n");
5652 dump_recur(mrb, tree->car, offset+2);
5653 if (tree->cdr) {
5654 dump_prefix(offset+1);
5655 printf("block:\n");
5656 parser_dump(mrb, tree->cdr, offset+2);
5659 break;
5661 case NODE_ZSUPER:
5662 printf("NODE_ZSUPER\n");
5663 break;
5665 case NODE_RETURN:
5666 printf("NODE_RETURN:\n");
5667 parser_dump(mrb, tree, offset+1);
5668 break;
5670 case NODE_YIELD:
5671 printf("NODE_YIELD:\n");
5672 dump_recur(mrb, tree, offset+1);
5673 break;
5675 case NODE_BREAK:
5676 printf("NODE_BREAK:\n");
5677 parser_dump(mrb, tree, offset+1);
5678 break;
5680 case NODE_NEXT:
5681 printf("NODE_NEXT:\n");
5682 parser_dump(mrb, tree, offset+1);
5683 break;
5685 case NODE_REDO:
5686 printf("NODE_REDO\n");
5687 break;
5689 case NODE_RETRY:
5690 printf("NODE_RETRY\n");
5691 break;
5693 case NODE_LVAR:
5694 printf("NODE_LVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5695 break;
5697 case NODE_GVAR:
5698 printf("NODE_GVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5699 break;
5701 case NODE_IVAR:
5702 printf("NODE_IVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5703 break;
5705 case NODE_CVAR:
5706 printf("NODE_CVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5707 break;
5709 case NODE_CONST:
5710 printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree)));
5711 break;
5713 case NODE_MATCH:
5714 printf("NODE_MATCH:\n");
5715 dump_prefix(offset + 1);
5716 printf("lhs:\n");
5717 parser_dump(mrb, tree->car, offset + 2);
5718 dump_prefix(offset + 1);
5719 printf("rhs:\n");
5720 parser_dump(mrb, tree->cdr, offset + 2);
5721 break;
5723 case NODE_BACK_REF:
5724 printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
5725 break;
5727 case NODE_NTH_REF:
5728 printf("NODE_NTH_REF: $%d\n", (int)(intptr_t)tree);
5729 break;
5731 case NODE_ARG:
5732 printf("NODE_ARG %s\n", mrb_sym2name(mrb, sym(tree)));
5733 break;
5735 case NODE_BLOCK_ARG:
5736 printf("NODE_BLOCK_ARG:\n");
5737 parser_dump(mrb, tree, offset+1);
5738 break;
5740 case NODE_INT:
5741 printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
5742 break;
5744 case NODE_FLOAT:
5745 printf("NODE_FLOAT %s\n", (char*)tree);
5746 break;
5748 case NODE_NEGATE:
5749 printf("NODE_NEGATE\n");
5750 parser_dump(mrb, tree, offset+1);
5751 break;
5753 case NODE_STR:
5754 printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
5755 break;
5757 case NODE_DSTR:
5758 printf("NODE_DSTR\n");
5759 dump_recur(mrb, tree, offset+1);
5760 break;
5762 case NODE_XSTR:
5763 printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
5764 break;
5766 case NODE_DXSTR:
5767 printf("NODE_DXSTR\n");
5768 dump_recur(mrb, tree, offset+1);
5769 break;
5771 case NODE_REGX:
5772 printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
5773 break;
5775 case NODE_DREGX:
5776 printf("NODE_DREGX\n");
5777 dump_recur(mrb, tree->car, offset+1);
5778 dump_prefix(offset);
5779 printf("tail: %s\n", (char*)tree->cdr->cdr->car);
5780 dump_prefix(offset);
5781 printf("opt: %s\n", (char*)tree->cdr->cdr->cdr);
5782 break;
5784 case NODE_SYM:
5785 printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree)));
5786 break;
5788 case NODE_SELF:
5789 printf("NODE_SELF\n");
5790 break;
5792 case NODE_NIL:
5793 printf("NODE_NIL\n");
5794 break;
5796 case NODE_TRUE:
5797 printf("NODE_TRUE\n");
5798 break;
5800 case NODE_FALSE:
5801 printf("NODE_FALSE\n");
5802 break;
5804 case NODE_ALIAS:
5805 printf("NODE_ALIAS %s %s:\n",
5806 mrb_sym2name(mrb, sym(tree->car)),
5807 mrb_sym2name(mrb, sym(tree->cdr)));
5808 break;
5810 case NODE_UNDEF:
5811 printf("NODE_UNDEF");
5813 node *t = tree;
5814 while (t) {
5815 printf(" %s", mrb_sym2name(mrb, sym(t->car)));
5816 t = t->cdr;
5819 printf(":\n");
5820 break;
5822 case NODE_CLASS:
5823 printf("NODE_CLASS:\n");
5824 if (tree->car->car == (node*)0) {
5825 dump_prefix(offset+1);
5826 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5828 else if (tree->car->car == (node*)1) {
5829 dump_prefix(offset+1);
5830 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5832 else {
5833 parser_dump(mrb, tree->car->car, offset+1);
5834 dump_prefix(offset+1);
5835 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5837 if (tree->cdr->car) {
5838 dump_prefix(offset+1);
5839 printf("super:\n");
5840 parser_dump(mrb, tree->cdr->car, offset+2);
5842 dump_prefix(offset+1);
5843 printf("body:\n");
5844 parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2);
5845 break;
5847 case NODE_MODULE:
5848 printf("NODE_MODULE:\n");
5849 if (tree->car->car == (node*)0) {
5850 dump_prefix(offset+1);
5851 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5853 else if (tree->car->car == (node*)1) {
5854 dump_prefix(offset+1);
5855 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5857 else {
5858 parser_dump(mrb, tree->car->car, offset+1);
5859 dump_prefix(offset+1);
5860 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5862 dump_prefix(offset+1);
5863 printf("body:\n");
5864 parser_dump(mrb, tree->cdr->car->cdr, offset+2);
5865 break;
5867 case NODE_SCLASS:
5868 printf("NODE_SCLASS:\n");
5869 parser_dump(mrb, tree->car, offset+1);
5870 dump_prefix(offset+1);
5871 printf("body:\n");
5872 parser_dump(mrb, tree->cdr->car->cdr, offset+2);
5873 break;
5875 case NODE_DEF:
5876 printf("NODE_DEF:\n");
5877 dump_prefix(offset+1);
5878 printf("%s\n", mrb_sym2name(mrb, sym(tree->car)));
5879 tree = tree->cdr;
5881 node *n2 = tree->car;
5883 if (n2 && (n2->car || n2->cdr)) {
5884 dump_prefix(offset+1);
5885 printf("local variables:\n");
5886 dump_prefix(offset+2);
5887 while (n2) {
5888 if (n2->car) {
5889 if (n2 != tree->car) printf(", ");
5890 printf("%s", mrb_sym2name(mrb, sym(n2->car)));
5892 n2 = n2->cdr;
5894 printf("\n");
5897 tree = tree->cdr;
5898 if (tree->car) {
5899 node *n = tree->car;
5901 if (n->car) {
5902 dump_prefix(offset+1);
5903 printf("mandatory args:\n");
5904 dump_recur(mrb, n->car, offset+2);
5906 n = n->cdr;
5907 if (n->car) {
5908 dump_prefix(offset+1);
5909 printf("optional args:\n");
5911 node *n2 = n->car;
5913 while (n2) {
5914 dump_prefix(offset+2);
5915 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5916 parser_dump(mrb, n2->car->cdr, 0);
5917 n2 = n2->cdr;
5921 n = n->cdr;
5922 if (n->car) {
5923 dump_prefix(offset+1);
5924 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5926 n = n->cdr;
5927 if (n->car) {
5928 dump_prefix(offset+1);
5929 printf("post mandatory args:\n");
5930 dump_recur(mrb, n->car, offset+2);
5932 n = n->cdr;
5933 if (n) {
5934 dump_prefix(offset+1);
5935 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5938 parser_dump(mrb, tree->cdr->car, offset+1);
5939 break;
5941 case NODE_SDEF:
5942 printf("NODE_SDEF:\n");
5943 parser_dump(mrb, tree->car, offset+1);
5944 tree = tree->cdr;
5945 dump_prefix(offset+1);
5946 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
5947 tree = tree->cdr->cdr;
5948 if (tree->car) {
5949 node *n = tree->car;
5951 if (n->car) {
5952 dump_prefix(offset+1);
5953 printf("mandatory args:\n");
5954 dump_recur(mrb, n->car, offset+2);
5956 n = n->cdr;
5957 if (n->car) {
5958 dump_prefix(offset+1);
5959 printf("optional args:\n");
5961 node *n2 = n->car;
5963 while (n2) {
5964 dump_prefix(offset+2);
5965 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5966 parser_dump(mrb, n2->car->cdr, 0);
5967 n2 = n2->cdr;
5971 n = n->cdr;
5972 if (n->car) {
5973 dump_prefix(offset+1);
5974 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5976 n = n->cdr;
5977 if (n->car) {
5978 dump_prefix(offset+1);
5979 printf("post mandatory args:\n");
5980 dump_recur(mrb, n->car, offset+2);
5982 n = n->cdr;
5983 if (n) {
5984 dump_prefix(offset+1);
5985 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5988 tree = tree->cdr;
5989 parser_dump(mrb, tree->car, offset+1);
5990 break;
5992 case NODE_POSTEXE:
5993 printf("NODE_POSTEXE:\n");
5994 parser_dump(mrb, tree, offset+1);
5995 break;
5997 case NODE_HEREDOC:
5998 printf("NODE_HEREDOC:\n");
5999 parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
6000 break;
6002 default:
6003 printf("node type: %d (0x%x)\n", (int)n, (int)n);
6004 break;
6006 #endif