Merge pull request #1046 from monaka/pr-add-configuration-macro-MRB_PARSER_BUF_SIZE
[mruby.git] / src / parse.y
blob7694644a97ad59fcf91060c586295a4ee447c229
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 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 void
72 cons_free_gen(parser_state *p, node *cons)
74 cons->cdr = p->cells;
75 p->cells = cons;
77 #define cons_free(c) cons_free_gen(p, (c))
79 static void*
80 parser_palloc(parser_state *p, size_t size)
82 void *m = mrb_pool_alloc(p->pool, size);
84 if (!m) {
85 longjmp(p->jmp, 1);
87 return m;
90 static node*
91 cons_gen(parser_state *p, node *car, node *cdr)
93 node *c;
95 if (p->cells) {
96 c = p->cells;
97 p->cells = p->cells->cdr;
99 else {
100 c = (node *)parser_palloc(p, sizeof(mrb_ast_node));
103 c->car = car;
104 c->cdr = cdr;
105 c->lineno = p->lineno;
106 return c;
108 #define cons(a,b) cons_gen(p,(a),(b))
110 static node*
111 list1_gen(parser_state *p, node *a)
113 return cons(a, 0);
115 #define list1(a) list1_gen(p, (a))
117 static node*
118 list2_gen(parser_state *p, node *a, node *b)
120 return cons(a, cons(b,0));
122 #define list2(a,b) list2_gen(p, (a),(b))
124 static node*
125 list3_gen(parser_state *p, node *a, node *b, node *c)
127 return cons(a, cons(b, cons(c,0)));
129 #define list3(a,b,c) list3_gen(p, (a),(b),(c))
131 static node*
132 list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
134 return cons(a, cons(b, cons(c, cons(d, 0))));
136 #define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
138 static node*
139 list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
141 return cons(a, cons(b, cons(c, cons(d, cons(e, 0)))));
143 #define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
145 static node*
146 list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
148 return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
150 #define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
152 static node*
153 append_gen(parser_state *p, node *a, node *b)
155 node *c = a;
157 if (!a) return b;
158 while (c->cdr) {
159 c = c->cdr;
161 if (b) {
162 c->cdr = b;
164 return a;
166 #define append(a,b) append_gen(p,(a),(b))
167 #define push(a,b) append_gen(p,(a),list1(b))
169 static char*
170 parser_strndup(parser_state *p, const char *s, size_t len)
172 char *b = (char *)parser_palloc(p, len+1);
174 memcpy(b, s, len);
175 b[len] = '\0';
176 return b;
178 #define strndup(s,len) parser_strndup(p, s, len)
180 static char*
181 parser_strdup(parser_state *p, const char *s)
183 return parser_strndup(p, s, strlen(s));
185 #undef strdup
186 #define strdup(s) parser_strdup(p, s)
188 // xxx -----------------------------
190 static node*
191 local_switch(parser_state *p)
193 node *prev = p->locals;
195 p->locals = cons(0, 0);
196 return prev;
199 static void
200 local_resume(parser_state *p, node *prev)
202 p->locals = prev;
205 static void
206 local_nest(parser_state *p)
208 p->locals = cons(0, p->locals);
211 static void
212 local_unnest(parser_state *p)
214 p->locals = p->locals->cdr;
217 static int
218 local_var_p(parser_state *p, mrb_sym sym)
220 node *l = p->locals;
222 while (l) {
223 node *n = l->car;
224 while (n) {
225 if (sym(n->car) == sym) return 1;
226 n = n->cdr;
228 l = l->cdr;
230 return 0;
233 static void
234 local_add_f(parser_state *p, mrb_sym sym)
236 p->locals->car = push(p->locals->car, nsym(sym));
239 static void
240 local_add(parser_state *p, mrb_sym sym)
242 if (!local_var_p(p, sym)) {
243 local_add_f(p, sym);
247 // (:scope (vars..) (prog...))
248 static node*
249 new_scope(parser_state *p, node *body)
251 return cons((node*)NODE_SCOPE, cons(p->locals->car, body));
254 // (:begin prog...)
255 static node*
256 new_begin(parser_state *p, node *body)
258 if (body)
259 return list2((node*)NODE_BEGIN, body);
260 return cons((node*)NODE_BEGIN, 0);
263 #define newline_node(n) (n)
265 // (:rescue body rescue else)
266 static node*
267 new_rescue(parser_state *p, node *body, node *resq, node *els)
269 return list4((node*)NODE_RESCUE, body, resq, els);
272 // (:ensure body ensure)
273 static node*
274 new_ensure(parser_state *p, node *a, node *b)
276 return cons((node*)NODE_ENSURE, cons(a, cons(0, b)));
279 // (:nil)
280 static node*
281 new_nil(parser_state *p)
283 return list1((node*)NODE_NIL);
286 // (:true)
287 static node*
288 new_true(parser_state *p)
290 return list1((node*)NODE_TRUE);
293 // (:false)
294 static node*
295 new_false(parser_state *p)
297 return list1((node*)NODE_FALSE);
300 // (:alias new old)
301 static node*
302 new_alias(parser_state *p, mrb_sym a, mrb_sym b)
304 return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
307 // (:if cond then else)
308 static node*
309 new_if(parser_state *p, node *a, node *b, node *c)
311 return list4((node*)NODE_IF, a, b, c);
314 // (:unless cond then else)
315 static node*
316 new_unless(parser_state *p, node *a, node *b, node *c)
318 return list4((node*)NODE_IF, a, c, b);
321 // (:while cond body)
322 static node*
323 new_while(parser_state *p, node *a, node *b)
325 return cons((node*)NODE_WHILE, cons(a, b));
328 // (:until cond body)
329 static node*
330 new_until(parser_state *p, node *a, node *b)
332 return cons((node*)NODE_UNTIL, cons(a, b));
335 // (:for var obj body)
336 static node*
337 new_for(parser_state *p, node *v, node *o, node *b)
339 return list4((node*)NODE_FOR, v, o, b);
342 // (:case a ((when ...) body) ((when...) body))
343 static node*
344 new_case(parser_state *p, node *a, node *b)
346 node *n = list2((node*)NODE_CASE, a);
347 node *n2 = n;
349 while (n2->cdr) {
350 n2 = n2->cdr;
352 n2->cdr = b;
353 return n;
356 // (:postexe a)
357 static node*
358 new_postexe(parser_state *p, node *a)
360 return cons((node*)NODE_POSTEXE, a);
363 // (:self)
364 static node*
365 new_self(parser_state *p)
367 return list1((node*)NODE_SELF);
370 // (:call a b c)
371 static node*
372 new_call(parser_state *p, node *a, mrb_sym b, node *c)
374 return list4((node*)NODE_CALL, a, nsym(b), c);
377 // (:fcall self mid args)
378 static node*
379 new_fcall(parser_state *p, mrb_sym b, node *c)
381 return list4((node*)NODE_FCALL, new_self(p), nsym(b), c);
384 #if 0
385 // (:vcall self mid)
386 static node*
387 new_vcall(parser_state *p, mrb_sym b)
389 return list3((node*)NODE_VCALL, new_self(p), (node*)b);
391 #endif
393 // (:super . c)
394 static node*
395 new_super(parser_state *p, node *c)
397 return cons((node*)NODE_SUPER, c);
400 // (:zsuper)
401 static node*
402 new_zsuper(parser_state *p)
404 return list1((node*)NODE_ZSUPER);
407 // (:yield . c)
408 static node*
409 new_yield(parser_state *p, node *c)
411 if (c) {
412 if (c->cdr) {
413 yyerror(p, "both block arg and actual block given");
415 return cons((node*)NODE_YIELD, c->car);
417 return cons((node*)NODE_YIELD, 0);
420 // (:return . c)
421 static node*
422 new_return(parser_state *p, node *c)
424 return cons((node*)NODE_RETURN, c);
427 // (:break . c)
428 static node*
429 new_break(parser_state *p, node *c)
431 return cons((node*)NODE_BREAK, c);
434 // (:next . c)
435 static node*
436 new_next(parser_state *p, node *c)
438 return cons((node*)NODE_NEXT, c);
441 // (:redo)
442 static node*
443 new_redo(parser_state *p)
445 return list1((node*)NODE_REDO);
448 // (:retry)
449 static node*
450 new_retry(parser_state *p)
452 return list1((node*)NODE_RETRY);
455 // (:dot2 a b)
456 static node*
457 new_dot2(parser_state *p, node *a, node *b)
459 return cons((node*)NODE_DOT2, cons(a, b));
462 // (:dot3 a b)
463 static node*
464 new_dot3(parser_state *p, node *a, node *b)
466 return cons((node*)NODE_DOT3, cons(a, b));
469 // (:colon2 b c)
470 static node*
471 new_colon2(parser_state *p, node *b, mrb_sym c)
473 return cons((node*)NODE_COLON2, cons(b, nsym(c)));
476 // (:colon3 . c)
477 static node*
478 new_colon3(parser_state *p, mrb_sym c)
480 return cons((node*)NODE_COLON3, nsym(c));
483 // (:and a b)
484 static node*
485 new_and(parser_state *p, node *a, node *b)
487 return cons((node*)NODE_AND, cons(a, b));
490 // (:or a b)
491 static node*
492 new_or(parser_state *p, node *a, node *b)
494 return cons((node*)NODE_OR, cons(a, b));
497 // (:array a...)
498 static node*
499 new_array(parser_state *p, node *a)
501 return cons((node*)NODE_ARRAY, a);
504 // (:splat . a)
505 static node*
506 new_splat(parser_state *p, node *a)
508 return cons((node*)NODE_SPLAT, a);
511 // (:hash (k . v) (k . v)...)
512 static node*
513 new_hash(parser_state *p, node *a)
515 return cons((node*)NODE_HASH, a);
518 // (:sym . a)
519 static node*
520 new_sym(parser_state *p, mrb_sym sym)
522 return cons((node*)NODE_SYM, nsym(sym));
525 static mrb_sym
526 new_strsym(parser_state *p, node* str)
528 const char *s = (const char*)str->cdr->car;
529 size_t len = (size_t)str->cdr->cdr;
531 return mrb_intern2(p->mrb, s, len);
534 // (:lvar . a)
535 static node*
536 new_lvar(parser_state *p, mrb_sym sym)
538 return cons((node*)NODE_LVAR, nsym(sym));
541 // (:gvar . a)
542 static node*
543 new_gvar(parser_state *p, mrb_sym sym)
545 return cons((node*)NODE_GVAR, nsym(sym));
548 // (:ivar . a)
549 static node*
550 new_ivar(parser_state *p, mrb_sym sym)
552 return cons((node*)NODE_IVAR, nsym(sym));
555 // (:cvar . a)
556 static node*
557 new_cvar(parser_state *p, mrb_sym sym)
559 return cons((node*)NODE_CVAR, nsym(sym));
562 // (:const . a)
563 static node*
564 new_const(parser_state *p, mrb_sym sym)
566 return cons((node*)NODE_CONST, nsym(sym));
569 // (:undef a...)
570 static node*
571 new_undef(parser_state *p, mrb_sym sym)
573 return list2((node*)NODE_UNDEF, nsym(sym));
576 // (:class class super body)
577 static node*
578 new_class(parser_state *p, node *c, node *s, node *b)
580 return list4((node*)NODE_CLASS, c, s, cons(p->locals->car, b));
583 // (:sclass obj body)
584 static node*
585 new_sclass(parser_state *p, node *o, node *b)
587 return list3((node*)NODE_SCLASS, o, cons(p->locals->car, b));
590 // (:module module body)
591 static node*
592 new_module(parser_state *p, node *m, node *b)
594 return list3((node*)NODE_MODULE, m, cons(p->locals->car, b));
597 // (:def m lv (arg . body))
598 static node*
599 new_def(parser_state *p, mrb_sym m, node *a, node *b)
601 return list5((node*)NODE_DEF, nsym(m), p->locals->car, a, b);
604 // (:sdef obj m lv (arg . body))
605 static node*
606 new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
608 return list6((node*)NODE_SDEF, o, nsym(m), p->locals->car, a, b);
611 // (:arg . sym)
612 static node*
613 new_arg(parser_state *p, mrb_sym sym)
615 return cons((node*)NODE_ARG, nsym(sym));
618 // (m o r m2 b)
619 // m: (a b c)
620 // o: ((a . e1) (b . e2))
621 // r: a
622 // m2: (a b c)
623 // b: a
624 static node*
625 new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
627 node *n;
629 n = cons(m2, nsym(blk));
630 n = cons(nsym(rest), n);
631 n = cons(opt, n);
632 return cons(m, n);
635 // (:block_arg . a)
636 static node*
637 new_block_arg(parser_state *p, node *a)
639 return cons((node*)NODE_BLOCK_ARG, a);
642 // (:block arg body)
643 static node*
644 new_block(parser_state *p, node *a, node *b)
646 return list4((node*)NODE_BLOCK, p->locals->car, a, b);
649 // (:lambda arg body)
650 static node*
651 new_lambda(parser_state *p, node *a, node *b)
653 return list4((node*)NODE_LAMBDA, p->locals->car, a, b);
656 // (:asgn lhs rhs)
657 static node*
658 new_asgn(parser_state *p, node *a, node *b)
660 return cons((node*)NODE_ASGN, cons(a, b));
663 // (:masgn mlhs=(pre rest post) mrhs)
664 static node*
665 new_masgn(parser_state *p, node *a, node *b)
667 return cons((node*)NODE_MASGN, cons(a, b));
670 // (:asgn lhs rhs)
671 static node*
672 new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
674 return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
677 // (:int . i)
678 static node*
679 new_int(parser_state *p, const char *s, int base)
681 return list3((node*)NODE_INT, (node*)strdup(s), (node*)(intptr_t)base);
684 // (:float . i)
685 static node*
686 new_float(parser_state *p, const char *s)
688 return cons((node*)NODE_FLOAT, (node*)strdup(s));
691 // (:str . (s . len))
692 static node*
693 new_str(parser_state *p, const char *s, int len)
695 return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
698 // (:dstr . a)
699 static node*
700 new_dstr(parser_state *p, node *a)
702 return cons((node*)NODE_DSTR, a);
705 // (:str . (s . len))
706 static node*
707 new_xstr(parser_state *p, const char *s, int len)
709 return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len));
712 // (:xstr . a)
713 static node*
714 new_dxstr(parser_state *p, node *a)
716 return cons((node*)NODE_DXSTR, a);
719 // (:dsym . a)
720 static node*
721 new_dsym(parser_state *p, node *a)
723 return cons((node*)NODE_DSYM, new_dstr(p, a));
726 // (:str . (a . a))
727 static node*
728 new_regx(parser_state *p, const char *p1, const char* p2)
730 return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2));
733 // (:dregx . a)
734 static node*
735 new_dregx(parser_state *p, node *a, node *b)
737 return cons((node*)NODE_DREGX, cons(a, b));
740 // (:backref . n)
741 static node*
742 new_back_ref(parser_state *p, int n)
744 return cons((node*)NODE_BACK_REF, (node*)(intptr_t)n);
747 // (:nthref . n)
748 static node*
749 new_nth_ref(parser_state *p, int n)
751 return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
754 // (:heredoc . a)
755 static node*
756 new_heredoc(parser_state *p)
758 parser_heredoc_info *inf = parser_palloc(p, sizeof(parser_heredoc_info));
759 return cons((node*)NODE_HEREDOC, (node*)inf);
762 static void
763 new_bv(parser_state *p, mrb_sym id)
767 static node*
768 new_literal_delim(parser_state *p)
770 return cons((node*)NODE_LITERAL_DELIM, 0);
773 // (:words . a)
774 static node*
775 new_words(parser_state *p, node *a)
777 return cons((node*)NODE_WORDS, a);
780 // (:symbols . a)
781 static node*
782 new_symbols(parser_state *p, node *a)
784 return cons((node*)NODE_SYMBOLS, a);
787 // xxx -----------------------------
789 // (:call a op)
790 static node*
791 call_uni_op(parser_state *p, node *recv, char *m)
793 return new_call(p, recv, intern(m), 0);
796 // (:call a op b)
797 static node*
798 call_bin_op(parser_state *p, node *recv, char *m, node *arg1)
800 return new_call(p, recv, intern(m), list1(list1(arg1)));
803 static void
804 args_with_block(parser_state *p, node *a, node *b)
806 if (b) {
807 if (a->cdr) {
808 yyerror(p, "both block arg and actual block given");
810 a->cdr = b;
814 static void
815 call_with_block(parser_state *p, node *a, node *b)
817 node *n;
819 if (a->car == (node*)NODE_SUPER ||
820 a->car == (node*)NODE_ZSUPER) {
821 if (!a->cdr) a->cdr = cons(0, b);
822 else {
823 args_with_block(p, a->cdr, b);
826 else {
827 n = a->cdr->cdr->cdr;
828 if (!n->car) n->car = cons(0, b);
829 else {
830 args_with_block(p, n->car, b);
835 static node*
836 negate_lit(parser_state *p, node *n)
838 return cons((node*)NODE_NEGATE, n);
841 static node*
842 cond(node *n)
844 return n;
847 static node*
848 ret_args(parser_state *p, node *n)
850 if (n->cdr) {
851 yyerror(p, "block argument should not be given");
853 if (!n->car->cdr) return n->car->car;
854 return new_array(p, n->car);
857 static void
858 assignable(parser_state *p, node *lhs)
860 if ((int)(intptr_t)lhs->car == NODE_LVAR) {
861 local_add(p, sym(lhs->cdr));
865 static node*
866 var_reference(parser_state *p, node *lhs)
868 node *n;
870 if ((int)(intptr_t)lhs->car == NODE_LVAR) {
871 if (!local_var_p(p, sym(lhs->cdr))) {
872 n = new_fcall(p, sym(lhs->cdr), 0);
873 cons_free(lhs);
874 return n;
878 return lhs;
881 typedef enum mrb_string_type string_type;
883 static node*
884 new_strterm(parser_state *p, string_type type, int term, int paren)
886 return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term)));
889 static void
890 end_strterm(parser_state *p)
892 cons_free(p->lex_strterm->cdr->cdr);
893 cons_free(p->lex_strterm->cdr);
894 cons_free(p->lex_strterm);
895 p->lex_strterm = NULL;
898 parser_heredoc_info *
899 parsing_heredoc_inf(parser_state *p)
901 node *nd = p->parsing_heredoc;
902 if (nd == NULL)
903 return NULL;
904 /* assert(nd->car->car == NODE_HEREDOC); */
905 return (parser_heredoc_info*)nd->car->cdr;
908 static void
909 heredoc_end(parser_state *p)
911 p->parsing_heredoc = p->parsing_heredoc->cdr;
912 if (p->parsing_heredoc == NULL) {
913 p->lstate = EXPR_BEG;
914 p->cmd_start = TRUE;
915 end_strterm(p);
916 p->heredoc_end_now = TRUE;
917 } else {
918 /* next heredoc */
919 p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type;
922 #define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func))
924 // xxx -----------------------------
928 %pure_parser
929 %parse-param {parser_state *p}
930 %lex-param {parser_state *p}
932 %union {
933 node *nd;
934 mrb_sym id;
935 int num;
936 unsigned int stack;
937 const struct vtable *vars;
940 %token
941 keyword_class
942 keyword_module
943 keyword_def
944 keyword_undef
945 keyword_begin
946 keyword_rescue
947 keyword_ensure
948 keyword_end
949 keyword_if
950 keyword_unless
951 keyword_then
952 keyword_elsif
953 keyword_else
954 keyword_case
955 keyword_when
956 keyword_while
957 keyword_until
958 keyword_for
959 keyword_break
960 keyword_next
961 keyword_redo
962 keyword_retry
963 keyword_in
964 keyword_do
965 keyword_do_cond
966 keyword_do_block
967 keyword_do_LAMBDA
968 keyword_return
969 keyword_yield
970 keyword_super
971 keyword_self
972 keyword_nil
973 keyword_true
974 keyword_false
975 keyword_and
976 keyword_or
977 keyword_not
978 modifier_if
979 modifier_unless
980 modifier_while
981 modifier_until
982 modifier_rescue
983 keyword_alias
984 keyword_BEGIN
985 keyword_END
986 keyword__LINE__
987 keyword__FILE__
988 keyword__ENCODING__
990 %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
991 %token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
992 %token <nd> tSTRING tSTRING_PART tSTRING_MID
993 %token <nd> tNTH_REF tBACK_REF
994 %token <num> tREGEXP_END
996 %type <nd> singleton string string_rep string_interp xstring regexp
997 %type <nd> literal numeric cpath symbol
998 %type <nd> top_compstmt top_stmts top_stmt
999 %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
1000 %type <nd> expr_value arg_value primary_value
1001 %type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
1002 %type <nd> args call_args opt_call_args
1003 %type <nd> paren_args opt_paren_args variable
1004 %type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
1005 %type <nd> command_asgn mrhs superclass block_call block_command
1006 %type <nd> f_block_optarg f_block_opt
1007 %type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
1008 %type <nd> assoc_list assocs assoc undef_list backref for_var
1009 %type <nd> block_param opt_block_param block_param_def f_opt
1010 %type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
1011 %type <nd> brace_block cmd_brace_block do_block lhs none f_bad_arg
1012 %type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
1013 %type <id> fsym sym basic_symbol operation operation2 operation3
1014 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg
1015 %type <nd> heredoc words symbols
1017 %token tUPLUS /* unary+ */
1018 %token tUMINUS /* unary- */
1019 %token tPOW /* ** */
1020 %token tCMP /* <=> */
1021 %token tEQ /* == */
1022 %token tEQQ /* === */
1023 %token tNEQ /* != */
1024 %token tGEQ /* >= */
1025 %token tLEQ /* <= */
1026 %token tANDOP tOROP /* && and || */
1027 %token tMATCH tNMATCH /* =~ and !~ */
1028 %token tDOT2 tDOT3 /* .. and ... */
1029 %token tAREF tASET /* [] and []= */
1030 %token tLSHFT tRSHFT /* << and >> */
1031 %token tCOLON2 /* :: */
1032 %token tCOLON3 /* :: at EXPR_BEG */
1033 %token <id> tOP_ASGN /* +=, -= etc. */
1034 %token tASSOC /* => */
1035 %token tLPAREN /* ( */
1036 %token tLPAREN_ARG /* ( */
1037 %token tRPAREN /* ) */
1038 %token tLBRACK /* [ */
1039 %token tLBRACE /* { */
1040 %token tLBRACE_ARG /* { */
1041 %token tSTAR /* * */
1042 %token tAMPER /* & */
1043 %token tLAMBDA /* -> */
1044 %token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
1045 %token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
1046 %token <nd> tHEREDOC_BEG /* <<, <<- */
1047 %token tHEREDOC_END tLITERAL_DELIM
1050 * precedence table
1053 %nonassoc tLOWEST
1054 %nonassoc tLBRACE_ARG
1056 %nonassoc modifier_if modifier_unless modifier_while modifier_until
1057 %left keyword_or keyword_and
1058 %right keyword_not
1059 %right '=' tOP_ASGN
1060 %left modifier_rescue
1061 %right '?' ':'
1062 %nonassoc tDOT2 tDOT3
1063 %left tOROP
1064 %left tANDOP
1065 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
1066 %left '>' tGEQ '<' tLEQ
1067 %left '|' '^'
1068 %left '&'
1069 %left tLSHFT tRSHFT
1070 %left '+' '-'
1071 %left '*' '/' '%'
1072 %right tUMINUS_NUM tUMINUS
1073 %right tPOW
1074 %right '!' '~' tUPLUS
1076 %nonassoc idNULL
1077 %nonassoc idRespond_to
1078 %nonassoc idIFUNC
1079 %nonassoc idCFUNC
1080 %nonassoc id_core_set_method_alias
1081 %nonassoc id_core_set_variable_alias
1082 %nonassoc id_core_undef_method
1083 %nonassoc id_core_define_method
1084 %nonassoc id_core_define_singleton_method
1085 %nonassoc id_core_set_postexe
1087 %token tLAST_TOKEN
1090 program : {
1091 p->lstate = EXPR_BEG;
1092 if (!p->locals) p->locals = cons(0,0);
1094 top_compstmt
1096 p->tree = new_scope(p, $2);
1100 top_compstmt : top_stmts opt_terms
1102 $$ = $1;
1106 top_stmts : none
1108 $$ = new_begin(p, 0);
1110 | top_stmt
1112 $$ = new_begin(p, $1);
1114 | top_stmts terms top_stmt
1116 $$ = push($1, newline_node($3));
1118 | error top_stmt
1120 $$ = new_begin(p, 0);
1124 top_stmt : stmt
1125 | keyword_BEGIN
1127 $<nd>$ = local_switch(p);
1129 '{' top_compstmt '}'
1131 yyerror(p, "BEGIN not supported");
1132 local_resume(p, $<nd>2);
1133 $$ = 0;
1137 bodystmt : compstmt
1138 opt_rescue
1139 opt_else
1140 opt_ensure
1142 if ($2) {
1143 $$ = new_rescue(p, $1, $2, $3);
1145 else if ($3) {
1146 yywarn(p, "else without rescue is useless");
1147 $$ = push($1, $3);
1149 else {
1150 $$ = $1;
1152 if ($4) {
1153 if ($$) {
1154 $$ = new_ensure(p, $$, $4);
1156 else {
1157 $$ = push($4, new_nil(p));
1163 compstmt : stmts opt_terms
1165 $$ = $1;
1169 stmts : none
1171 $$ = new_begin(p, 0);
1173 | stmt
1175 $$ = new_begin(p, $1);
1177 | stmts terms stmt
1179 $$ = push($1, newline_node($3));
1181 | error stmt
1183 $$ = new_begin(p, $2);
1187 stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
1189 $$ = new_alias(p, $2, $4);
1191 | keyword_undef undef_list
1193 $$ = $2;
1195 | stmt modifier_if expr_value
1197 $$ = new_if(p, cond($3), $1, 0);
1199 | stmt modifier_unless expr_value
1201 $$ = new_unless(p, cond($3), $1, 0);
1203 | stmt modifier_while expr_value
1205 $$ = new_while(p, cond($3), $1);
1207 | stmt modifier_until expr_value
1209 $$ = new_until(p, cond($3), $1);
1211 | stmt modifier_rescue stmt
1213 $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0);
1215 | keyword_END '{' compstmt '}'
1217 yyerror(p, "END not suported");
1218 $$ = new_postexe(p, $3);
1220 | command_asgn
1221 | mlhs '=' command_call
1223 $$ = new_masgn(p, $1, $3);
1225 | var_lhs tOP_ASGN command_call
1227 $$ = new_op_asgn(p, $1, $2, $3);
1229 | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
1231 $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
1233 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
1235 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1237 | primary_value '.' tCONSTANT tOP_ASGN command_call
1239 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1241 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
1243 yyerror(p, "constant re-assignment");
1244 $$ = 0;
1246 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
1248 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1250 | backref tOP_ASGN command_call
1252 backref_error(p, $1);
1253 $$ = new_begin(p, 0);
1255 | lhs '=' mrhs
1257 $$ = new_asgn(p, $1, new_array(p, $3));
1259 | mlhs '=' arg_value
1261 $$ = new_masgn(p, $1, $3);
1263 | mlhs '=' mrhs
1265 $$ = new_masgn(p, $1, new_array(p, $3));
1267 | expr
1270 command_asgn : lhs '=' command_call
1272 $$ = new_asgn(p, $1, $3);
1274 | lhs '=' command_asgn
1276 $$ = new_asgn(p, $1, $3);
1281 expr : command_call
1282 | expr keyword_and expr
1284 $$ = new_and(p, $1, $3);
1286 | expr keyword_or expr
1288 $$ = new_or(p, $1, $3);
1290 | keyword_not opt_nl expr
1292 $$ = call_uni_op(p, cond($3), "!");
1294 | '!' command_call
1296 $$ = call_uni_op(p, cond($2), "!");
1298 | arg
1301 expr_value : expr
1303 if (!$1) $$ = new_nil(p);
1304 else $$ = $1;
1308 command_call : command
1309 | block_command
1312 block_command : block_call
1313 | block_call dot_or_colon operation2 command_args
1316 cmd_brace_block : tLBRACE_ARG
1318 local_nest(p);
1320 opt_block_param
1321 compstmt
1324 $$ = new_block(p, $3, $4);
1325 local_unnest(p);
1329 command : operation command_args %prec tLOWEST
1331 $$ = new_fcall(p, $1, $2);
1333 | operation command_args cmd_brace_block
1335 args_with_block(p, $2, $3);
1336 $$ = new_fcall(p, $1, $2);
1338 | primary_value '.' operation2 command_args %prec tLOWEST
1340 $$ = new_call(p, $1, $3, $4);
1342 | primary_value '.' operation2 command_args cmd_brace_block
1344 args_with_block(p, $4, $5);
1345 $$ = new_call(p, $1, $3, $4);
1347 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
1349 $$ = new_call(p, $1, $3, $4);
1351 | primary_value tCOLON2 operation2 command_args cmd_brace_block
1353 args_with_block(p, $4, $5);
1354 $$ = new_call(p, $1, $3, $4);
1356 | keyword_super command_args
1358 $$ = new_super(p, $2);
1360 | keyword_yield command_args
1362 $$ = new_yield(p, $2);
1364 | keyword_return call_args
1366 $$ = new_return(p, ret_args(p, $2));
1368 | keyword_break call_args
1370 $$ = new_break(p, ret_args(p, $2));
1372 | keyword_next call_args
1374 $$ = new_next(p, ret_args(p, $2));
1378 mlhs : mlhs_basic
1380 $$ = $1;
1382 | tLPAREN mlhs_inner rparen
1384 $$ = $2;
1388 mlhs_inner : mlhs_basic
1389 | tLPAREN mlhs_inner rparen
1391 $$ = list1($2);
1395 mlhs_basic : mlhs_list
1397 $$ = list1($1);
1399 | mlhs_list mlhs_item
1401 $$ = list1(push($1,$2));
1403 | mlhs_list tSTAR mlhs_node
1405 $$ = list2($1, $3);
1407 | mlhs_list tSTAR mlhs_node ',' mlhs_post
1409 $$ = list3($1, $3, $5);
1411 | mlhs_list tSTAR
1413 $$ = list2($1, new_nil(p));
1415 | mlhs_list tSTAR ',' mlhs_post
1417 $$ = list3($1, new_nil(p), $4);
1419 | tSTAR mlhs_node
1421 $$ = list2(0, $2);
1423 | tSTAR mlhs_node ',' mlhs_post
1425 $$ = list3(0, $2, $4);
1427 | tSTAR
1429 $$ = list2(0, new_nil(p));
1431 | tSTAR ',' mlhs_post
1433 $$ = list3(0, new_nil(p), $3);
1437 mlhs_item : mlhs_node
1438 | tLPAREN mlhs_inner rparen
1440 $$ = $2;
1444 mlhs_list : mlhs_item ','
1446 $$ = list1($1);
1448 | mlhs_list mlhs_item ','
1450 $$ = push($1, $2);
1454 mlhs_post : mlhs_item
1456 $$ = list1($1);
1458 | mlhs_list mlhs_item
1460 $$ = push($1, $2);
1464 mlhs_node : variable
1466 assignable(p, $1);
1468 | primary_value '[' opt_call_args rbracket
1470 $$ = new_call(p, $1, intern("[]"), $3);
1472 | primary_value '.' tIDENTIFIER
1474 $$ = new_call(p, $1, $3, 0);
1476 | primary_value tCOLON2 tIDENTIFIER
1478 $$ = new_call(p, $1, $3, 0);
1480 | primary_value '.' tCONSTANT
1482 $$ = new_call(p, $1, $3, 0);
1484 | primary_value tCOLON2 tCONSTANT
1486 if (p->in_def || p->in_single)
1487 yyerror(p, "dynamic constant assignment");
1488 $$ = new_colon2(p, $1, $3);
1490 | tCOLON3 tCONSTANT
1492 if (p->in_def || p->in_single)
1493 yyerror(p, "dynamic constant assignment");
1494 $$ = new_colon3(p, $2);
1496 | backref
1498 backref_error(p, $1);
1499 $$ = 0;
1503 lhs : variable
1505 assignable(p, $1);
1507 | primary_value '[' opt_call_args rbracket
1509 $$ = new_call(p, $1, intern("[]"), $3);
1511 | primary_value '.' tIDENTIFIER
1513 $$ = new_call(p, $1, $3, 0);
1515 | primary_value tCOLON2 tIDENTIFIER
1517 $$ = new_call(p, $1, $3, 0);
1519 | primary_value '.' tCONSTANT
1521 $$ = new_call(p, $1, $3, 0);
1523 | primary_value tCOLON2 tCONSTANT
1525 if (p->in_def || p->in_single)
1526 yyerror(p, "dynamic constant assignment");
1527 $$ = new_colon2(p, $1, $3);
1529 | tCOLON3 tCONSTANT
1531 if (p->in_def || p->in_single)
1532 yyerror(p, "dynamic constant assignment");
1533 $$ = new_colon3(p, $2);
1535 | backref
1537 backref_error(p, $1);
1538 $$ = 0;
1542 cname : tIDENTIFIER
1544 yyerror(p, "class/module name must be CONSTANT");
1546 | tCONSTANT
1549 cpath : tCOLON3 cname
1551 $$ = cons((node*)1, nsym($2));
1553 | cname
1555 $$ = cons((node*)0, nsym($1));
1557 | primary_value tCOLON2 cname
1559 $$ = cons($1, nsym($3));
1563 fname : tIDENTIFIER
1564 | tCONSTANT
1565 | tFID
1566 | op
1568 p->lstate = EXPR_ENDFN;
1569 $$ = $1;
1571 | reswords
1573 p->lstate = EXPR_ENDFN;
1574 $$ = $<id>1;
1578 fsym : fname
1579 | basic_symbol
1582 undef_list : fsym
1584 $$ = new_undef(p, $1);
1586 | undef_list ',' {p->lstate = EXPR_FNAME;} fsym
1588 $$ = push($1, nsym($4));
1592 op : '|' { $$ = intern("|"); }
1593 | '^' { $$ = intern("^"); }
1594 | '&' { $$ = intern("&"); }
1595 | tCMP { $$ = intern("<=>"); }
1596 | tEQ { $$ = intern("=="); }
1597 | tEQQ { $$ = intern("==="); }
1598 | tMATCH { $$ = intern("=~"); }
1599 | tNMATCH { $$ = intern("!~"); }
1600 | '>' { $$ = intern(">"); }
1601 | tGEQ { $$ = intern(">="); }
1602 | '<' { $$ = intern("<"); }
1603 | tLEQ { $$ = intern("<="); }
1604 | tNEQ { $$ = intern("!="); }
1605 | tLSHFT { $$ = intern("<<"); }
1606 | tRSHFT { $$ = intern(">>"); }
1607 | '+' { $$ = intern("+"); }
1608 | '-' { $$ = intern("-"); }
1609 | '*' { $$ = intern("*"); }
1610 | tSTAR { $$ = intern("*"); }
1611 | '/' { $$ = intern("/"); }
1612 | '%' { $$ = intern("%"); }
1613 | tPOW { $$ = intern("**"); }
1614 | '!' { $$ = intern("!"); }
1615 | '~' { $$ = intern("~"); }
1616 | tUPLUS { $$ = intern("+@"); }
1617 | tUMINUS { $$ = intern("-@"); }
1618 | tAREF { $$ = intern("[]"); }
1619 | tASET { $$ = intern("[]="); }
1620 | '`' { $$ = intern("`"); }
1623 reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
1624 | keyword_BEGIN | keyword_END
1625 | keyword_alias | keyword_and | keyword_begin
1626 | keyword_break | keyword_case | keyword_class | keyword_def
1627 | keyword_do | keyword_else | keyword_elsif
1628 | keyword_end | keyword_ensure | keyword_false
1629 | keyword_for | keyword_in | keyword_module | keyword_next
1630 | keyword_nil | keyword_not | keyword_or | keyword_redo
1631 | keyword_rescue | keyword_retry | keyword_return | keyword_self
1632 | keyword_super | keyword_then | keyword_true | keyword_undef
1633 | keyword_when | keyword_yield | keyword_if | keyword_unless
1634 | keyword_while | keyword_until
1637 arg : lhs '=' arg
1639 $$ = new_asgn(p, $1, $3);
1641 | lhs '=' arg modifier_rescue arg
1643 $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
1645 | var_lhs tOP_ASGN arg
1647 $$ = new_op_asgn(p, $1, $2, $3);
1649 | var_lhs tOP_ASGN arg modifier_rescue arg
1651 $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0));
1653 | primary_value '[' opt_call_args rbracket tOP_ASGN arg
1655 $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6);
1657 | primary_value '.' tIDENTIFIER tOP_ASGN arg
1659 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1661 | primary_value '.' tCONSTANT tOP_ASGN arg
1663 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1665 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
1667 $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5);
1669 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
1671 yyerror(p, "constant re-assignment");
1672 $$ = new_begin(p, 0);
1674 | tCOLON3 tCONSTANT tOP_ASGN arg
1676 yyerror(p, "constant re-assignment");
1677 $$ = new_begin(p, 0);
1679 | backref tOP_ASGN arg
1681 backref_error(p, $1);
1682 $$ = new_begin(p, 0);
1684 | arg tDOT2 arg
1686 $$ = new_dot2(p, $1, $3);
1688 | arg tDOT3 arg
1690 $$ = new_dot3(p, $1, $3);
1692 | arg '+' arg
1694 $$ = call_bin_op(p, $1, "+", $3);
1696 | arg '-' arg
1698 $$ = call_bin_op(p, $1, "-", $3);
1700 | arg '*' arg
1702 $$ = call_bin_op(p, $1, "*", $3);
1704 | arg '/' arg
1706 $$ = call_bin_op(p, $1, "/", $3);
1708 | arg '%' arg
1710 $$ = call_bin_op(p, $1, "%", $3);
1712 | arg tPOW arg
1714 $$ = call_bin_op(p, $1, "**", $3);
1716 | tUMINUS_NUM tINTEGER tPOW arg
1718 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
1720 | tUMINUS_NUM tFLOAT tPOW arg
1722 $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
1724 | tUPLUS arg
1726 $$ = call_uni_op(p, $2, "+@");
1728 | tUMINUS arg
1730 $$ = call_uni_op(p, $2, "-@");
1732 | arg '|' arg
1734 $$ = call_bin_op(p, $1, "|", $3);
1736 | arg '^' arg
1738 $$ = call_bin_op(p, $1, "^", $3);
1740 | arg '&' arg
1742 $$ = call_bin_op(p, $1, "&", $3);
1744 | arg tCMP arg
1746 $$ = call_bin_op(p, $1, "<=>", $3);
1748 | arg '>' arg
1750 $$ = call_bin_op(p, $1, ">", $3);
1752 | arg tGEQ arg
1754 $$ = call_bin_op(p, $1, ">=", $3);
1756 | arg '<' arg
1758 $$ = call_bin_op(p, $1, "<", $3);
1760 | arg tLEQ arg
1762 $$ = call_bin_op(p, $1, "<=", $3);
1764 | arg tEQ arg
1766 $$ = call_bin_op(p, $1, "==", $3);
1768 | arg tEQQ arg
1770 $$ = call_bin_op(p, $1, "===", $3);
1772 | arg tNEQ arg
1774 $$ = call_bin_op(p, $1, "!=", $3);
1776 | arg tMATCH arg
1778 $$ = call_bin_op(p, $1, "=~", $3);
1779 #if 0
1780 if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
1781 $$ = reg_named_capture_assign($1->nd_lit, $$);
1783 #endif
1785 | arg tNMATCH arg
1787 $$ = call_bin_op(p, $1, "!~", $3);
1789 | '!' arg
1791 $$ = call_uni_op(p, cond($2), "!");
1793 | '~' arg
1795 $$ = call_uni_op(p, cond($2), "~");
1797 | arg tLSHFT arg
1799 $$ = call_bin_op(p, $1, "<<", $3);
1801 | arg tRSHFT arg
1803 $$ = call_bin_op(p, $1, ">>", $3);
1805 | arg tANDOP arg
1807 $$ = new_and(p, $1, $3);
1809 | arg tOROP arg
1811 $$ = new_or(p, $1, $3);
1813 | arg '?' arg opt_nl ':' arg
1815 $$ = new_if(p, cond($1), $3, $6);
1817 | primary
1819 $$ = $1;
1823 arg_value : arg
1825 $$ = $1;
1826 if (!$$) $$ = new_nil(p);
1830 aref_args : none
1831 | args trailer
1833 $$ = $1;
1835 | args ',' assocs trailer
1837 $$ = push($1, new_hash(p, $3));
1839 | assocs trailer
1841 $$ = cons(new_hash(p, $1), 0);
1845 paren_args : '(' opt_call_args rparen
1847 $$ = $2;
1851 opt_paren_args : none
1852 | paren_args
1855 opt_call_args : none
1856 | call_args
1857 | args ','
1859 $$ = cons($1,0);
1861 | args ',' assocs ','
1863 $$ = cons(push($1, new_hash(p, $3)), 0);
1865 | assocs ','
1867 $$ = cons(list1(new_hash(p, $1)), 0);
1871 call_args : command
1873 $$ = cons(list1($1), 0);
1875 | args opt_block_arg
1877 $$ = cons($1, $2);
1879 | assocs opt_block_arg
1881 $$ = cons(list1(new_hash(p, $1)), $2);
1883 | args ',' assocs opt_block_arg
1885 $$ = cons(push($1, new_hash(p, $3)), $4);
1887 | block_arg
1889 $$ = cons(0, $1);
1893 command_args : {
1894 $<stack>$ = p->cmdarg_stack;
1895 CMDARG_PUSH(1);
1897 call_args
1899 p->cmdarg_stack = $<stack>1;
1900 $$ = $2;
1904 block_arg : tAMPER arg_value
1906 $$ = new_block_arg(p, $2);
1910 opt_block_arg : ',' block_arg
1912 $$ = $2;
1914 | none
1916 $$ = 0;
1920 args : arg_value
1922 $$ = cons($1, 0);
1924 | tSTAR arg_value
1926 $$ = cons(new_splat(p, $2), 0);
1928 | args ',' arg_value
1930 $$ = push($1, $3);
1932 | args ',' tSTAR arg_value
1934 $$ = push($1, new_splat(p, $4));
1938 mrhs : args ',' arg_value
1940 $$ = push($1, $3);
1942 | args ',' tSTAR arg_value
1944 $$ = push($1, new_splat(p, $4));
1946 | tSTAR arg_value
1948 $$ = list1(new_splat(p, $2));
1952 primary : literal
1953 | string
1954 | xstring
1955 | regexp
1956 | heredoc
1957 | var_ref
1958 | backref
1959 | tFID
1961 $$ = new_fcall(p, $1, 0);
1963 | keyword_begin
1965 $<stack>1 = p->cmdarg_stack;
1966 p->cmdarg_stack = 0;
1968 bodystmt
1969 keyword_end
1971 p->cmdarg_stack = $<stack>1;
1972 $$ = $3;
1974 | tLPAREN_ARG expr {p->lstate = EXPR_ENDARG;} rparen
1976 $$ = $2;
1978 | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
1980 $$ = 0;
1982 | tLPAREN compstmt ')'
1984 $$ = $2;
1986 | primary_value tCOLON2 tCONSTANT
1988 $$ = new_colon2(p, $1, $3);
1990 | tCOLON3 tCONSTANT
1992 $$ = new_colon3(p, $2);
1994 | tLBRACK aref_args ']'
1996 $$ = new_array(p, $2);
1998 | tLBRACE assoc_list '}'
2000 $$ = new_hash(p, $2);
2002 | keyword_return
2004 $$ = new_return(p, 0);
2006 | keyword_yield '(' call_args rparen
2008 $$ = new_yield(p, $3);
2010 | keyword_yield '(' rparen
2012 $$ = new_yield(p, 0);
2014 | keyword_yield
2016 $$ = new_yield(p, 0);
2018 | keyword_not '(' expr rparen
2020 $$ = call_uni_op(p, cond($3), "!");
2022 | keyword_not '(' rparen
2024 $$ = call_uni_op(p, new_nil(p), "!");
2026 | operation brace_block
2028 $$ = new_fcall(p, $1, cons(0, $2));
2030 | method_call
2031 | method_call brace_block
2033 call_with_block(p, $1, $2);
2034 $$ = $1;
2036 | tLAMBDA
2038 local_nest(p);
2039 $<num>$ = p->lpar_beg;
2040 p->lpar_beg = ++p->paren_nest;
2042 f_larglist
2043 lambda_body
2045 p->lpar_beg = $<num>2;
2046 $$ = new_lambda(p, $3, $4);
2047 local_unnest(p);
2049 | keyword_if expr_value then
2050 compstmt
2051 if_tail
2052 keyword_end
2054 $$ = new_if(p, cond($2), $4, $5);
2056 | keyword_unless expr_value then
2057 compstmt
2058 opt_else
2059 keyword_end
2061 $$ = new_unless(p, cond($2), $4, $5);
2063 | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();}
2064 compstmt
2065 keyword_end
2067 $$ = new_while(p, cond($3), $6);
2069 | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();}
2070 compstmt
2071 keyword_end
2073 $$ = new_until(p, cond($3), $6);
2075 | keyword_case expr_value opt_terms
2076 case_body
2077 keyword_end
2079 $$ = new_case(p, $2, $4);
2081 | keyword_case opt_terms case_body keyword_end
2083 $$ = new_case(p, 0, $3);
2085 | keyword_for for_var keyword_in
2086 {COND_PUSH(1);}
2087 expr_value do
2088 {COND_POP();}
2089 compstmt
2090 keyword_end
2092 $$ = new_for(p, $2, $5, $8);
2094 | keyword_class cpath superclass
2096 if (p->in_def || p->in_single)
2097 yyerror(p, "class definition in method body");
2098 $<nd>$ = local_switch(p);
2100 bodystmt
2101 keyword_end
2103 $$ = new_class(p, $2, $3, $5);
2104 local_resume(p, $<nd>4);
2106 | keyword_class tLSHFT expr
2108 $<num>$ = p->in_def;
2109 p->in_def = 0;
2111 term
2113 $<nd>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single);
2114 p->in_single = 0;
2116 bodystmt
2117 keyword_end
2119 $$ = new_sclass(p, $3, $7);
2120 local_resume(p, $<nd>6->car);
2121 p->in_def = $<num>4;
2122 p->in_single = (int)(intptr_t)$<nd>6->cdr;
2124 | keyword_module cpath
2126 if (p->in_def || p->in_single)
2127 yyerror(p, "module definition in method body");
2128 $<nd>$ = local_switch(p);
2130 bodystmt
2131 keyword_end
2133 $$ = new_module(p, $2, $4);
2134 local_resume(p, $<nd>3);
2136 | keyword_def fname
2138 p->in_def++;
2139 $<nd>$ = local_switch(p);
2141 f_arglist
2142 bodystmt
2143 keyword_end
2145 $$ = new_def(p, $2, $4, $5);
2146 local_resume(p, $<nd>3);
2147 p->in_def--;
2149 | keyword_def singleton dot_or_colon {p->lstate = EXPR_FNAME;} fname
2151 p->in_single++;
2152 p->lstate = EXPR_ENDFN; /* force for args */
2153 $<nd>$ = local_switch(p);
2155 f_arglist
2156 bodystmt
2157 keyword_end
2159 $$ = new_sdef(p, $2, $5, $7, $8);
2160 local_resume(p, $<nd>6);
2161 p->in_single--;
2163 | keyword_break
2165 $$ = new_break(p, 0);
2167 | keyword_next
2169 $$ = new_next(p, 0);
2171 | keyword_redo
2173 $$ = new_redo(p);
2175 | keyword_retry
2177 $$ = new_retry(p);
2181 primary_value : primary
2183 $$ = $1;
2184 if (!$$) $$ = new_nil(p);
2188 then : term
2189 | keyword_then
2190 | term keyword_then
2193 do : term
2194 | keyword_do_cond
2197 if_tail : opt_else
2198 | keyword_elsif expr_value then
2199 compstmt
2200 if_tail
2202 $$ = new_if(p, cond($2), $4, $5);
2206 opt_else : none
2207 | keyword_else compstmt
2209 $$ = $2;
2213 for_var : lhs
2215 $$ = list1(list1($1));
2217 | mlhs
2220 f_marg : f_norm_arg
2222 $$ = new_arg(p, $1);
2224 | tLPAREN f_margs rparen
2226 $$ = new_masgn(p, $2, 0);
2230 f_marg_list : f_marg
2232 $$ = list1($1);
2234 | f_marg_list ',' f_marg
2236 $$ = push($1, $3);
2240 f_margs : f_marg_list
2242 $$ = list3($1,0,0);
2244 | f_marg_list ',' tSTAR f_norm_arg
2246 $$ = list3($1, new_arg(p, $4), 0);
2248 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
2250 $$ = list3($1, new_arg(p, $4), $6);
2252 | f_marg_list ',' tSTAR
2254 $$ = list3($1, (node*)-1, 0);
2256 | f_marg_list ',' tSTAR ',' f_marg_list
2258 $$ = list3($1, (node*)-1, $5);
2260 | tSTAR f_norm_arg
2262 $$ = list3(0, new_arg(p, $2), 0);
2264 | tSTAR f_norm_arg ',' f_marg_list
2266 $$ = list3(0, new_arg(p, $2), $4);
2268 | tSTAR
2270 $$ = list3(0, (node*)-1, 0);
2272 | tSTAR ',' f_marg_list
2274 $$ = list3(0, (node*)-1, $3);
2278 block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
2280 $$ = new_args(p, $1, $3, $5, 0, $6);
2282 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2284 $$ = new_args(p, $1, $3, $5, $7, $8);
2286 | f_arg ',' f_block_optarg opt_f_block_arg
2288 $$ = new_args(p, $1, $3, 0, 0, $4);
2290 | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
2292 $$ = new_args(p, $1, $3, 0, $5, $6);
2294 | f_arg ',' f_rest_arg opt_f_block_arg
2296 $$ = new_args(p, $1, 0, $3, 0, $4);
2298 | f_arg ','
2300 $$ = new_args(p, $1, 0, 1, 0, 0);
2302 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
2304 $$ = new_args(p, $1, 0, $3, $5, $6);
2306 | f_arg opt_f_block_arg
2308 $$ = new_args(p, $1, 0, 0, 0, $2);
2310 | f_block_optarg ',' f_rest_arg opt_f_block_arg
2312 $$ = new_args(p, 0, $1, $3, 0, $4);
2314 | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2316 $$ = new_args(p, 0, $1, $3, $5, $6);
2318 | f_block_optarg opt_f_block_arg
2320 $$ = new_args(p, 0, $1, 0, 0, $2);
2322 | f_block_optarg ',' f_arg opt_f_block_arg
2324 $$ = new_args(p, 0, $1, 0, $3, $4);
2326 | f_rest_arg opt_f_block_arg
2328 $$ = new_args(p, 0, 0, $1, 0, $2);
2330 | f_rest_arg ',' f_arg opt_f_block_arg
2332 $$ = new_args(p, 0, 0, $1, $3, $4);
2334 | f_block_arg
2336 $$ = new_args(p, 0, 0, 0, 0, $1);
2340 opt_block_param : none
2341 | block_param_def
2343 p->cmd_start = TRUE;
2344 $$ = $1;
2348 block_param_def : '|' opt_bv_decl '|'
2350 local_add_f(p, 0);
2351 $$ = 0;
2353 | tOROP
2355 local_add_f(p, 0);
2356 $$ = 0;
2358 | '|' block_param opt_bv_decl '|'
2360 $$ = $2;
2365 opt_bv_decl : opt_nl
2367 $$ = 0;
2369 | opt_nl ';' bv_decls opt_nl
2371 $$ = 0;
2375 bv_decls : bvar
2376 | bv_decls ',' bvar
2379 bvar : tIDENTIFIER
2381 local_add_f(p, $1);
2382 new_bv(p, $1);
2384 | f_bad_arg
2387 f_larglist : '(' f_args opt_bv_decl ')'
2389 $$ = $2;
2391 | f_args
2393 $$ = $1;
2397 lambda_body : tLAMBEG compstmt '}'
2399 $$ = $2;
2401 | keyword_do_LAMBDA compstmt keyword_end
2403 $$ = $2;
2407 do_block : keyword_do_block
2409 local_nest(p);
2411 opt_block_param
2412 compstmt
2413 keyword_end
2415 $$ = new_block(p,$3,$4);
2416 local_unnest(p);
2420 block_call : command do_block
2422 if ($1->car == (node*)NODE_YIELD) {
2423 yyerror(p, "block given to yield");
2425 else {
2426 call_with_block(p, $1, $2);
2428 $$ = $1;
2430 | block_call dot_or_colon operation2 opt_paren_args
2432 $$ = new_call(p, $1, $3, $4);
2434 | block_call dot_or_colon operation2 opt_paren_args brace_block
2436 $$ = new_call(p, $1, $3, $4);
2437 call_with_block(p, $$, $5);
2439 | block_call dot_or_colon operation2 command_args do_block
2441 $$ = new_call(p, $1, $3, $4);
2442 call_with_block(p, $$, $5);
2446 method_call : operation paren_args
2448 $$ = new_fcall(p, $1, $2);
2450 | primary_value '.' operation2 opt_paren_args
2452 $$ = new_call(p, $1, $3, $4);
2454 | primary_value tCOLON2 operation2 paren_args
2456 $$ = new_call(p, $1, $3, $4);
2458 | primary_value tCOLON2 operation3
2460 $$ = new_call(p, $1, $3, 0);
2462 | primary_value '.' paren_args
2464 $$ = new_call(p, $1, intern("call"), $3);
2466 | primary_value tCOLON2 paren_args
2468 $$ = new_call(p, $1, intern("call"), $3);
2470 | keyword_super paren_args
2472 $$ = new_super(p, $2);
2474 | keyword_super
2476 $$ = new_zsuper(p);
2478 | primary_value '[' opt_call_args rbracket
2480 $$ = new_call(p, $1, intern("[]"), $3);
2484 brace_block : '{'
2486 local_nest(p);
2488 opt_block_param
2489 compstmt '}'
2491 $$ = new_block(p,$3,$4);
2492 local_unnest(p);
2494 | keyword_do
2496 local_nest(p);
2498 opt_block_param
2499 compstmt keyword_end
2501 $$ = new_block(p,$3,$4);
2502 local_unnest(p);
2506 case_body : keyword_when args then
2507 compstmt
2508 cases
2510 $$ = cons(cons($2, $4), $5);
2514 cases : opt_else
2516 if ($1) {
2517 $$ = cons(cons(0, $1), 0);
2519 else {
2520 $$ = 0;
2523 | case_body
2526 opt_rescue : keyword_rescue exc_list exc_var then
2527 compstmt
2528 opt_rescue
2530 $$ = list1(list3($2, $3, $5));
2531 if ($6) $$ = append($$, $6);
2533 | none
2536 exc_list : arg_value
2538 $$ = list1($1);
2540 | mrhs
2541 | none
2544 exc_var : tASSOC lhs
2546 $$ = $2;
2548 | none
2551 opt_ensure : keyword_ensure compstmt
2553 $$ = $2;
2555 | none
2558 literal : numeric
2559 | symbol
2560 | words
2561 | symbols
2564 string : tCHAR
2565 | tSTRING
2566 | tSTRING_BEG tSTRING
2568 $$ = $2;
2570 | tSTRING_BEG string_rep tSTRING
2572 $$ = new_dstr(p, push($2, $3));
2576 string_rep : string_interp
2577 | string_rep string_interp
2579 $$ = append($1, $2);
2583 string_interp : tSTRING_MID
2585 $$ = list1($1);
2587 | tSTRING_PART
2589 $<nd>$ = p->lex_strterm;
2590 p->lex_strterm = NULL;
2592 compstmt
2595 p->lex_strterm = $<nd>2;
2596 $$ = list2($1, $3);
2598 | tLITERAL_DELIM
2600 $$ = list1(new_literal_delim(p));
2604 xstring : tXSTRING_BEG tXSTRING
2606 $$ = $2;
2608 | tXSTRING_BEG string_rep tXSTRING
2610 $$ = new_dxstr(p, push($2, $3));
2614 regexp : tREGEXP_BEG tREGEXP
2616 $$ = $2;
2618 | tREGEXP_BEG string_rep tREGEXP
2620 $$ = new_dregx(p, $2, $3);
2624 heredoc : tHEREDOC_BEG
2627 opt_heredoc_bodies : none
2628 | heredoc_bodies
2631 heredoc_bodies : heredoc_body
2632 | heredoc_bodies heredoc_body
2635 heredoc_body : tHEREDOC_END
2637 parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0));
2638 heredoc_end(p);
2640 | string_rep tHEREDOC_END
2642 parsing_heredoc_inf(p)->doc = $1;
2643 heredoc_end(p);
2647 words : tWORDS_BEG tSTRING
2649 $$ = new_words(p, list1($2));
2651 | tWORDS_BEG string_rep tSTRING
2653 $$ = new_words(p, push($2, $3));
2658 symbol : basic_symbol
2660 $$ = new_sym(p, $1);
2662 | tSYMBEG tSTRING_BEG string_interp tSTRING
2664 p->lstate = EXPR_END;
2665 $$ = new_dsym(p, push($3, $4));
2669 basic_symbol : tSYMBEG sym
2671 p->lstate = EXPR_END;
2672 $$ = $2;
2676 sym : fname
2677 | tIVAR
2678 | tGVAR
2679 | tCVAR
2680 | tSTRING
2682 $$ = new_strsym(p, $1);
2684 | tSTRING_BEG tSTRING
2686 $$ = new_strsym(p, $2);
2690 symbols : tSYMBOLS_BEG tSTRING
2692 $$ = new_symbols(p, list1($2));
2694 | tSYMBOLS_BEG string_rep tSTRING
2696 $$ = new_symbols(p, push($2, $3));
2700 numeric : tINTEGER
2701 | tFLOAT
2702 | tUMINUS_NUM tINTEGER %prec tLOWEST
2704 $$ = negate_lit(p, $2);
2706 | tUMINUS_NUM tFLOAT %prec tLOWEST
2708 $$ = negate_lit(p, $2);
2712 variable : tIDENTIFIER
2714 $$ = new_lvar(p, $1);
2716 | tIVAR
2718 $$ = new_ivar(p, $1);
2720 | tGVAR
2722 $$ = new_gvar(p, $1);
2724 | tCVAR
2726 $$ = new_cvar(p, $1);
2728 | tCONSTANT
2730 $$ = new_const(p, $1);
2734 var_lhs : variable
2736 assignable(p, $1);
2740 var_ref : variable
2742 $$ = var_reference(p, $1);
2744 | keyword_nil
2746 $$ = new_nil(p);
2748 | keyword_self
2750 $$ = new_self(p);
2752 | keyword_true
2754 $$ = new_true(p);
2756 | keyword_false
2758 $$ = new_false(p);
2760 | keyword__FILE__
2762 if (!p->filename) {
2763 p->filename = "(null)";
2765 $$ = new_str(p, p->filename, strlen(p->filename));
2767 | keyword__LINE__
2769 char buf[16];
2771 snprintf(buf, sizeof(buf), "%d", p->lineno);
2772 $$ = new_int(p, buf, 10);
2776 backref : tNTH_REF
2777 | tBACK_REF
2780 superclass : term
2782 $$ = 0;
2784 | '<'
2786 p->lstate = EXPR_BEG;
2787 p->cmd_start = TRUE;
2789 expr_value term
2791 $$ = $3;
2793 | error term
2795 yyerrok;
2796 $$ = 0;
2800 f_arglist : '(' f_args rparen
2802 $$ = $2;
2803 p->lstate = EXPR_BEG;
2804 p->cmd_start = TRUE;
2806 | f_args term
2808 $$ = $1;
2812 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
2814 $$ = new_args(p, $1, $3, $5, 0, $6);
2816 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2818 $$ = new_args(p, $1, $3, $5, $7, $8);
2820 | f_arg ',' f_optarg opt_f_block_arg
2822 $$ = new_args(p, $1, $3, 0, 0, $4);
2824 | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
2826 $$ = new_args(p, $1, $3, 0, $5, $6);
2828 | f_arg ',' f_rest_arg opt_f_block_arg
2830 $$ = new_args(p, $1, 0, $3, 0, $4);
2832 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
2834 $$ = new_args(p, $1, 0, $3, $5, $6);
2836 | f_arg opt_f_block_arg
2838 $$ = new_args(p, $1, 0, 0, 0, $2);
2840 | f_optarg ',' f_rest_arg opt_f_block_arg
2842 $$ = new_args(p, 0, $1, $3, 0, $4);
2844 | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
2846 $$ = new_args(p, 0, $1, $3, $5, $6);
2848 | f_optarg opt_f_block_arg
2850 $$ = new_args(p, 0, $1, 0, 0, $2);
2852 | f_optarg ',' f_arg opt_f_block_arg
2854 $$ = new_args(p, 0, $1, 0, $3, $4);
2856 | f_rest_arg opt_f_block_arg
2858 $$ = new_args(p, 0, 0, $1, 0, $2);
2860 | f_rest_arg ',' f_arg opt_f_block_arg
2862 $$ = new_args(p, 0, 0, $1, $3, $4);
2864 | f_block_arg
2866 $$ = new_args(p, 0, 0, 0, 0, $1);
2868 | /* none */
2870 local_add_f(p, 0);
2871 $$ = new_args(p, 0, 0, 0, 0, 0);
2875 f_bad_arg : tCONSTANT
2877 yyerror(p, "formal argument cannot be a constant");
2878 $$ = 0;
2880 | tIVAR
2882 yyerror(p, "formal argument cannot be an instance variable");
2883 $$ = 0;
2885 | tGVAR
2887 yyerror(p, "formal argument cannot be a global variable");
2888 $$ = 0;
2890 | tCVAR
2892 yyerror(p, "formal argument cannot be a class variable");
2893 $$ = 0;
2897 f_norm_arg : f_bad_arg
2899 $$ = 0;
2901 | tIDENTIFIER
2903 local_add_f(p, $1);
2904 $$ = $1;
2908 f_arg_item : f_norm_arg
2910 $$ = new_arg(p, $1);
2912 | tLPAREN f_margs rparen
2914 $$ = new_masgn(p, $2, 0);
2918 f_arg : f_arg_item
2920 $$ = list1($1);
2922 | f_arg ',' f_arg_item
2924 $$ = push($1, $3);
2928 f_opt : tIDENTIFIER '=' arg_value
2930 local_add_f(p, $1);
2931 $$ = cons(nsym($1), $3);
2935 f_block_opt : tIDENTIFIER '=' primary_value
2937 local_add_f(p, $1);
2938 $$ = cons(nsym($1), $3);
2942 f_block_optarg : f_block_opt
2944 $$ = list1($1);
2946 | f_block_optarg ',' f_block_opt
2948 $$ = push($1, $3);
2952 f_optarg : f_opt
2954 $$ = list1($1);
2956 | f_optarg ',' f_opt
2958 $$ = push($1, $3);
2962 restarg_mark : '*'
2963 | tSTAR
2966 f_rest_arg : restarg_mark tIDENTIFIER
2968 local_add_f(p, $2);
2969 $$ = $2;
2971 | restarg_mark
2973 local_add_f(p, 0);
2974 $$ = -1;
2978 blkarg_mark : '&'
2979 | tAMPER
2982 f_block_arg : blkarg_mark tIDENTIFIER
2984 local_add_f(p, $2);
2985 $$ = $2;
2989 opt_f_block_arg : ',' f_block_arg
2991 $$ = $2;
2993 | none
2995 local_add_f(p, 0);
2996 $$ = 0;
3000 singleton : var_ref
3002 $$ = $1;
3003 if (!$$) $$ = new_nil(p);
3005 | '(' {p->lstate = EXPR_BEG;} expr rparen
3007 if ($3 == 0) {
3008 yyerror(p, "can't define singleton method for ().");
3010 else {
3011 switch ((enum node_type)(int)(intptr_t)$3->car) {
3012 case NODE_STR:
3013 case NODE_DSTR:
3014 case NODE_XSTR:
3015 case NODE_DXSTR:
3016 case NODE_DREGX:
3017 case NODE_MATCH:
3018 case NODE_FLOAT:
3019 case NODE_ARRAY:
3020 case NODE_HEREDOC:
3021 yyerror(p, "can't define singleton method for literals");
3022 default:
3023 break;
3026 $$ = $3;
3030 assoc_list : none
3031 | assocs trailer
3033 $$ = $1;
3037 assocs : assoc
3039 $$ = list1($1);
3041 | assocs ',' assoc
3043 $$ = push($1, $3);
3047 assoc : arg_value tASSOC arg_value
3049 $$ = cons($1, $3);
3051 | tLABEL arg_value
3053 $$ = cons(new_sym(p, $1), $2);
3057 operation : tIDENTIFIER
3058 | tCONSTANT
3059 | tFID
3062 operation2 : tIDENTIFIER
3063 | tCONSTANT
3064 | tFID
3065 | op
3068 operation3 : tIDENTIFIER
3069 | tFID
3070 | op
3073 dot_or_colon : '.'
3074 | tCOLON2
3077 opt_terms : /* none */
3078 | terms
3081 opt_nl : /* none */
3082 | nl
3085 rparen : opt_nl ')'
3088 rbracket : opt_nl ']'
3091 trailer : /* none */
3092 | nl
3093 | ','
3096 term : ';' {yyerrok;}
3097 | nl
3100 nl : '\n'
3102 p->lineno++;
3103 p->column = 0;
3105 opt_heredoc_bodies
3107 terms : term
3108 | terms ';' {yyerrok;}
3111 none : /* none */
3113 $$ = 0;
3117 #define yylval (*((YYSTYPE*)(p->ylval)))
3119 static void
3120 yyerror(parser_state *p, const char *s)
3122 char* c;
3123 int n;
3125 if (! p->capture_errors) {
3126 #ifdef ENABLE_STDIO
3127 if (p->filename) {
3128 fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
3130 else {
3131 fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
3133 #endif
3135 else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) {
3136 n = strlen(s);
3137 c = (char *)parser_palloc(p, n + 1);
3138 memcpy(c, s, n + 1);
3139 p->error_buffer[p->nerr].message = c;
3140 p->error_buffer[p->nerr].lineno = p->lineno;
3141 p->error_buffer[p->nerr].column = p->column;
3143 p->nerr++;
3146 static void
3147 yyerror_i(parser_state *p, const char *fmt, int i)
3149 char buf[256];
3151 snprintf(buf, sizeof(buf), fmt, i);
3152 yyerror(p, buf);
3155 static void
3156 yywarn(parser_state *p, const char *s)
3158 char* c;
3159 int n;
3161 if (! p->capture_errors) {
3162 #ifdef ENABLE_STDIO
3163 if (p->filename) {
3164 fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
3166 else {
3167 fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
3169 #endif
3171 else if (p->nwarn < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) {
3172 n = strlen(s);
3173 c = (char *)parser_palloc(p, n + 1);
3174 memcpy(c, s, n + 1);
3175 p->warn_buffer[p->nwarn].message = c;
3176 p->warn_buffer[p->nwarn].lineno = p->lineno;
3177 p->warn_buffer[p->nwarn].column = p->column;
3179 p->nwarn++;
3182 static void
3183 yywarning(parser_state *p, const char *s)
3185 yywarn(p, s);
3188 static void
3189 yywarning_s(parser_state *p, const char *fmt, const char *s)
3191 char buf[256];
3193 snprintf(buf, sizeof(buf), fmt, s);
3194 yywarning(p, buf);
3197 static void
3198 backref_error(parser_state *p, node *n)
3200 int c;
3202 c = (int)(intptr_t)n->car;
3204 if (c == NODE_NTH_REF) {
3205 yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr);
3206 } else if (c == NODE_BACK_REF) {
3207 yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
3208 } else {
3209 mrb_bug("Internal error in backref_error() : n=>car == %d", c);
3213 static int peeks(parser_state *p, const char *s);
3214 static int skips(parser_state *p, const char *s);
3216 static inline int
3217 nextc(parser_state *p)
3219 int c;
3221 if (p->pb) {
3222 node *tmp;
3224 c = (int)(intptr_t)p->pb->car;
3225 tmp = p->pb;
3226 p->pb = p->pb->cdr;
3227 cons_free(tmp);
3229 else {
3230 if (p->f) {
3231 if (feof(p->f)) return -1;
3232 c = fgetc(p->f);
3233 if (c == EOF) return -1;
3235 else if (!p->s || p->s >= p->send) {
3236 return -1;
3238 else {
3239 c = (unsigned char)*p->s++;
3242 p->column++;
3243 return c;
3246 static void
3247 pushback(parser_state *p, int c)
3249 if (c < 0) return;
3250 p->column--;
3251 p->pb = cons((node*)(intptr_t)c, p->pb);
3254 static void
3255 skip(parser_state *p, char term)
3257 int c;
3259 for (;;) {
3260 c = nextc(p);
3261 if (c < 0) break;
3262 if (c == term) break;
3266 static int
3267 peek_n(parser_state *p, int c, int n)
3269 node *list = 0;
3270 int c0;
3272 do {
3273 c0 = nextc(p);
3274 if (c0 < 0) return FALSE;
3275 list = push(list, (node*)(intptr_t)c0);
3276 } while(n--);
3277 if (p->pb) {
3278 p->pb = push(p->pb, (node*)list);
3280 else {
3281 p->pb = list;
3283 if (c0 == c) return TRUE;
3284 return FALSE;
3286 #define peek(p,c) peek_n((p), (c), 0)
3288 static int
3289 peeks(parser_state *p, const char *s)
3291 int len = strlen(s);
3293 if (p->f) {
3294 int n = 0;
3295 while (*s) {
3296 if (!peek_n(p, *s++, n++)) return FALSE;
3298 return TRUE;
3300 else if (p->s && p->s + len >= p->send) {
3301 if (memcmp(p->s, s, len) == 0) return TRUE;
3303 return FALSE;
3306 static int
3307 skips(parser_state *p, const char *s)
3309 int c;
3311 for (;;) {
3312 // skip until first char
3313 for (;;) {
3314 c = nextc(p);
3315 if (c < 0) return c;
3316 if (c == *s) break;
3318 s++;
3319 if (peeks(p, s)) {
3320 int len = strlen(s);
3322 while (len--) {
3323 nextc(p);
3325 return TRUE;
3327 else{
3328 s--;
3331 return FALSE;
3335 static int
3336 newtok(parser_state *p)
3338 p->bidx = 0;
3339 return p->column - 1;
3342 static void
3343 tokadd(parser_state *p, int c)
3345 if (p->bidx < MRB_PARSER_BUF_SIZE) {
3346 p->buf[p->bidx++] = c;
3350 static int
3351 toklast(parser_state *p)
3353 return p->buf[p->bidx-1];
3356 static void
3357 tokfix(parser_state *p)
3359 if (p->bidx >= MRB_PARSER_BUF_SIZE) {
3360 yyerror(p, "string too long (truncated)");
3362 p->buf[p->bidx] = '\0';
3365 static const char*
3366 tok(parser_state *p)
3368 return p->buf;
3371 static int
3372 toklen(parser_state *p)
3374 return p->bidx;
3377 #define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG)
3378 #define IS_END() (p->lstate == EXPR_END || p->lstate == EXPR_ENDARG || p->lstate == EXPR_ENDFN)
3379 #define IS_BEG() (p->lstate == EXPR_BEG || p->lstate == EXPR_MID || p->lstate == EXPR_VALUE || p->lstate == EXPR_CLASS)
3380 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
3381 #define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
3382 #define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
3384 static int
3385 scan_oct(const int *start, int len, int *retlen)
3387 const int *s = start;
3388 int retval = 0;
3390 /* assert(len <= 3) */
3391 while (len-- && *s >= '0' && *s <= '7') {
3392 retval <<= 3;
3393 retval |= *s++ - '0';
3395 *retlen = s - start;
3397 return retval;
3400 static int
3401 scan_hex(const int *start, int len, int *retlen)
3403 static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
3404 register const int *s = start;
3405 register int retval = 0;
3406 char *tmp;
3408 /* assert(len <= 2) */
3409 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
3410 retval <<= 4;
3411 retval |= (tmp - hexdigit) & 15;
3412 s++;
3414 *retlen = s - start;
3416 return retval;
3419 static int
3420 read_escape(parser_state *p)
3422 int c;
3424 switch (c = nextc(p)) {
3425 case '\\': /* Backslash */
3426 return c;
3428 case 'n': /* newline */
3429 return '\n';
3431 case 't': /* horizontal tab */
3432 return '\t';
3434 case 'r': /* carriage-return */
3435 return '\r';
3437 case 'f': /* form-feed */
3438 return '\f';
3440 case 'v': /* vertical tab */
3441 return '\13';
3443 case 'a': /* alarm(bell) */
3444 return '\007';
3446 case 'e': /* escape */
3447 return 033;
3449 case '0': case '1': case '2': case '3': /* octal constant */
3450 case '4': case '5': case '6': case '7':
3452 int buf[3];
3453 int i;
3455 buf[0] = c;
3456 for (i=1; i<3; i++) {
3457 buf[i] = nextc(p);
3458 if (buf[i] == -1) goto eof;
3459 if (buf[i] < '0' || '7' < buf[i]) {
3460 pushback(p, buf[i]);
3461 break;
3464 c = scan_oct(buf, i, &i);
3466 return c;
3468 case 'x': /* hex constant */
3470 int buf[2];
3471 int i;
3473 for (i=0; i<2; i++) {
3474 buf[i] = nextc(p);
3475 if (buf[i] == -1) goto eof;
3476 if (!isxdigit(buf[i])) {
3477 pushback(p, buf[i]);
3478 break;
3481 c = scan_hex(buf, i, &i);
3482 if (i == 0) {
3483 yyerror(p, "Invalid escape character syntax");
3484 return 0;
3487 return c;
3489 case 'b': /* backspace */
3490 return '\010';
3492 case 's': /* space */
3493 return ' ';
3495 case 'M':
3496 if ((c = nextc(p)) != '-') {
3497 yyerror(p, "Invalid escape character syntax");
3498 pushback(p, c);
3499 return '\0';
3501 if ((c = nextc(p)) == '\\') {
3502 return read_escape(p) | 0x80;
3504 else if (c == -1) goto eof;
3505 else {
3506 return ((c & 0xff) | 0x80);
3509 case 'C':
3510 if ((c = nextc(p)) != '-') {
3511 yyerror(p, "Invalid escape character syntax");
3512 pushback(p, c);
3513 return '\0';
3515 case 'c':
3516 if ((c = nextc(p))== '\\') {
3517 c = read_escape(p);
3519 else if (c == '?')
3520 return 0177;
3521 else if (c == -1) goto eof;
3522 return c & 0x9f;
3524 eof:
3525 case -1:
3526 yyerror(p, "Invalid escape character syntax");
3527 return '\0';
3529 default:
3530 return c;
3535 static int
3536 parse_string(parser_state *p)
3538 int c;
3539 string_type type = (string_type)(intptr_t)p->lex_strterm->car;
3540 int nest_level = (intptr_t)p->lex_strterm->cdr->car;
3541 int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
3542 int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
3543 parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
3545 newtok(p);
3546 while ((c = nextc(p)) != end || nest_level != 0) {
3547 if (hinf && (c == '\n' || c == -1)) {
3548 int line_head;
3549 tokadd(p, '\n');
3550 tokfix(p);
3551 p->lineno++;
3552 p->column = 0;
3553 line_head = hinf->line_head;
3554 hinf->line_head = TRUE;
3555 if (line_head) {
3556 /* check whether end of heredoc */
3557 const char *s = tok(p);
3558 int len = toklen(p);
3559 if (hinf->allow_indent) {
3560 while (ISSPACE(*s) && len > 0) {
3561 ++s;
3562 --len;
3565 if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
3566 return tHEREDOC_END;
3569 if (c == -1) {
3570 char buf[256];
3571 snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term);
3572 yyerror(p, buf);
3573 return 0;
3575 yylval.nd = new_str(p, tok(p), toklen(p));
3576 return tSTRING_MID;
3578 if (c == -1) {
3579 yyerror(p, "unterminated string meets end of file");
3580 return 0;
3582 else if (c == beg) {
3583 nest_level++;
3584 p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
3586 else if (c == end) {
3587 nest_level--;
3588 p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
3590 else if (c == '\\') {
3591 c = nextc(p);
3592 if (type & STR_FUNC_EXPAND) {
3593 if (c == end || c == beg) {
3594 tokadd(p, c);
3596 else if ((c == '\n') && (type & STR_FUNC_ARRAY)) {
3597 p->lineno++;
3598 p->column = 0;
3599 tokadd(p, '\n');
3601 else {
3602 pushback(p, c);
3604 if(type & STR_FUNC_REGEXP)
3605 tokadd(p, '\\');
3607 tokadd(p, read_escape(p));
3608 if (hinf)
3609 hinf->line_head = FALSE;
3611 } else {
3612 if (c != beg && c != end) {
3613 switch (c) {
3614 case '\n':
3615 p->lineno++;
3616 p->column = 0;
3617 break;
3619 case '\\':
3620 break;
3622 default:
3623 if (! ISSPACE(c))
3624 tokadd(p, '\\');
3627 tokadd(p, c);
3629 continue;
3631 else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
3632 c = nextc(p);
3633 if (c == '{') {
3634 tokfix(p);
3635 p->lstate = EXPR_BEG;
3636 p->cmd_start = TRUE;
3637 yylval.nd = new_str(p, tok(p), toklen(p));
3638 if (hinf)
3639 hinf->line_head = FALSE;
3640 return tSTRING_PART;
3642 tokadd(p, '#');
3643 pushback(p, c);
3644 continue;
3646 if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
3647 if (toklen(p) == 0) {
3648 do {
3649 if (c == '\n') {
3650 p->lineno++;
3651 p->column = 0;
3653 } while (ISSPACE(c = nextc(p)));
3654 pushback(p, c);
3655 return tLITERAL_DELIM;
3656 } else {
3657 pushback(p, c);
3658 tokfix(p);
3659 yylval.nd = new_str(p, tok(p), toklen(p));
3660 return tSTRING_MID;
3664 tokadd(p, c);
3668 tokfix(p);
3669 p->lstate = EXPR_END;
3670 end_strterm(p);
3672 if (type & STR_FUNC_XQUOTE) {
3673 yylval.nd = new_xstr(p, tok(p), toklen(p));
3674 return tXSTRING;
3677 if (type & STR_FUNC_REGEXP) {
3678 int f = 0;
3679 int c;
3680 char *s = strndup(tok(p), toklen(p));
3681 char flag[4] = { '\0' };
3683 newtok(p);
3684 while (c = nextc(p), ISALPHA(c)) {
3685 switch (c) {
3686 case 'i': f |= 1; break;
3687 case 'x': f |= 2; break;
3688 case 'm': f |= 4; break;
3689 default: tokadd(p, c); break;
3692 pushback(p, c);
3693 if (toklen(p)) {
3694 char msg[128];
3695 tokfix(p);
3696 snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
3697 toklen(p) > 1 ? "s" : "", tok(p));
3698 yyerror(p, msg);
3700 if (f & 1) strcat(flag, "i");
3701 if (f & 2) strcat(flag, "x");
3702 if (f & 4) strcat(flag, "m");
3703 yylval.nd = new_regx(p, s, strdup(flag));
3705 return tREGEXP;
3708 yylval.nd = new_str(p, tok(p), toklen(p));
3709 return tSTRING;
3713 static int
3714 heredoc_identifier(parser_state *p)
3716 int c;
3717 int type = str_heredoc;
3718 int indent = FALSE;
3719 int quote = FALSE;
3720 node *newnode;
3721 parser_heredoc_info *info;
3723 c = nextc(p);
3724 if (ISSPACE(c) || c == '=') {
3725 pushback(p, c);
3726 return 0;
3728 if (c == '-') {
3729 indent = TRUE;
3730 c = nextc(p);
3732 if (c == '\'' || c == '"') {
3733 int term = c;
3734 if (c == '\'')
3735 quote = TRUE;
3736 newtok(p);
3737 while ((c = nextc(p)) != -1 && c != term) {
3738 if (c == '\n') {
3739 c = -1;
3740 break;
3742 tokadd(p, c);
3744 if (c == -1) {
3745 yyerror(p, "unterminated here document identifier");
3746 return 0;
3748 } else {
3749 if (! identchar(c)) {
3750 pushback(p, c);
3751 if (indent) pushback(p, '-');
3752 return 0;
3754 newtok(p);
3755 do {
3756 tokadd(p, c);
3757 } while ((c = nextc(p)) != -1 && identchar(c));
3758 pushback(p, c);
3760 tokfix(p);
3761 newnode = new_heredoc(p);
3762 info = (parser_heredoc_info*)newnode->cdr;
3763 info->term = strndup(tok(p), toklen(p));
3764 info->term_len = toklen(p);
3765 if (! quote)
3766 type |= STR_FUNC_EXPAND;
3767 info->type = type;
3768 info->allow_indent = indent;
3769 info->line_head = TRUE;
3770 info->doc = NULL;
3771 p->heredocs = push(p->heredocs, newnode);
3772 if (p->parsing_heredoc == NULL) {
3773 node *n = p->heredocs;
3774 while (n->cdr)
3775 n = n->cdr;
3776 p->parsing_heredoc = n;
3778 p->heredoc_starts_nextline = TRUE;
3779 p->lstate = EXPR_END;
3781 yylval.nd = newnode;
3782 return tHEREDOC_BEG;
3785 static int
3786 arg_ambiguous(parser_state *p)
3788 yywarning(p, "ambiguous first argument; put parentheses or even spaces");
3789 return 1;
3792 #include "lex.def"
3794 static int
3795 parser_yylex(parser_state *p)
3797 register int c;
3798 int space_seen = 0;
3799 int cmd_state;
3800 enum mrb_lex_state_enum last_state;
3801 int token_column;
3803 if (p->lex_strterm) {
3804 if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
3805 if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline))
3806 return parse_string(p);
3808 else
3809 return parse_string(p);
3811 cmd_state = p->cmd_start;
3812 p->cmd_start = FALSE;
3813 retry:
3814 last_state = p->lstate;
3815 switch (c = nextc(p)) {
3816 case '\0': /* NUL */
3817 case '\004': /* ^D */
3818 case '\032': /* ^Z */
3819 case -1: /* end of script. */
3820 return 0;
3822 /* white spaces */
3823 case ' ': case '\t': case '\f': case '\r':
3824 case '\13': /* '\v' */
3825 space_seen = 1;
3826 goto retry;
3828 case '#': /* it's a comment */
3829 skip(p, '\n');
3830 /* fall through */
3831 case '\n':
3832 p->heredoc_starts_nextline = FALSE;
3833 if (p->parsing_heredoc != NULL) {
3834 p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
3835 goto normal_newline;
3837 switch (p->lstate) {
3838 case EXPR_BEG:
3839 case EXPR_FNAME:
3840 case EXPR_DOT:
3841 case EXPR_CLASS:
3842 case EXPR_VALUE:
3843 p->lineno++;
3844 p->column = 0;
3845 goto retry;
3846 default:
3847 break;
3849 while ((c = nextc(p))) {
3850 switch (c) {
3851 case ' ': case '\t': case '\f': case '\r':
3852 case '\13': /* '\v' */
3853 space_seen = 1;
3854 break;
3855 case '.':
3856 if ((c = nextc(p)) != '.') {
3857 pushback(p, c);
3858 pushback(p, '.');
3859 goto retry;
3861 case -1: /* EOF */
3862 goto normal_newline;
3863 default:
3864 pushback(p, c);
3865 goto normal_newline;
3868 normal_newline:
3869 p->cmd_start = TRUE;
3870 p->lstate = EXPR_BEG;
3871 return '\n';
3873 case '*':
3874 if ((c = nextc(p)) == '*') {
3875 if ((c = nextc(p)) == '=') {
3876 yylval.id = intern("**");
3877 p->lstate = EXPR_BEG;
3878 return tOP_ASGN;
3880 pushback(p, c);
3881 c = tPOW;
3883 else {
3884 if (c == '=') {
3885 yylval.id = intern("*");
3886 p->lstate = EXPR_BEG;
3887 return tOP_ASGN;
3889 pushback(p, c);
3890 if (IS_SPCARG(c)) {
3891 yywarning(p, "`*' interpreted as argument prefix");
3892 c = tSTAR;
3894 else if (IS_BEG()) {
3895 c = tSTAR;
3897 else {
3898 c = '*';
3901 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3902 p->lstate = EXPR_ARG;
3903 } else {
3904 p->lstate = EXPR_BEG;
3906 return c;
3908 case '!':
3909 c = nextc(p);
3910 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3911 p->lstate = EXPR_ARG;
3912 if (c == '@') {
3913 return '!';
3916 else {
3917 p->lstate = EXPR_BEG;
3919 if (c == '=') {
3920 return tNEQ;
3922 if (c == '~') {
3923 return tNMATCH;
3925 pushback(p, c);
3926 return '!';
3928 case '=':
3929 if (p->column == 1) {
3930 if (peeks(p, "begin\n")) {
3931 skips(p, "\n=end\n");
3932 goto retry;
3935 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3936 p->lstate = EXPR_ARG;
3937 } else {
3938 p->lstate = EXPR_BEG;
3940 if ((c = nextc(p)) == '=') {
3941 if ((c = nextc(p)) == '=') {
3942 return tEQQ;
3944 pushback(p, c);
3945 return tEQ;
3947 if (c == '~') {
3948 return tMATCH;
3950 else if (c == '>') {
3951 return tASSOC;
3953 pushback(p, c);
3954 return '=';
3956 case '<':
3957 last_state = p->lstate;
3958 c = nextc(p);
3959 if (c == '<' &&
3960 p->lstate != EXPR_DOT &&
3961 p->lstate != EXPR_CLASS &&
3962 !IS_END() &&
3963 (!IS_ARG() || space_seen)) {
3964 int token = heredoc_identifier(p);
3965 if (token)
3966 return token;
3968 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3969 p->lstate = EXPR_ARG;
3970 } else {
3971 p->lstate = EXPR_BEG;
3972 if (p->lstate == EXPR_CLASS) {
3973 p->cmd_start = TRUE;
3976 if (c == '=') {
3977 if ((c = nextc(p)) == '>') {
3978 return tCMP;
3980 pushback(p, c);
3981 return tLEQ;
3983 if (c == '<') {
3984 if ((c = nextc(p)) == '=') {
3985 yylval.id = intern("<<");
3986 p->lstate = EXPR_BEG;
3987 return tOP_ASGN;
3989 pushback(p, c);
3990 return tLSHFT;
3992 pushback(p, c);
3993 return '<';
3995 case '>':
3996 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
3997 p->lstate = EXPR_ARG;
3998 } else {
3999 p->lstate = EXPR_BEG;
4001 if ((c = nextc(p)) == '=') {
4002 return tGEQ;
4004 if (c == '>') {
4005 if ((c = nextc(p)) == '=') {
4006 yylval.id = intern(">>");
4007 p->lstate = EXPR_BEG;
4008 return tOP_ASGN;
4010 pushback(p, c);
4011 return tRSHFT;
4013 pushback(p, c);
4014 return '>';
4016 case '"':
4017 p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
4018 return tSTRING_BEG;
4020 case '\'':
4021 p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
4022 return parse_string(p);
4024 case '`':
4025 if (p->lstate == EXPR_FNAME) {
4026 p->lstate = EXPR_ENDFN;
4027 return '`';
4029 if (p->lstate == EXPR_DOT) {
4030 if (cmd_state)
4031 p->lstate = EXPR_CMDARG;
4032 else
4033 p->lstate = EXPR_ARG;
4034 return '`';
4036 p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
4037 return tXSTRING_BEG;
4039 case '?':
4040 if (IS_END()) {
4041 p->lstate = EXPR_VALUE;
4042 return '?';
4044 c = nextc(p);
4045 if (c == -1) {
4046 yyerror(p, "incomplete character syntax");
4047 return 0;
4049 if (isspace(c)) {
4050 if (!IS_ARG()) {
4051 int c2;
4052 switch (c) {
4053 case ' ':
4054 c2 = 's';
4055 break;
4056 case '\n':
4057 c2 = 'n';
4058 break;
4059 case '\t':
4060 c2 = 't';
4061 break;
4062 case '\v':
4063 c2 = 'v';
4064 break;
4065 case '\r':
4066 c2 = 'r';
4067 break;
4068 case '\f':
4069 c2 = 'f';
4070 break;
4071 default:
4072 c2 = 0;
4073 break;
4075 if (c2) {
4076 char buf[256];
4077 snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
4078 yyerror(p, buf);
4081 ternary:
4082 pushback(p, c);
4083 p->lstate = EXPR_VALUE;
4084 return '?';
4086 token_column = newtok(p);
4087 // need support UTF-8 if configured
4088 if ((isalnum(c) || c == '_')) {
4089 int c2 = nextc(p);
4090 pushback(p, c2);
4091 if ((isalnum(c2) || c2 == '_')) {
4092 goto ternary;
4095 if (c == '\\') {
4096 c = nextc(p);
4097 if (c == 'u') {
4098 #if 0
4099 tokadd_utf8(p);
4100 #endif
4102 else {
4103 pushback(p, c);
4104 c = read_escape(p);
4105 tokadd(p, c);
4108 else {
4109 tokadd(p, c);
4111 tokfix(p);
4112 yylval.nd = new_str(p, tok(p), toklen(p));
4113 p->lstate = EXPR_END;
4114 return tCHAR;
4116 case '&':
4117 if ((c = nextc(p)) == '&') {
4118 p->lstate = EXPR_BEG;
4119 if ((c = nextc(p)) == '=') {
4120 yylval.id = intern("&&");
4121 p->lstate = EXPR_BEG;
4122 return tOP_ASGN;
4124 pushback(p, c);
4125 return tANDOP;
4127 else if (c == '=') {
4128 yylval.id = intern("&");
4129 p->lstate = EXPR_BEG;
4130 return tOP_ASGN;
4132 pushback(p, c);
4133 if (IS_SPCARG(c)) {
4134 yywarning(p, "`&' interpreted as argument prefix");
4135 c = tAMPER;
4137 else if (IS_BEG()) {
4138 c = tAMPER;
4140 else {
4141 c = '&';
4143 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4144 p->lstate = EXPR_ARG;
4145 } else {
4146 p->lstate = EXPR_BEG;
4148 return c;
4150 case '|':
4151 if ((c = nextc(p)) == '|') {
4152 p->lstate = EXPR_BEG;
4153 if ((c = nextc(p)) == '=') {
4154 yylval.id = intern("||");
4155 p->lstate = EXPR_BEG;
4156 return tOP_ASGN;
4158 pushback(p, c);
4159 return tOROP;
4161 if (c == '=') {
4162 yylval.id = intern("|");
4163 p->lstate = EXPR_BEG;
4164 return tOP_ASGN;
4166 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4167 p->lstate = EXPR_ARG;
4169 else {
4170 p->lstate = EXPR_BEG;
4172 pushback(p, c);
4173 return '|';
4175 case '+':
4176 c = nextc(p);
4177 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4178 p->lstate = EXPR_ARG;
4179 if (c == '@') {
4180 return tUPLUS;
4182 pushback(p, c);
4183 return '+';
4185 if (c == '=') {
4186 yylval.id = intern("+");
4187 p->lstate = EXPR_BEG;
4188 return tOP_ASGN;
4190 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
4191 p->lstate = EXPR_BEG;
4192 pushback(p, c);
4193 if (c != -1 && ISDIGIT(c)) {
4194 c = '+';
4195 goto start_num;
4197 return tUPLUS;
4199 p->lstate = EXPR_BEG;
4200 pushback(p, c);
4201 return '+';
4203 case '-':
4204 c = nextc(p);
4205 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4206 p->lstate = EXPR_ARG;
4207 if (c == '@') {
4208 return tUMINUS;
4210 pushback(p, c);
4211 return '-';
4213 if (c == '=') {
4214 yylval.id = intern("-");
4215 p->lstate = EXPR_BEG;
4216 return tOP_ASGN;
4218 if (c == '>') {
4219 p->lstate = EXPR_ENDFN;
4220 return tLAMBDA;
4222 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
4223 p->lstate = EXPR_BEG;
4224 pushback(p, c);
4225 if (c != -1 && ISDIGIT(c)) {
4226 return tUMINUS_NUM;
4228 return tUMINUS;
4230 p->lstate = EXPR_BEG;
4231 pushback(p, c);
4232 return '-';
4234 case '.':
4235 p->lstate = EXPR_BEG;
4236 if ((c = nextc(p)) == '.') {
4237 if ((c = nextc(p)) == '.') {
4238 return tDOT3;
4240 pushback(p, c);
4241 return tDOT2;
4243 pushback(p, c);
4244 if (c != -1 && ISDIGIT(c)) {
4245 yyerror(p, "no .<digit> floating literal anymore; put 0 before dot");
4247 p->lstate = EXPR_DOT;
4248 return '.';
4250 start_num:
4251 case '0': case '1': case '2': case '3': case '4':
4252 case '5': case '6': case '7': case '8': case '9':
4254 int is_float, seen_point, seen_e, nondigit;
4256 is_float = seen_point = seen_e = nondigit = 0;
4257 p->lstate = EXPR_END;
4258 token_column = newtok(p);
4259 if (c == '-' || c == '+') {
4260 tokadd(p, c);
4261 c = nextc(p);
4263 if (c == '0') {
4264 #define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0)
4265 int start = toklen(p);
4266 c = nextc(p);
4267 if (c == 'x' || c == 'X') {
4268 /* hexadecimal */
4269 c = nextc(p);
4270 if (c != -1 && ISXDIGIT(c)) {
4271 do {
4272 if (c == '_') {
4273 if (nondigit) break;
4274 nondigit = c;
4275 continue;
4277 if (!ISXDIGIT(c)) break;
4278 nondigit = 0;
4279 tokadd(p, tolower(c));
4280 } while ((c = nextc(p)) != -1);
4282 pushback(p, c);
4283 tokfix(p);
4284 if (toklen(p) == start) {
4285 no_digits();
4287 else if (nondigit) goto trailing_uc;
4288 yylval.nd = new_int(p, tok(p), 16);
4289 return tINTEGER;
4291 if (c == 'b' || c == 'B') {
4292 /* binary */
4293 c = nextc(p);
4294 if (c == '0' || c == '1') {
4295 do {
4296 if (c == '_') {
4297 if (nondigit) break;
4298 nondigit = c;
4299 continue;
4301 if (c != '0' && c != '1') break;
4302 nondigit = 0;
4303 tokadd(p, c);
4304 } while ((c = nextc(p)) != -1);
4306 pushback(p, c);
4307 tokfix(p);
4308 if (toklen(p) == start) {
4309 no_digits();
4311 else if (nondigit) goto trailing_uc;
4312 yylval.nd = new_int(p, tok(p), 2);
4313 return tINTEGER;
4315 if (c == 'd' || c == 'D') {
4316 /* decimal */
4317 c = nextc(p);
4318 if (c != -1 && ISDIGIT(c)) {
4319 do {
4320 if (c == '_') {
4321 if (nondigit) break;
4322 nondigit = c;
4323 continue;
4325 if (!ISDIGIT(c)) break;
4326 nondigit = 0;
4327 tokadd(p, c);
4328 } while ((c = nextc(p)) != -1);
4330 pushback(p, c);
4331 tokfix(p);
4332 if (toklen(p) == start) {
4333 no_digits();
4335 else if (nondigit) goto trailing_uc;
4336 yylval.nd = new_int(p, tok(p), 10);
4337 return tINTEGER;
4339 if (c == '_') {
4340 /* 0_0 */
4341 goto octal_number;
4343 if (c == 'o' || c == 'O') {
4344 /* prefixed octal */
4345 c = nextc(p);
4346 if (c == -1 || c == '_' || !ISDIGIT(c)) {
4347 no_digits();
4350 if (c >= '0' && c <= '7') {
4351 /* octal */
4352 octal_number:
4353 do {
4354 if (c == '_') {
4355 if (nondigit) break;
4356 nondigit = c;
4357 continue;
4359 if (c < '0' || c > '9') break;
4360 if (c > '7') goto invalid_octal;
4361 nondigit = 0;
4362 tokadd(p, c);
4363 } while ((c = nextc(p)) != -1);
4365 if (toklen(p) > start) {
4366 pushback(p, c);
4367 tokfix(p);
4368 if (nondigit) goto trailing_uc;
4369 yylval.nd = new_int(p, tok(p), 8);
4370 return tINTEGER;
4372 if (nondigit) {
4373 pushback(p, c);
4374 goto trailing_uc;
4377 if (c > '7' && c <= '9') {
4378 invalid_octal:
4379 yyerror(p, "Invalid octal digit");
4381 else if (c == '.' || c == 'e' || c == 'E') {
4382 tokadd(p, '0');
4384 else {
4385 pushback(p, c);
4386 yylval.nd = new_int(p, "0", 10);
4387 return tINTEGER;
4391 for (;;) {
4392 switch (c) {
4393 case '0': case '1': case '2': case '3': case '4':
4394 case '5': case '6': case '7': case '8': case '9':
4395 nondigit = 0;
4396 tokadd(p, c);
4397 break;
4399 case '.':
4400 if (nondigit) goto trailing_uc;
4401 if (seen_point || seen_e) {
4402 goto decode_num;
4404 else {
4405 int c0 = nextc(p);
4406 if (c0 == -1 || !ISDIGIT(c0)) {
4407 pushback(p, c0);
4408 goto decode_num;
4410 c = c0;
4412 tokadd(p, '.');
4413 tokadd(p, c);
4414 is_float++;
4415 seen_point++;
4416 nondigit = 0;
4417 break;
4419 case 'e':
4420 case 'E':
4421 if (nondigit) {
4422 pushback(p, c);
4423 c = nondigit;
4424 goto decode_num;
4426 if (seen_e) {
4427 goto decode_num;
4429 tokadd(p, c);
4430 seen_e++;
4431 is_float++;
4432 nondigit = c;
4433 c = nextc(p);
4434 if (c != '-' && c != '+') continue;
4435 tokadd(p, c);
4436 nondigit = c;
4437 break;
4439 case '_': /* `_' in number just ignored */
4440 if (nondigit) goto decode_num;
4441 nondigit = c;
4442 break;
4444 default:
4445 goto decode_num;
4447 c = nextc(p);
4450 decode_num:
4451 pushback(p, c);
4452 if (nondigit) {
4453 trailing_uc:
4454 yyerror_i(p, "trailing `%c' in number", nondigit);
4456 tokfix(p);
4457 if (is_float) {
4458 double d;
4459 char *endp;
4461 errno = 0;
4462 d = strtod(tok(p), &endp);
4463 if (d == 0 && endp == tok(p)) {
4464 yywarning_s(p, "corrupted float value %s", tok(p));
4466 else if (errno == ERANGE) {
4467 yywarning_s(p, "float %s out of range", tok(p));
4468 errno = 0;
4470 yylval.nd = new_float(p, tok(p));
4471 return tFLOAT;
4473 yylval.nd = new_int(p, tok(p), 10);
4474 return tINTEGER;
4477 case ')':
4478 case ']':
4479 p->paren_nest--;
4480 case '}':
4481 COND_LEXPOP();
4482 CMDARG_LEXPOP();
4483 if (c == ')')
4484 p->lstate = EXPR_ENDFN;
4485 else
4486 p->lstate = EXPR_ENDARG;
4487 return c;
4489 case ':':
4490 c = nextc(p);
4491 if (c == ':') {
4492 if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) {
4493 p->lstate = EXPR_BEG;
4494 return tCOLON3;
4496 p->lstate = EXPR_DOT;
4497 return tCOLON2;
4499 if (IS_END() || ISSPACE(c)) {
4500 pushback(p, c);
4501 p->lstate = EXPR_BEG;
4502 return ':';
4504 pushback(p, c);
4505 p->lstate = EXPR_FNAME;
4506 return tSYMBEG;
4508 case '/':
4509 if (IS_BEG()) {
4510 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
4511 return tREGEXP_BEG;
4513 if ((c = nextc(p)) == '=') {
4514 yylval.id = intern("/");
4515 p->lstate = EXPR_BEG;
4516 return tOP_ASGN;
4518 pushback(p, c);
4519 if (IS_SPCARG(c)) {
4520 p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
4521 return tREGEXP_BEG;
4523 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4524 p->lstate = EXPR_ARG;
4525 } else {
4526 p->lstate = EXPR_BEG;
4528 return '/';
4530 case '^':
4531 if ((c = nextc(p)) == '=') {
4532 yylval.id = intern("^");
4533 p->lstate = EXPR_BEG;
4534 return tOP_ASGN;
4536 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4537 p->lstate = EXPR_ARG;
4538 } else {
4539 p->lstate = EXPR_BEG;
4541 pushback(p, c);
4542 return '^';
4544 case ';':
4545 p->lstate = EXPR_BEG;
4546 return ';';
4548 case ',':
4549 p->lstate = EXPR_BEG;
4550 return ',';
4552 case '~':
4553 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4554 if ((c = nextc(p)) != '@') {
4555 pushback(p, c);
4557 p->lstate = EXPR_ARG;
4559 else {
4560 p->lstate = EXPR_BEG;
4562 return '~';
4564 case '(':
4565 if (IS_BEG()) {
4566 c = tLPAREN;
4568 else if (IS_SPCARG(-1)) {
4569 c = tLPAREN_ARG;
4571 p->paren_nest++;
4572 COND_PUSH(0);
4573 CMDARG_PUSH(0);
4574 p->lstate = EXPR_BEG;
4575 return c;
4577 case '[':
4578 p->paren_nest++;
4579 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4580 p->lstate = EXPR_ARG;
4581 if ((c = nextc(p)) == ']') {
4582 if ((c = nextc(p)) == '=') {
4583 return tASET;
4585 pushback(p, c);
4586 return tAREF;
4588 pushback(p, c);
4589 return '[';
4591 else if (IS_BEG()) {
4592 c = tLBRACK;
4594 else if (IS_ARG() && space_seen) {
4595 c = tLBRACK;
4597 p->lstate = EXPR_BEG;
4598 COND_PUSH(0);
4599 CMDARG_PUSH(0);
4600 return c;
4602 case '{':
4603 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
4604 p->lstate = EXPR_BEG;
4605 p->lpar_beg = 0;
4606 p->paren_nest--;
4607 COND_PUSH(0);
4608 CMDARG_PUSH(0);
4609 return tLAMBEG;
4611 if (IS_ARG() || p->lstate == EXPR_END || p->lstate == EXPR_ENDFN)
4612 c = '{'; /* block (primary) */
4613 else if (p->lstate == EXPR_ENDARG)
4614 c = tLBRACE_ARG; /* block (expr) */
4615 else
4616 c = tLBRACE; /* hash */
4617 COND_PUSH(0);
4618 CMDARG_PUSH(0);
4619 p->lstate = EXPR_BEG;
4620 return c;
4622 case '\\':
4623 c = nextc(p);
4624 if (c == '\n') {
4625 p->lineno++;
4626 p->column = 0;
4627 space_seen = 1;
4628 goto retry; /* skip \\n */
4630 pushback(p, c);
4631 return '\\';
4633 case '%':
4634 if (IS_BEG()) {
4635 int term;
4636 int paren;
4638 c = nextc(p);
4639 quotation:
4640 if (c == -1 || !ISALNUM(c)) {
4641 term = c;
4642 c = 'Q';
4644 else {
4645 term = nextc(p);
4646 if (isalnum(term)) {
4647 yyerror(p, "unknown type of %string");
4648 return 0;
4651 if (c == -1 || term == -1) {
4652 yyerror(p, "unterminated quoted string meets end of file");
4653 return 0;
4655 paren = term;
4656 if (term == '(') term = ')';
4657 else if (term == '[') term = ']';
4658 else if (term == '{') term = '}';
4659 else if (term == '<') term = '>';
4660 else paren = 0;
4662 switch (c) {
4663 case 'Q':
4664 p->lex_strterm = new_strterm(p, str_dquote, term, paren);
4665 return tSTRING_BEG;
4667 case 'q':
4668 p->lex_strterm = new_strterm(p, str_squote, term, paren);
4669 return parse_string(p);
4671 case 'W':
4672 p->lex_strterm = new_strterm(p, str_dword, term, paren);
4673 return tWORDS_BEG;
4675 case 'w':
4676 p->lex_strterm = new_strterm(p, str_sword, term, paren);
4677 return tWORDS_BEG;
4679 case 'x':
4680 p->lex_strterm = new_strterm(p, str_xquote, term, paren);
4681 return tXSTRING_BEG;
4683 case 'r':
4684 p->lex_strterm = new_strterm(p, str_regexp, term, paren);
4685 return tREGEXP_BEG;
4687 case 's':
4688 p->lex_strterm = new_strterm(p, str_ssym, term, paren);
4689 return tSYMBEG;
4691 case 'I':
4692 p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
4693 return tSYMBOLS_BEG;
4695 case 'i':
4696 p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
4697 return tSYMBOLS_BEG;
4699 default:
4700 yyerror(p, "unknown type of %string");
4701 return 0;
4704 if ((c = nextc(p)) == '=') {
4705 yylval.id = intern("%");
4706 p->lstate = EXPR_BEG;
4707 return tOP_ASGN;
4709 if (IS_SPCARG(c)) {
4710 goto quotation;
4712 if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
4713 p->lstate = EXPR_ARG;
4714 } else {
4715 p->lstate = EXPR_BEG;
4717 pushback(p, c);
4718 return '%';
4720 case '$':
4721 p->lstate = EXPR_END;
4722 token_column = newtok(p);
4723 c = nextc(p);
4724 switch (c) {
4725 case '_': /* $_: last read line string */
4726 c = nextc(p);
4727 pushback(p, c);
4728 c = '_';
4729 /* fall through */
4730 case '~': /* $~: match-data */
4731 case '*': /* $*: argv */
4732 case '$': /* $$: pid */
4733 case '?': /* $?: last status */
4734 case '!': /* $!: error string */
4735 case '@': /* $@: error position */
4736 case '/': /* $/: input record separator */
4737 case '\\': /* $\: output record separator */
4738 case ';': /* $;: field separator */
4739 case ',': /* $,: output field separator */
4740 case '.': /* $.: last read line number */
4741 case '=': /* $=: ignorecase */
4742 case ':': /* $:: load path */
4743 case '<': /* $<: reading filename */
4744 case '>': /* $>: default output handle */
4745 case '\"': /* $": already loaded files */
4746 tokadd(p, '$');
4747 tokadd(p, c);
4748 tokfix(p);
4749 yylval.id = intern(tok(p));
4750 return tGVAR;
4752 case '-':
4753 tokadd(p, '$');
4754 tokadd(p, c);
4755 c = nextc(p);
4756 pushback(p, c);
4757 gvar:
4758 tokfix(p);
4759 yylval.id = intern(tok(p));
4760 return tGVAR;
4762 case '&': /* $&: last match */
4763 case '`': /* $`: string before last match */
4764 case '\'': /* $': string after last match */
4765 case '+': /* $+: string matches last pattern */
4766 if (last_state == EXPR_FNAME) {
4767 tokadd(p, '$');
4768 tokadd(p, c);
4769 goto gvar;
4771 yylval.nd = new_back_ref(p, c);
4772 return tBACK_REF;
4774 case '1': case '2': case '3':
4775 case '4': case '5': case '6':
4776 case '7': case '8': case '9':
4777 do {
4778 tokadd(p, c);
4779 c = nextc(p);
4780 } while (c != -1 && isdigit(c));
4781 pushback(p, c);
4782 if (last_state == EXPR_FNAME) goto gvar;
4783 tokfix(p);
4784 yylval.nd = new_nth_ref(p, atoi(tok(p)));
4785 return tNTH_REF;
4787 default:
4788 if (!identchar(c)) {
4789 pushback(p, c);
4790 return '$';
4792 case '0':
4793 tokadd(p, '$');
4795 break;
4797 case '@':
4798 c = nextc(p);
4799 token_column = newtok(p);
4800 tokadd(p, '@');
4801 if (c == '@') {
4802 tokadd(p, '@');
4803 c = nextc(p);
4805 if (c != -1 && isdigit(c)) {
4806 if (p->bidx == 1) {
4807 yyerror_i(p, "`@%c' is not allowed as an instance variable name", c);
4809 else {
4810 yyerror_i(p, "`@@%c' is not allowed as a class variable name", c);
4812 return 0;
4814 if (!identchar(c)) {
4815 pushback(p, c);
4816 return '@';
4818 break;
4820 case '_':
4821 token_column = newtok(p);
4822 break;
4824 default:
4825 if (!identchar(c)) {
4826 yyerror_i(p, "Invalid char `\\x%02X' in expression", c);
4827 goto retry;
4830 token_column = newtok(p);
4831 break;
4834 do {
4835 tokadd(p, c);
4836 c = nextc(p);
4837 if (c < 0) break;
4838 } while (identchar(c));
4839 if (token_column == 0 && toklen(p) == 7 && (c < 0 || c == '\n') &&
4840 strncmp(tok(p), "__END__", toklen(p)) == 0)
4841 return -1;
4843 switch (tok(p)[0]) {
4844 case '@': case '$':
4845 pushback(p, c);
4846 break;
4847 default:
4848 if ((c == '!' || c == '?') && !peek(p, '=')) {
4849 tokadd(p, c);
4851 else {
4852 pushback(p, c);
4855 tokfix(p);
4857 int result = 0;
4859 last_state = p->lstate;
4860 switch (tok(p)[0]) {
4861 case '$':
4862 p->lstate = EXPR_END;
4863 result = tGVAR;
4864 break;
4865 case '@':
4866 p->lstate = EXPR_END;
4867 if (tok(p)[1] == '@')
4868 result = tCVAR;
4869 else
4870 result = tIVAR;
4871 break;
4873 default:
4874 if (toklast(p) == '!' || toklast(p) == '?') {
4875 result = tFID;
4877 else {
4878 if (p->lstate == EXPR_FNAME) {
4879 if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
4880 (!peek(p, '=') || (peek_n(p, '>', 1)))) {
4881 result = tIDENTIFIER;
4882 tokadd(p, c);
4883 tokfix(p);
4885 else {
4886 pushback(p, c);
4889 if (result == 0 && isupper((int)tok(p)[0])) {
4890 result = tCONSTANT;
4892 else {
4893 result = tIDENTIFIER;
4897 if (IS_LABEL_POSSIBLE()) {
4898 if (IS_LABEL_SUFFIX(0)) {
4899 p->lstate = EXPR_BEG;
4900 nextc(p);
4901 tokfix(p);
4902 yylval.id = intern(tok(p));
4903 return tLABEL;
4906 if (p->lstate != EXPR_DOT) {
4907 const struct kwtable *kw;
4909 /* See if it is a reserved word. */
4910 kw = mrb_reserved_word(tok(p), toklen(p));
4911 if (kw) {
4912 enum mrb_lex_state_enum state = p->lstate;
4913 p->lstate = kw->state;
4914 if (state == EXPR_FNAME) {
4915 yylval.id = intern(kw->name);
4916 return kw->id[0];
4918 if (p->lstate == EXPR_BEG) {
4919 p->cmd_start = TRUE;
4921 if (kw->id[0] == keyword_do) {
4922 if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
4923 p->lpar_beg = 0;
4924 p->paren_nest--;
4925 return keyword_do_LAMBDA;
4927 if (COND_P()) return keyword_do_cond;
4928 if (CMDARG_P() && state != EXPR_CMDARG)
4929 return keyword_do_block;
4930 if (state == EXPR_ENDARG || state == EXPR_BEG)
4931 return keyword_do_block;
4932 return keyword_do;
4934 if (state == EXPR_BEG || state == EXPR_VALUE)
4935 return kw->id[0];
4936 else {
4937 if (kw->id[0] != kw->id[1])
4938 p->lstate = EXPR_BEG;
4939 return kw->id[1];
4944 if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
4945 if (cmd_state) {
4946 p->lstate = EXPR_CMDARG;
4948 else {
4949 p->lstate = EXPR_ARG;
4952 else if (p->lstate == EXPR_FNAME) {
4953 p->lstate = EXPR_ENDFN;
4955 else {
4956 p->lstate = EXPR_END;
4960 mrb_sym ident = intern(tok(p));
4962 yylval.id = ident;
4963 #if 0
4964 if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
4965 p->lstate = EXPR_END;
4967 #endif
4969 return result;
4973 static int
4974 yylex(void *lval, parser_state *p)
4976 int t;
4978 p->ylval = lval;
4979 t = parser_yylex(p);
4981 return t;
4984 static void
4985 parser_init_cxt(parser_state *p, mrbc_context *cxt)
4987 if (!cxt) return;
4988 if (cxt->lineno) p->lineno = cxt->lineno;
4989 if (cxt->filename) p->filename = cxt->filename;
4990 if (cxt->syms) {
4991 int i;
4993 p->locals = cons(0,0);
4994 for (i=0; i<cxt->slen; i++) {
4995 local_add_f(p, cxt->syms[i]);
4998 p->capture_errors = cxt->capture_errors;
5001 static void
5002 parser_update_cxt(parser_state *p, mrbc_context *cxt)
5004 node *n, *n0;
5005 int i = 0;
5007 if (!cxt) return;
5008 if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
5009 n0 = n = p->tree->cdr->car;
5010 while (n) {
5011 i++;
5012 n = n->cdr;
5014 cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
5015 cxt->slen = i;
5016 for (i=0, n=n0; n; i++,n=n->cdr) {
5017 cxt->syms[i] = sym(n->car);
5021 void codedump_all(mrb_state*, int);
5022 void parser_dump(mrb_state *mrb, node *tree, int offset);
5024 void
5025 mrb_parser_parse(parser_state *p, mrbc_context *c)
5027 if (setjmp(p->jmp) != 0) {
5028 yyerror(p, "memory allocation error");
5029 p->nerr++;
5030 p->tree = 0;
5031 return;
5034 p->cmd_start = TRUE;
5035 p->in_def = p->in_single = FALSE;
5036 p->nerr = p->nwarn = 0;
5037 p->lex_strterm = NULL;
5039 parser_init_cxt(p, c);
5040 yyparse(p);
5041 if (!p->tree) {
5042 p->tree = new_nil(p);
5044 parser_update_cxt(p, c);
5045 if (c && c->dump_result) {
5046 parser_dump(p->mrb, p->tree, 0);
5050 parser_state*
5051 mrb_parser_new(mrb_state *mrb)
5053 mrb_pool *pool;
5054 parser_state *p;
5055 static const parser_state parser_state_zero = { 0 };
5057 pool = mrb_pool_open(mrb);
5058 if (!pool) return 0;
5059 p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state));
5060 if (!p) return 0;
5062 *p = parser_state_zero;
5063 p->mrb = mrb;
5064 p->pool = pool;
5065 p->in_def = p->in_single = 0;
5067 p->s = p->send = NULL;
5068 p->f = NULL;
5070 p->cmd_start = TRUE;
5071 p->in_def = p->in_single = FALSE;
5073 p->capture_errors = 0;
5074 p->lineno = 1;
5075 p->column = 0;
5076 #if defined(PARSER_TEST) || defined(PARSER_DEBUG)
5077 yydebug = 1;
5078 #endif
5080 p->lex_strterm = NULL;
5081 p->heredocs = p->parsing_heredoc = NULL;
5083 return p;
5086 void
5087 mrb_parser_free(parser_state *p) {
5088 mrb_pool_close(p->pool);
5091 mrbc_context*
5092 mrbc_context_new(mrb_state *mrb)
5094 mrbc_context *c;
5096 c = (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context));
5097 return c;
5100 void
5101 mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
5103 mrb_free(mrb, cxt->syms);
5104 mrb_free(mrb, cxt);
5107 const char*
5108 mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
5110 if (s) {
5111 int len = strlen(s);
5112 char *p = (char *)mrb_alloca(mrb, len + 1);
5114 memcpy(p, s, len + 1);
5115 c->filename = p;
5116 c->lineno = 1;
5118 return c->filename;
5121 parser_state*
5122 mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
5124 parser_state *p;
5126 p = mrb_parser_new(mrb);
5127 if (!p) return 0;
5128 p->s = p->send = NULL;
5129 p->f = f;
5131 mrb_parser_parse(p, c);
5132 return p;
5135 parser_state*
5136 mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
5138 parser_state *p;
5140 p = mrb_parser_new(mrb);
5141 if (!p) return 0;
5142 p->s = s;
5143 p->send = s + len;
5145 mrb_parser_parse(p, c);
5146 return p;
5149 parser_state*
5150 mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
5152 return mrb_parse_nstring(mrb, s, strlen(s), c);
5155 static mrb_value
5156 load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
5158 int n;
5159 mrb_value v;
5161 if (!p) {
5162 return mrb_undef_value();
5164 if (!p->tree || p->nerr) {
5165 if (p->capture_errors) {
5166 char buf[256];
5168 n = snprintf(buf, sizeof(buf), "line %d: %s\n",
5169 p->error_buffer[0].lineno, p->error_buffer[0].message);
5170 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
5171 mrb_parser_free(p);
5172 return mrb_undef_value();
5174 else {
5175 static const char msg[] = "syntax error";
5176 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1));
5177 mrb_parser_free(p);
5178 return mrb_undef_value();
5181 n = mrb_generate_code(mrb, p);
5182 mrb_parser_free(p);
5183 if (n < 0) {
5184 static const char msg[] = "codegen error";
5185 mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1));
5186 return mrb_nil_value();
5188 if (c) {
5189 if (c->dump_result) codedump_all(mrb, n);
5190 if (c->no_exec) return mrb_fixnum_value(n);
5192 v = mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
5193 if (mrb->exc) return mrb_nil_value();
5194 return v;
5197 mrb_value
5198 mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
5200 return load_exec(mrb, mrb_parse_file(mrb, f, c), c);
5203 mrb_value
5204 mrb_load_file(mrb_state *mrb, FILE *f)
5206 return mrb_load_file_cxt(mrb, f, NULL);
5209 mrb_value
5210 mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
5212 return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
5215 mrb_value
5216 mrb_load_nstring(mrb_state *mrb, const char *s, int len)
5218 return mrb_load_nstring_cxt(mrb, s, len, NULL);
5221 mrb_value
5222 mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
5224 return mrb_load_nstring_cxt(mrb, s, strlen(s), c);
5227 mrb_value
5228 mrb_load_string(mrb_state *mrb, const char *s)
5230 return mrb_load_string_cxt(mrb, s, NULL);
5233 #ifdef ENABLE_STDIO
5235 static void
5236 dump_prefix(int offset)
5238 while (offset--) {
5239 putc(' ', stdout);
5240 putc(' ', stdout);
5244 static void
5245 dump_recur(mrb_state *mrb, node *tree, int offset)
5247 while (tree) {
5248 parser_dump(mrb, tree->car, offset);
5249 tree = tree->cdr;
5253 #endif
5255 void
5256 parser_dump(mrb_state *mrb, node *tree, int offset)
5258 #ifdef ENABLE_STDIO
5259 int n;
5261 if (!tree) return;
5262 again:
5263 dump_prefix(offset);
5264 n = (int)(intptr_t)tree->car;
5265 tree = tree->cdr;
5266 switch (n) {
5267 case NODE_BEGIN:
5268 printf("NODE_BEGIN:\n");
5269 dump_recur(mrb, tree, offset+1);
5270 break;
5272 case NODE_RESCUE:
5273 printf("NODE_RESCUE:\n");
5274 if (tree->car) {
5275 dump_prefix(offset+1);
5276 printf("body:\n");
5277 parser_dump(mrb, tree->car, offset+2);
5279 tree = tree->cdr;
5280 if (tree->car) {
5281 node *n2 = tree->car;
5283 dump_prefix(offset+1);
5284 printf("rescue:\n");
5285 while (n2) {
5286 node *n3 = n2->car;
5287 if (n3->car) {
5288 dump_prefix(offset+2);
5289 printf("handle classes:\n");
5290 dump_recur(mrb, n3->car, offset+3);
5292 if (n3->cdr->car) {
5293 dump_prefix(offset+2);
5294 printf("exc_var:\n");
5295 parser_dump(mrb, n3->cdr->car, offset+3);
5297 if (n3->cdr->cdr->car) {
5298 dump_prefix(offset+2);
5299 printf("rescue body:\n");
5300 parser_dump(mrb, n3->cdr->cdr->car, offset+3);
5302 n2 = n2->cdr;
5305 tree = tree->cdr;
5306 if (tree->car) {
5307 dump_prefix(offset+1);
5308 printf("else:\n");
5309 parser_dump(mrb, tree->car, offset+2);
5311 break;
5313 case NODE_ENSURE:
5314 printf("NODE_ENSURE:\n");
5315 dump_prefix(offset+1);
5316 printf("body:\n");
5317 parser_dump(mrb, tree->car, offset+2);
5318 dump_prefix(offset+1);
5319 printf("ensure:\n");
5320 parser_dump(mrb, tree->cdr->cdr, offset+2);
5321 break;
5323 case NODE_LAMBDA:
5324 printf("NODE_BLOCK:\n");
5325 goto block;
5327 case NODE_BLOCK:
5328 block:
5329 printf("NODE_BLOCK:\n");
5330 tree = tree->cdr;
5331 if (tree->car) {
5332 node *n = tree->car;
5334 if (n->car) {
5335 dump_prefix(offset+1);
5336 printf("mandatory args:\n");
5337 dump_recur(mrb, n->car, offset+2);
5339 n = n->cdr;
5340 if (n->car) {
5341 dump_prefix(offset+1);
5342 printf("optional args:\n");
5344 node *n2 = n->car;
5346 while (n2) {
5347 dump_prefix(offset+2);
5348 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5349 parser_dump(mrb, n2->car->cdr, 0);
5350 n2 = n2->cdr;
5354 n = n->cdr;
5355 if (n->car) {
5356 dump_prefix(offset+1);
5357 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5359 n = n->cdr;
5360 if (n->car) {
5361 dump_prefix(offset+1);
5362 printf("post mandatory args:\n");
5363 dump_recur(mrb, n->car, offset+2);
5365 n = n->cdr;
5366 if (n) {
5367 dump_prefix(offset+1);
5368 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5371 dump_prefix(offset+1);
5372 printf("body:\n");
5373 parser_dump(mrb, tree->cdr->car, offset+2);
5374 break;
5376 case NODE_IF:
5377 printf("NODE_IF:\n");
5378 dump_prefix(offset+1);
5379 printf("cond:\n");
5380 parser_dump(mrb, tree->car, offset+2);
5381 dump_prefix(offset+1);
5382 printf("then:\n");
5383 parser_dump(mrb, tree->cdr->car, offset+2);
5384 if (tree->cdr->cdr->car) {
5385 dump_prefix(offset+1);
5386 printf("else:\n");
5387 parser_dump(mrb, tree->cdr->cdr->car, offset+2);
5389 break;
5391 case NODE_AND:
5392 printf("NODE_AND:\n");
5393 parser_dump(mrb, tree->car, offset+1);
5394 parser_dump(mrb, tree->cdr, offset+1);
5395 break;
5397 case NODE_OR:
5398 printf("NODE_OR:\n");
5399 parser_dump(mrb, tree->car, offset+1);
5400 parser_dump(mrb, tree->cdr, offset+1);
5401 break;
5403 case NODE_CASE:
5404 printf("NODE_CASE:\n");
5405 if (tree->car) {
5406 parser_dump(mrb, tree->car, offset+1);
5408 tree = tree->cdr;
5409 while (tree) {
5410 dump_prefix(offset+1);
5411 printf("case:\n");
5412 dump_recur(mrb, tree->car->car, offset+2);
5413 dump_prefix(offset+1);
5414 printf("body:\n");
5415 parser_dump(mrb, tree->car->cdr, offset+2);
5416 tree = tree->cdr;
5418 break;
5420 case NODE_WHILE:
5421 printf("NODE_WHILE:\n");
5422 dump_prefix(offset+1);
5423 printf("cond:\n");
5424 parser_dump(mrb, tree->car, offset+2);
5425 dump_prefix(offset+1);
5426 printf("body:\n");
5427 parser_dump(mrb, tree->cdr, offset+2);
5428 break;
5430 case NODE_UNTIL:
5431 printf("NODE_UNTIL:\n");
5432 dump_prefix(offset+1);
5433 printf("cond:\n");
5434 parser_dump(mrb, tree->car, offset+2);
5435 dump_prefix(offset+1);
5436 printf("body:\n");
5437 parser_dump(mrb, tree->cdr, offset+2);
5438 break;
5440 case NODE_FOR:
5441 printf("NODE_FOR:\n");
5442 dump_prefix(offset+1);
5443 printf("var:\n");
5445 node *n2 = tree->car;
5447 if (n2->car) {
5448 dump_prefix(offset+2);
5449 printf("pre:\n");
5450 dump_recur(mrb, n2->car, offset+3);
5452 n2 = n2->cdr;
5453 if (n2) {
5454 if (n2->car) {
5455 dump_prefix(offset+2);
5456 printf("rest:\n");
5457 parser_dump(mrb, n2->car, offset+3);
5459 n2 = n2->cdr;
5460 if (n2) {
5461 if (n2->car) {
5462 dump_prefix(offset+2);
5463 printf("post:\n");
5464 dump_recur(mrb, n2->car, offset+3);
5469 tree = tree->cdr;
5470 dump_prefix(offset+1);
5471 printf("in:\n");
5472 parser_dump(mrb, tree->car, offset+2);
5473 tree = tree->cdr;
5474 dump_prefix(offset+1);
5475 printf("do:\n");
5476 parser_dump(mrb, tree->car, offset+2);
5477 break;
5479 case NODE_SCOPE:
5480 printf("NODE_SCOPE:\n");
5482 node *n2 = tree->car;
5484 if (n2 && (n2->car || n2->cdr)) {
5485 dump_prefix(offset+1);
5486 printf("local variables:\n");
5487 dump_prefix(offset+2);
5488 while (n2) {
5489 if (n2->car) {
5490 if (n2 != tree->car) printf(", ");
5491 printf("%s", mrb_sym2name(mrb, sym(n2->car)));
5493 n2 = n2->cdr;
5495 printf("\n");
5498 tree = tree->cdr;
5499 offset++;
5500 goto again;
5502 case NODE_FCALL:
5503 case NODE_CALL:
5504 printf("NODE_CALL:\n");
5505 parser_dump(mrb, tree->car, offset+1);
5506 dump_prefix(offset+1);
5507 printf("method='%s' (%d)\n",
5508 mrb_sym2name(mrb, sym(tree->cdr->car)),
5509 (int)(intptr_t)tree->cdr->car);
5510 tree = tree->cdr->cdr->car;
5511 if (tree) {
5512 dump_prefix(offset+1);
5513 printf("args:\n");
5514 dump_recur(mrb, tree->car, offset+2);
5515 if (tree->cdr) {
5516 dump_prefix(offset+1);
5517 printf("block:\n");
5518 parser_dump(mrb, tree->cdr, offset+2);
5521 break;
5523 case NODE_DOT2:
5524 printf("NODE_DOT2:\n");
5525 parser_dump(mrb, tree->car, offset+1);
5526 parser_dump(mrb, tree->cdr, offset+1);
5527 break;
5529 case NODE_DOT3:
5530 printf("NODE_DOT3:\n");
5531 parser_dump(mrb, tree->car, offset+1);
5532 parser_dump(mrb, tree->cdr, offset+1);
5533 break;
5535 case NODE_COLON2:
5536 printf("NODE_COLON2:\n");
5537 parser_dump(mrb, tree->car, offset+1);
5538 dump_prefix(offset+1);
5539 printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr)));
5540 break;
5542 case NODE_COLON3:
5543 printf("NODE_COLON3:\n");
5544 dump_prefix(offset+1);
5545 printf("::%s\n", mrb_sym2name(mrb, sym(tree)));
5546 break;
5548 case NODE_ARRAY:
5549 printf("NODE_ARRAY:\n");
5550 dump_recur(mrb, tree, offset+1);
5551 break;
5553 case NODE_HASH:
5554 printf("NODE_HASH:\n");
5555 while (tree) {
5556 dump_prefix(offset+1);
5557 printf("key:\n");
5558 parser_dump(mrb, tree->car->car, offset+2);
5559 dump_prefix(offset+1);
5560 printf("value:\n");
5561 parser_dump(mrb, tree->car->cdr, offset+2);
5562 tree = tree->cdr;
5564 break;
5566 case NODE_SPLAT:
5567 printf("NODE_SPLAT:\n");
5568 parser_dump(mrb, tree, offset+1);
5569 break;
5571 case NODE_ASGN:
5572 printf("NODE_ASGN:\n");
5573 dump_prefix(offset+1);
5574 printf("lhs:\n");
5575 parser_dump(mrb, tree->car, offset+2);
5576 dump_prefix(offset+1);
5577 printf("rhs:\n");
5578 parser_dump(mrb, tree->cdr, offset+2);
5579 break;
5581 case NODE_MASGN:
5582 printf("NODE_MASGN:\n");
5583 dump_prefix(offset+1);
5584 printf("mlhs:\n");
5586 node *n2 = tree->car;
5588 if (n2->car) {
5589 dump_prefix(offset+2);
5590 printf("pre:\n");
5591 dump_recur(mrb, n2->car, offset+3);
5593 n2 = n2->cdr;
5594 if (n2) {
5595 if (n2->car) {
5596 dump_prefix(offset+2);
5597 printf("rest:\n");
5598 if (n2->car == (node*)-1) {
5599 dump_prefix(offset+2);
5600 printf("(empty)\n");
5602 else {
5603 parser_dump(mrb, n2->car, offset+3);
5606 n2 = n2->cdr;
5607 if (n2) {
5608 if (n2->car) {
5609 dump_prefix(offset+2);
5610 printf("post:\n");
5611 dump_recur(mrb, n2->car, offset+3);
5616 dump_prefix(offset+1);
5617 printf("rhs:\n");
5618 parser_dump(mrb, tree->cdr, offset+2);
5619 break;
5621 case NODE_OP_ASGN:
5622 printf("NODE_OP_ASGN:\n");
5623 dump_prefix(offset+1);
5624 printf("lhs:\n");
5625 parser_dump(mrb, tree->car, offset+2);
5626 tree = tree->cdr;
5627 dump_prefix(offset+1);
5628 printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
5629 tree = tree->cdr;
5630 parser_dump(mrb, tree->car, offset+1);
5631 break;
5633 case NODE_SUPER:
5634 printf("NODE_SUPER:\n");
5635 if (tree) {
5636 dump_prefix(offset+1);
5637 printf("args:\n");
5638 dump_recur(mrb, tree->car, offset+2);
5639 if (tree->cdr) {
5640 dump_prefix(offset+1);
5641 printf("block:\n");
5642 parser_dump(mrb, tree->cdr, offset+2);
5645 break;
5647 case NODE_ZSUPER:
5648 printf("NODE_ZSUPER\n");
5649 break;
5651 case NODE_RETURN:
5652 printf("NODE_RETURN:\n");
5653 parser_dump(mrb, tree, offset+1);
5654 break;
5656 case NODE_YIELD:
5657 printf("NODE_YIELD:\n");
5658 dump_recur(mrb, tree, offset+1);
5659 break;
5661 case NODE_BREAK:
5662 printf("NODE_BREAK:\n");
5663 parser_dump(mrb, tree, offset+1);
5664 break;
5666 case NODE_NEXT:
5667 printf("NODE_NEXT:\n");
5668 parser_dump(mrb, tree, offset+1);
5669 break;
5671 case NODE_REDO:
5672 printf("NODE_REDO\n");
5673 break;
5675 case NODE_RETRY:
5676 printf("NODE_RETRY\n");
5677 break;
5679 case NODE_LVAR:
5680 printf("NODE_LVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5681 break;
5683 case NODE_GVAR:
5684 printf("NODE_GVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5685 break;
5687 case NODE_IVAR:
5688 printf("NODE_IVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5689 break;
5691 case NODE_CVAR:
5692 printf("NODE_CVAR %s\n", mrb_sym2name(mrb, sym(tree)));
5693 break;
5695 case NODE_CONST:
5696 printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree)));
5697 break;
5699 case NODE_MATCH:
5700 printf("NODE_MATCH:\n");
5701 dump_prefix(offset + 1);
5702 printf("lhs:\n");
5703 parser_dump(mrb, tree->car, offset + 2);
5704 dump_prefix(offset + 1);
5705 printf("rhs:\n");
5706 parser_dump(mrb, tree->cdr, offset + 2);
5707 break;
5709 case NODE_BACK_REF:
5710 printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
5711 break;
5713 case NODE_NTH_REF:
5714 printf("NODE_NTH_REF: $%d\n", (int)(intptr_t)tree);
5715 break;
5717 case NODE_ARG:
5718 printf("NODE_ARG %s\n", mrb_sym2name(mrb, sym(tree)));
5719 break;
5721 case NODE_BLOCK_ARG:
5722 printf("NODE_BLOCK_ARG:\n");
5723 parser_dump(mrb, tree, offset+1);
5724 break;
5726 case NODE_INT:
5727 printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
5728 break;
5730 case NODE_FLOAT:
5731 printf("NODE_FLOAT %s\n", (char*)tree);
5732 break;
5734 case NODE_NEGATE:
5735 printf("NODE_NEGATE\n");
5736 parser_dump(mrb, tree, offset+1);
5737 break;
5739 case NODE_STR:
5740 printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
5741 break;
5743 case NODE_DSTR:
5744 printf("NODE_DSTR\n");
5745 dump_recur(mrb, tree, offset+1);
5746 break;
5748 case NODE_XSTR:
5749 printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
5750 break;
5752 case NODE_DXSTR:
5753 printf("NODE_DXSTR\n");
5754 dump_recur(mrb, tree, offset+1);
5755 break;
5757 case NODE_REGX:
5758 printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
5759 break;
5761 case NODE_DREGX:
5762 printf("NODE_DREGX\n");
5763 dump_recur(mrb, tree->car, offset+1);
5764 dump_prefix(offset);
5765 printf("tail: %s\n", (char*)tree->cdr->cdr->car);
5766 dump_prefix(offset);
5767 printf("opt: %s\n", (char*)tree->cdr->cdr->cdr);
5768 break;
5770 case NODE_SYM:
5771 printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree)));
5772 break;
5774 case NODE_SELF:
5775 printf("NODE_SELF\n");
5776 break;
5778 case NODE_NIL:
5779 printf("NODE_NIL\n");
5780 break;
5782 case NODE_TRUE:
5783 printf("NODE_TRUE\n");
5784 break;
5786 case NODE_FALSE:
5787 printf("NODE_FALSE\n");
5788 break;
5790 case NODE_ALIAS:
5791 printf("NODE_ALIAS %s %s:\n",
5792 mrb_sym2name(mrb, sym(tree->car)),
5793 mrb_sym2name(mrb, sym(tree->cdr)));
5794 break;
5796 case NODE_UNDEF:
5797 printf("NODE_UNDEF");
5799 node *t = tree;
5800 while (t) {
5801 printf(" %s", mrb_sym2name(mrb, sym(t->car)));
5802 t = t->cdr;
5805 printf(":\n");
5806 break;
5808 case NODE_CLASS:
5809 printf("NODE_CLASS:\n");
5810 if (tree->car->car == (node*)0) {
5811 dump_prefix(offset+1);
5812 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5814 else if (tree->car->car == (node*)1) {
5815 dump_prefix(offset+1);
5816 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5818 else {
5819 parser_dump(mrb, tree->car->car, offset+1);
5820 dump_prefix(offset+1);
5821 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5823 if (tree->cdr->car) {
5824 dump_prefix(offset+1);
5825 printf("super:\n");
5826 parser_dump(mrb, tree->cdr->car, offset+2);
5828 dump_prefix(offset+1);
5829 printf("body:\n");
5830 parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2);
5831 break;
5833 case NODE_MODULE:
5834 printf("NODE_MODULE:\n");
5835 if (tree->car->car == (node*)0) {
5836 dump_prefix(offset+1);
5837 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5839 else if (tree->car->car == (node*)1) {
5840 dump_prefix(offset+1);
5841 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5843 else {
5844 parser_dump(mrb, tree->car->car, offset+1);
5845 dump_prefix(offset+1);
5846 printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
5848 dump_prefix(offset+1);
5849 printf("body:\n");
5850 parser_dump(mrb, tree->cdr->car->cdr, offset+2);
5851 break;
5853 case NODE_SCLASS:
5854 printf("NODE_SCLASS:\n");
5855 parser_dump(mrb, tree->car, offset+1);
5856 dump_prefix(offset+1);
5857 printf("body:\n");
5858 parser_dump(mrb, tree->cdr->car->cdr, offset+2);
5859 break;
5861 case NODE_DEF:
5862 printf("NODE_DEF:\n");
5863 dump_prefix(offset+1);
5864 printf("%s\n", mrb_sym2name(mrb, sym(tree->car)));
5865 tree = tree->cdr;
5867 node *n2 = tree->car;
5869 if (n2 && (n2->car || n2->cdr)) {
5870 dump_prefix(offset+1);
5871 printf("local variables:\n");
5872 dump_prefix(offset+2);
5873 while (n2) {
5874 if (n2->car) {
5875 if (n2 != tree->car) printf(", ");
5876 printf("%s", mrb_sym2name(mrb, sym(n2->car)));
5878 n2 = n2->cdr;
5880 printf("\n");
5883 tree = tree->cdr;
5884 if (tree->car) {
5885 node *n = tree->car;
5887 if (n->car) {
5888 dump_prefix(offset+1);
5889 printf("mandatory args:\n");
5890 dump_recur(mrb, n->car, offset+2);
5892 n = n->cdr;
5893 if (n->car) {
5894 dump_prefix(offset+1);
5895 printf("optional args:\n");
5897 node *n2 = n->car;
5899 while (n2) {
5900 dump_prefix(offset+2);
5901 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5902 parser_dump(mrb, n2->car->cdr, 0);
5903 n2 = n2->cdr;
5907 n = n->cdr;
5908 if (n->car) {
5909 dump_prefix(offset+1);
5910 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5912 n = n->cdr;
5913 if (n->car) {
5914 dump_prefix(offset+1);
5915 printf("post mandatory args:\n");
5916 dump_recur(mrb, n->car, offset+2);
5918 n = n->cdr;
5919 if (n) {
5920 dump_prefix(offset+1);
5921 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5924 parser_dump(mrb, tree->cdr->car, offset+1);
5925 break;
5927 case NODE_SDEF:
5928 printf("NODE_SDEF:\n");
5929 parser_dump(mrb, tree->car, offset+1);
5930 tree = tree->cdr;
5931 dump_prefix(offset+1);
5932 printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
5933 tree = tree->cdr->cdr;
5934 if (tree->car) {
5935 node *n = tree->car;
5937 if (n->car) {
5938 dump_prefix(offset+1);
5939 printf("mandatory args:\n");
5940 dump_recur(mrb, n->car, offset+2);
5942 n = n->cdr;
5943 if (n->car) {
5944 dump_prefix(offset+1);
5945 printf("optional args:\n");
5947 node *n2 = n->car;
5949 while (n2) {
5950 dump_prefix(offset+2);
5951 printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
5952 parser_dump(mrb, n2->car->cdr, 0);
5953 n2 = n2->cdr;
5957 n = n->cdr;
5958 if (n->car) {
5959 dump_prefix(offset+1);
5960 printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
5962 n = n->cdr;
5963 if (n->car) {
5964 dump_prefix(offset+1);
5965 printf("post mandatory args:\n");
5966 dump_recur(mrb, n->car, offset+2);
5968 n = n->cdr;
5969 if (n) {
5970 dump_prefix(offset+1);
5971 printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
5974 tree = tree->cdr;
5975 parser_dump(mrb, tree->car, offset+1);
5976 break;
5978 case NODE_POSTEXE:
5979 printf("NODE_POSTEXE:\n");
5980 parser_dump(mrb, tree, offset+1);
5981 break;
5983 case NODE_HEREDOC:
5984 printf("NODE_HEREDOC:\n");
5985 parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
5986 break;
5988 default:
5989 printf("node type: %d (0x%x)\n", (int)n, (int)n);
5990 break;
5992 #endif