Ruby  2.0.0p594(2014-10-27revision48167)
parse.y
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   parse.y -
00004 
00005   $Author: usa $
00006   created at: Fri May 28 18:02:42 JST 1993
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009 
00010 **********************************************************************/
00011 
00012 %{
00013 
00014 #ifndef PARSER_DEBUG
00015 #define PARSER_DEBUG 0
00016 #endif
00017 #define YYDEBUG 1
00018 #define YYERROR_VERBOSE 1
00019 #define YYSTACK_USE_ALLOCA 0
00020 
00021 #include "ruby/ruby.h"
00022 #include "ruby/st.h"
00023 #include "ruby/encoding.h"
00024 #include "internal.h"
00025 #include "node.h"
00026 #include "parse.h"
00027 #include "id.h"
00028 #include "regenc.h"
00029 #include <stdio.h>
00030 #include <errno.h>
00031 #include <ctype.h>
00032 #include "probes.h"
00033 
00034 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00035 
00036 #define YYMALLOC(size)          rb_parser_malloc(parser, (size))
00037 #define YYREALLOC(ptr, size)    rb_parser_realloc(parser, (ptr), (size))
00038 #define YYCALLOC(nelem, size)   rb_parser_calloc(parser, (nelem), (size))
00039 #define YYFREE(ptr)             rb_parser_free(parser, (ptr))
00040 #define malloc  YYMALLOC
00041 #define realloc YYREALLOC
00042 #define calloc  YYCALLOC
00043 #define free    YYFREE
00044 
00045 #ifndef RIPPER
00046 static ID register_symid(ID, const char *, long, rb_encoding *);
00047 static ID register_symid_str(ID, VALUE);
00048 #define REGISTER_SYMID(id, name) register_symid((id), (name), strlen(name), enc)
00049 #include "id.c"
00050 #endif
00051 
00052 #define is_notop_id(id) ((id)>tLAST_OP_ID)
00053 #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
00054 #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
00055 #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
00056 #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
00057 #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
00058 #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
00059 #define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
00060 #define id_type(id) (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1)
00061 
00062 #define is_asgn_or_id(id) ((is_notop_id(id)) && \
00063         (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
00064          ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
00065          ((id)&ID_SCOPE_MASK) == ID_CLASS))
00066 
00067 enum lex_state_bits {
00068     EXPR_BEG_bit,               /* ignore newline, +/- is a sign. */
00069     EXPR_END_bit,               /* newline significant, +/- is an operator. */
00070     EXPR_ENDARG_bit,            /* ditto, and unbound braces. */
00071     EXPR_ENDFN_bit,             /* ditto, and unbound braces. */
00072     EXPR_ARG_bit,               /* newline significant, +/- is an operator. */
00073     EXPR_CMDARG_bit,            /* newline significant, +/- is an operator. */
00074     EXPR_MID_bit,               /* newline significant, +/- is an operator. */
00075     EXPR_FNAME_bit,             /* ignore newline, no reserved words. */
00076     EXPR_DOT_bit,               /* right after `.' or `::', no reserved words. */
00077     EXPR_CLASS_bit,             /* immediate after `class', no here document. */
00078     EXPR_VALUE_bit,             /* alike EXPR_BEG but label is disallowed. */
00079     EXPR_MAX_STATE
00080 };
00081 /* examine combinations */
00082 enum lex_state_e {
00083 #define DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit)
00084     DEF_EXPR(BEG),
00085     DEF_EXPR(END),
00086     DEF_EXPR(ENDARG),
00087     DEF_EXPR(ENDFN),
00088     DEF_EXPR(ARG),
00089     DEF_EXPR(CMDARG),
00090     DEF_EXPR(MID),
00091     DEF_EXPR(FNAME),
00092     DEF_EXPR(DOT),
00093     DEF_EXPR(CLASS),
00094     DEF_EXPR(VALUE),
00095     EXPR_BEG_ANY  =  (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS),
00096     EXPR_ARG_ANY  =  (EXPR_ARG | EXPR_CMDARG),
00097     EXPR_END_ANY  =  (EXPR_END | EXPR_ENDARG | EXPR_ENDFN)
00098 };
00099 #define IS_lex_state_for(x, ls) ((x) & (ls))
00100 #define IS_lex_state(ls)        IS_lex_state_for(lex_state, (ls))
00101 
00102 #if PARSER_DEBUG
00103 static const char *lex_state_name(enum lex_state_e state);
00104 #endif
00105 
00106 typedef VALUE stack_type;
00107 
00108 # define BITSTACK_PUSH(stack, n)        ((stack) = ((stack)<<1)|((n)&1))
00109 # define BITSTACK_POP(stack)    ((stack) = (stack) >> 1)
00110 # define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
00111 # define BITSTACK_SET_P(stack)  ((stack)&1)
00112 
00113 #define COND_PUSH(n)    BITSTACK_PUSH(cond_stack, (n))
00114 #define COND_POP()      BITSTACK_POP(cond_stack)
00115 #define COND_LEXPOP()   BITSTACK_LEXPOP(cond_stack)
00116 #define COND_P()        BITSTACK_SET_P(cond_stack)
00117 
00118 #define CMDARG_PUSH(n)  BITSTACK_PUSH(cmdarg_stack, (n))
00119 #define CMDARG_POP()    BITSTACK_POP(cmdarg_stack)
00120 #define CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
00121 #define CMDARG_P()      BITSTACK_SET_P(cmdarg_stack)
00122 
00123 struct vtable {
00124     ID *tbl;
00125     int pos;
00126     int capa;
00127     struct vtable *prev;
00128 };
00129 
00130 struct local_vars {
00131     struct vtable *args;
00132     struct vtable *vars;
00133     struct vtable *used;
00134     struct local_vars *prev;
00135     stack_type cmdargs;
00136 };
00137 
00138 #define DVARS_INHERIT ((void*)1)
00139 #define DVARS_TOPSCOPE NULL
00140 #define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
00141 #define POINTER_P(val) ((VALUE)(val) & ~(VALUE)3)
00142 
00143 static int
00144 vtable_size(const struct vtable *tbl)
00145 {
00146     if (POINTER_P(tbl)) {
00147         return tbl->pos;
00148     }
00149     else {
00150         return 0;
00151     }
00152 }
00153 
00154 #define VTBL_DEBUG 0
00155 
00156 static struct vtable *
00157 vtable_alloc(struct vtable *prev)
00158 {
00159     struct vtable *tbl = ALLOC(struct vtable);
00160     tbl->pos = 0;
00161     tbl->capa = 8;
00162     tbl->tbl = ALLOC_N(ID, tbl->capa);
00163     tbl->prev = prev;
00164     if (VTBL_DEBUG) printf("vtable_alloc: %p\n", (void *)tbl);
00165     return tbl;
00166 }
00167 
00168 static void
00169 vtable_free(struct vtable *tbl)
00170 {
00171     if (VTBL_DEBUG)printf("vtable_free: %p\n", (void *)tbl);
00172     if (POINTER_P(tbl)) {
00173         if (tbl->tbl) {
00174             xfree(tbl->tbl);
00175         }
00176         xfree(tbl);
00177     }
00178 }
00179 
00180 static void
00181 vtable_add(struct vtable *tbl, ID id)
00182 {
00183     if (!POINTER_P(tbl)) {
00184         rb_bug("vtable_add: vtable is not allocated (%p)", (void *)tbl);
00185     }
00186     if (VTBL_DEBUG) printf("vtable_add: %p, %s\n", (void *)tbl, rb_id2name(id));
00187 
00188     if (tbl->pos == tbl->capa) {
00189         tbl->capa = tbl->capa * 2;
00190         REALLOC_N(tbl->tbl, ID, tbl->capa);
00191     }
00192     tbl->tbl[tbl->pos++] = id;
00193 }
00194 
00195 static int
00196 vtable_included(const struct vtable * tbl, ID id)
00197 {
00198     int i;
00199 
00200     if (POINTER_P(tbl)) {
00201         for (i = 0; i < tbl->pos; i++) {
00202             if (tbl->tbl[i] == id) {
00203                 return i+1;
00204             }
00205         }
00206     }
00207     return 0;
00208 }
00209 
00210 
00211 #ifndef RIPPER
00212 typedef struct token_info {
00213     const char *token;
00214     int linenum;
00215     int column;
00216     int nonspc;
00217     struct token_info *next;
00218 } token_info;
00219 #endif
00220 
00221 /*
00222     Structure of Lexer Buffer:
00223 
00224  lex_pbeg      tokp         lex_p        lex_pend
00225     |           |              |            |
00226     |-----------+--------------+------------|
00227                 |<------------>|
00228                      token
00229 */
00230 struct parser_params {
00231     int is_ripper;
00232     NODE *heap;
00233 
00234     YYSTYPE *parser_yylval;
00235     VALUE eofp;
00236 
00237     NODE *parser_lex_strterm;
00238     enum lex_state_e parser_lex_state;
00239     stack_type parser_cond_stack;
00240     stack_type parser_cmdarg_stack;
00241     int parser_class_nest;
00242     int parser_paren_nest;
00243     int parser_lpar_beg;
00244     int parser_in_single;
00245     int parser_in_def;
00246     int parser_brace_nest;
00247     int parser_compile_for_eval;
00248     VALUE parser_cur_mid;
00249     int parser_in_defined;
00250     char *parser_tokenbuf;
00251     int parser_tokidx;
00252     int parser_toksiz;
00253     int parser_tokline;
00254     VALUE parser_lex_input;
00255     VALUE parser_lex_lastline;
00256     VALUE parser_lex_nextline;
00257     const char *parser_lex_pbeg;
00258     const char *parser_lex_p;
00259     const char *parser_lex_pend;
00260     int parser_heredoc_end;
00261     int parser_command_start;
00262     NODE *parser_deferred_nodes;
00263     long parser_lex_gets_ptr;
00264     VALUE (*parser_lex_gets)(struct parser_params*,VALUE);
00265     struct local_vars *parser_lvtbl;
00266     int parser_ruby__end__seen;
00267     int line_count;
00268     int has_shebang;
00269     char *parser_ruby_sourcefile; /* current source file */
00270     int parser_ruby_sourceline; /* current line no. */
00271     VALUE parser_ruby_sourcefile_string;
00272     rb_encoding *enc;
00273 
00274     int parser_yydebug;
00275 
00276 #ifndef RIPPER
00277     /* Ruby core only */
00278     NODE *parser_eval_tree_begin;
00279     NODE *parser_eval_tree;
00280     VALUE debug_lines;
00281     VALUE coverage;
00282     int nerr;
00283 
00284     int parser_token_info_enabled;
00285     token_info *parser_token_info;
00286 #else
00287     /* Ripper only */
00288     const char *tokp;
00289     VALUE delayed;
00290     int delayed_line;
00291     int delayed_col;
00292 
00293     VALUE value;
00294     VALUE result;
00295     VALUE parsing_thread;
00296     int toplevel_p;
00297 #endif
00298 };
00299 
00300 #define STR_NEW(p,n) rb_enc_str_new((p),(n),current_enc)
00301 #define STR_NEW0() rb_enc_str_new(0,0,current_enc)
00302 #define STR_NEW2(p) rb_enc_str_new((p),strlen(p),current_enc)
00303 #define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),current_enc)
00304 #define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
00305 #define TOK_INTERN(mb) rb_intern3(tok(), toklen(), current_enc)
00306 
00307 static int parser_yyerror(struct parser_params*, const char*);
00308 #define yyerror(msg) parser_yyerror(parser, (msg))
00309 
00310 #define lex_strterm             (parser->parser_lex_strterm)
00311 #define lex_state               (parser->parser_lex_state)
00312 #define cond_stack              (parser->parser_cond_stack)
00313 #define cmdarg_stack            (parser->parser_cmdarg_stack)
00314 #define class_nest              (parser->parser_class_nest)
00315 #define paren_nest              (parser->parser_paren_nest)
00316 #define lpar_beg                (parser->parser_lpar_beg)
00317 #define brace_nest              (parser->parser_brace_nest)
00318 #define in_single               (parser->parser_in_single)
00319 #define in_def                  (parser->parser_in_def)
00320 #define compile_for_eval        (parser->parser_compile_for_eval)
00321 #define cur_mid                 (parser->parser_cur_mid)
00322 #define in_defined              (parser->parser_in_defined)
00323 #define tokenbuf                (parser->parser_tokenbuf)
00324 #define tokidx                  (parser->parser_tokidx)
00325 #define toksiz                  (parser->parser_toksiz)
00326 #define tokline                 (parser->parser_tokline)
00327 #define lex_input               (parser->parser_lex_input)
00328 #define lex_lastline            (parser->parser_lex_lastline)
00329 #define lex_nextline            (parser->parser_lex_nextline)
00330 #define lex_pbeg                (parser->parser_lex_pbeg)
00331 #define lex_p                   (parser->parser_lex_p)
00332 #define lex_pend                (parser->parser_lex_pend)
00333 #define heredoc_end             (parser->parser_heredoc_end)
00334 #define command_start           (parser->parser_command_start)
00335 #define deferred_nodes          (parser->parser_deferred_nodes)
00336 #define lex_gets_ptr            (parser->parser_lex_gets_ptr)
00337 #define lex_gets                (parser->parser_lex_gets)
00338 #define lvtbl                   (parser->parser_lvtbl)
00339 #define ruby__end__seen         (parser->parser_ruby__end__seen)
00340 #define ruby_sourceline         (parser->parser_ruby_sourceline)
00341 #define ruby_sourcefile         (parser->parser_ruby_sourcefile)
00342 #define ruby_sourcefile_string  (parser->parser_ruby_sourcefile_string)
00343 #define current_enc             (parser->enc)
00344 #define yydebug                 (parser->parser_yydebug)
00345 #ifdef RIPPER
00346 #else
00347 #define ruby_eval_tree          (parser->parser_eval_tree)
00348 #define ruby_eval_tree_begin    (parser->parser_eval_tree_begin)
00349 #define ruby_debug_lines        (parser->debug_lines)
00350 #define ruby_coverage           (parser->coverage)
00351 #endif
00352 
00353 #if YYPURE
00354 static int yylex(void*, void*);
00355 #else
00356 static int yylex(void*);
00357 #endif
00358 
00359 #ifndef RIPPER
00360 #define yyparse ruby_yyparse
00361 
00362 static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE);
00363 #define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, (type), (a1), (a2), (a3))
00364 
00365 static NODE *cond_gen(struct parser_params*,NODE*);
00366 #define cond(node) cond_gen(parser, (node))
00367 static NODE *logop_gen(struct parser_params*,enum node_type,NODE*,NODE*);
00368 #define logop(type,node1,node2) logop_gen(parser, (type), (node1), (node2))
00369 
00370 static NODE *newline_node(NODE*);
00371 static void fixpos(NODE*,NODE*);
00372 
00373 static int value_expr_gen(struct parser_params*,NODE*);
00374 static void void_expr_gen(struct parser_params*,NODE*);
00375 static NODE *remove_begin(NODE*);
00376 #define value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
00377 #define void_expr0(node) void_expr_gen(parser, (node))
00378 #define void_expr(node) void_expr0((node) = remove_begin(node))
00379 static void void_stmts_gen(struct parser_params*,NODE*);
00380 #define void_stmts(node) void_stmts_gen(parser, (node))
00381 static void reduce_nodes_gen(struct parser_params*,NODE**);
00382 #define reduce_nodes(n) reduce_nodes_gen(parser,(n))
00383 static void block_dup_check_gen(struct parser_params*,NODE*,NODE*);
00384 #define block_dup_check(n1,n2) block_dup_check_gen(parser,(n1),(n2))
00385 
00386 static NODE *block_append_gen(struct parser_params*,NODE*,NODE*);
00387 #define block_append(h,t) block_append_gen(parser,(h),(t))
00388 static NODE *list_append_gen(struct parser_params*,NODE*,NODE*);
00389 #define list_append(l,i) list_append_gen(parser,(l),(i))
00390 static NODE *list_concat_gen(struct parser_params*,NODE*,NODE*);
00391 #define list_concat(h,t) list_concat_gen(parser,(h),(t))
00392 static NODE *arg_append_gen(struct parser_params*,NODE*,NODE*);
00393 #define arg_append(h,t) arg_append_gen(parser,(h),(t))
00394 static NODE *arg_concat_gen(struct parser_params*,NODE*,NODE*);
00395 #define arg_concat(h,t) arg_concat_gen(parser,(h),(t))
00396 static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*);
00397 #define literal_concat(h,t) literal_concat_gen(parser,(h),(t))
00398 static int literal_concat0(struct parser_params *, VALUE, VALUE);
00399 static NODE *new_evstr_gen(struct parser_params*,NODE*);
00400 #define new_evstr(n) new_evstr_gen(parser,(n))
00401 static NODE *evstr2dstr_gen(struct parser_params*,NODE*);
00402 #define evstr2dstr(n) evstr2dstr_gen(parser,(n))
00403 static NODE *splat_array(NODE*);
00404 
00405 static NODE *call_bin_op_gen(struct parser_params*,NODE*,ID,NODE*);
00406 #define call_bin_op(recv,id,arg1) call_bin_op_gen(parser, (recv),(id),(arg1))
00407 static NODE *call_uni_op_gen(struct parser_params*,NODE*,ID);
00408 #define call_uni_op(recv,id) call_uni_op_gen(parser, (recv),(id))
00409 
00410 static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*);
00411 #define new_args(f,o,r,p,t) new_args_gen(parser, (f),(o),(r),(p),(t))
00412 static NODE *new_args_tail_gen(struct parser_params*,NODE*,ID,ID);
00413 #define new_args_tail(k,kr,b) new_args_tail_gen(parser, (k),(kr),(b))
00414 
00415 static NODE *negate_lit(NODE*);
00416 static NODE *ret_args_gen(struct parser_params*,NODE*);
00417 #define ret_args(node) ret_args_gen(parser, (node))
00418 static NODE *arg_blk_pass(NODE*,NODE*);
00419 static NODE *new_yield_gen(struct parser_params*,NODE*);
00420 #define new_yield(node) new_yield_gen(parser, (node))
00421 static NODE *dsym_node_gen(struct parser_params*,NODE*);
00422 #define dsym_node(node) dsym_node_gen(parser, (node))
00423 
00424 static NODE *gettable_gen(struct parser_params*,ID);
00425 #define gettable(id) gettable_gen(parser,(id))
00426 static NODE *assignable_gen(struct parser_params*,ID,NODE*);
00427 #define assignable(id,node) assignable_gen(parser, (id), (node))
00428 
00429 static NODE *aryset_gen(struct parser_params*,NODE*,NODE*);
00430 #define aryset(node1,node2) aryset_gen(parser, (node1), (node2))
00431 static NODE *attrset_gen(struct parser_params*,NODE*,ID);
00432 #define attrset(node,id) attrset_gen(parser, (node), (id))
00433 
00434 static void rb_backref_error_gen(struct parser_params*,NODE*);
00435 #define rb_backref_error(n) rb_backref_error_gen(parser,(n))
00436 static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*);
00437 #define node_assign(node1, node2) node_assign_gen(parser, (node1), (node2))
00438 
00439 static NODE *new_op_assign_gen(struct parser_params *parser, NODE *lhs, ID op, NODE *rhs);
00440 static NODE *new_attr_op_assign_gen(struct parser_params *parser, NODE *lhs, ID attr, ID op, NODE *rhs);
00441 #define new_attr_op_assign(lhs, type, attr, op, rhs) new_attr_op_assign_gen(parser, (lhs), (attr), (op), (rhs))
00442 static NODE *new_const_op_assign_gen(struct parser_params *parser, NODE *lhs, ID op, NODE *rhs);
00443 #define new_const_op_assign(lhs, op, rhs) new_const_op_assign_gen(parser, (lhs), (op), (rhs))
00444 
00445 static NODE *match_op_gen(struct parser_params*,NODE*,NODE*);
00446 #define match_op(node1,node2) match_op_gen(parser, (node1), (node2))
00447 
00448 static ID  *local_tbl_gen(struct parser_params*);
00449 #define local_tbl() local_tbl_gen(parser)
00450 
00451 static void fixup_nodes(NODE **);
00452 
00453 static VALUE reg_compile_gen(struct parser_params*, VALUE, int);
00454 #define reg_compile(str,options) reg_compile_gen(parser, (str), (options))
00455 static void reg_fragment_setenc_gen(struct parser_params*, VALUE, int);
00456 #define reg_fragment_setenc(str,options) reg_fragment_setenc_gen(parser, (str), (options))
00457 static int reg_fragment_check_gen(struct parser_params*, VALUE, int);
00458 #define reg_fragment_check(str,options) reg_fragment_check_gen(parser, (str), (options))
00459 static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
00460 #define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,(regexp),(match))
00461 
00462 #define get_id(id) (id)
00463 #define get_value(val) (val)
00464 #else
00465 #define value_expr(node) ((void)(node))
00466 #define remove_begin(node) (node)
00467 #define rb_dvar_defined(id) 0
00468 #define rb_local_defined(id) 0
00469 static ID ripper_get_id(VALUE);
00470 #define get_id(id) ripper_get_id(id)
00471 static VALUE ripper_get_value(VALUE);
00472 #define get_value(val) ripper_get_value(val)
00473 static VALUE assignable_gen(struct parser_params*,VALUE);
00474 #define assignable(lhs,node) assignable_gen(parser, (lhs))
00475 static int id_is_var_gen(struct parser_params *parser, ID id);
00476 #define id_is_var(id) id_is_var_gen(parser, (id))
00477 
00478 #define node_assign(node1, node2) dispatch2(assign, (node1), (node2))
00479 
00480 static VALUE new_op_assign_gen(struct parser_params *parser, VALUE lhs, VALUE op, VALUE rhs);
00481 static VALUE new_attr_op_assign_gen(struct parser_params *parser, VALUE lhs, VALUE type, VALUE attr, VALUE op, VALUE rhs);
00482 #define new_attr_op_assign(lhs, type, attr, op, rhs) new_attr_op_assign_gen(parser, (lhs), (type), (attr), (op), (rhs))
00483 
00484 #endif /* !RIPPER */
00485 
00486 #define new_op_assign(lhs, op, rhs) new_op_assign_gen(parser, (lhs), (op), (rhs))
00487 
00488 static ID formal_argument_gen(struct parser_params*, ID);
00489 #define formal_argument(id) formal_argument_gen(parser, (id))
00490 static ID shadowing_lvar_gen(struct parser_params*,ID);
00491 #define shadowing_lvar(name) shadowing_lvar_gen(parser, (name))
00492 static void new_bv_gen(struct parser_params*,ID);
00493 #define new_bv(id) new_bv_gen(parser, (id))
00494 
00495 static void local_push_gen(struct parser_params*,int);
00496 #define local_push(top) local_push_gen(parser,(top))
00497 static void local_pop_gen(struct parser_params*);
00498 #define local_pop() local_pop_gen(parser)
00499 static int local_var_gen(struct parser_params*, ID);
00500 #define local_var(id) local_var_gen(parser, (id))
00501 static int arg_var_gen(struct parser_params*, ID);
00502 #define arg_var(id) arg_var_gen(parser, (id))
00503 static int  local_id_gen(struct parser_params*, ID);
00504 #define local_id(id) local_id_gen(parser, (id))
00505 static ID   internal_id_gen(struct parser_params*);
00506 #define internal_id() internal_id_gen(parser)
00507 
00508 static const struct vtable *dyna_push_gen(struct parser_params *);
00509 #define dyna_push() dyna_push_gen(parser)
00510 static void dyna_pop_gen(struct parser_params*, const struct vtable *);
00511 #define dyna_pop(node) dyna_pop_gen(parser, (node))
00512 static int dyna_in_block_gen(struct parser_params*);
00513 #define dyna_in_block() dyna_in_block_gen(parser)
00514 #define dyna_var(id) local_var(id)
00515 static int dvar_defined_gen(struct parser_params*,ID,int);
00516 #define dvar_defined(id) dvar_defined_gen(parser, (id), 0)
00517 #define dvar_defined_get(id) dvar_defined_gen(parser, (id), 1)
00518 static int dvar_curr_gen(struct parser_params*,ID);
00519 #define dvar_curr(id) dvar_curr_gen(parser, (id))
00520 
00521 static int lvar_defined_gen(struct parser_params*, ID);
00522 #define lvar_defined(id) lvar_defined_gen(parser, (id))
00523 
00524 #define RE_OPTION_ONCE (1<<16)
00525 #define RE_OPTION_ENCODING_SHIFT 8
00526 #define RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
00527 #define RE_OPTION_ENCODING_IDX(o) (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
00528 #define RE_OPTION_ENCODING_NONE(o) ((o)&RE_OPTION_ARG_ENCODING_NONE)
00529 #define RE_OPTION_MASK  0xff
00530 #define RE_OPTION_ARG_ENCODING_NONE 32
00531 
00532 #define NODE_STRTERM NODE_ZARRAY        /* nothing to gc */
00533 #define NODE_HEREDOC NODE_ARRAY         /* 1, 3 to gc */
00534 #define SIGN_EXTEND(x,n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
00535 #define nd_func u1.id
00536 #if SIZEOF_SHORT == 2
00537 #define nd_term(node) ((signed short)(node)->u2.id)
00538 #else
00539 #define nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
00540 #endif
00541 #define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
00542 #define nd_nest u3.cnt
00543 
00544 /****** Ripper *******/
00545 
00546 #ifdef RIPPER
00547 #define RIPPER_VERSION "0.1.0"
00548 
00549 #include "eventids1.c"
00550 #include "eventids2.c"
00551 
00552 static VALUE ripper_dispatch0(struct parser_params*,ID);
00553 static VALUE ripper_dispatch1(struct parser_params*,ID,VALUE);
00554 static VALUE ripper_dispatch2(struct parser_params*,ID,VALUE,VALUE);
00555 static VALUE ripper_dispatch3(struct parser_params*,ID,VALUE,VALUE,VALUE);
00556 static VALUE ripper_dispatch4(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE);
00557 static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE);
00558 static VALUE ripper_dispatch7(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE);
00559 
00560 #define dispatch0(n)            ripper_dispatch0(parser, TOKEN_PASTE(ripper_id_, n))
00561 #define dispatch1(n,a)          ripper_dispatch1(parser, TOKEN_PASTE(ripper_id_, n), (a))
00562 #define dispatch2(n,a,b)        ripper_dispatch2(parser, TOKEN_PASTE(ripper_id_, n), (a), (b))
00563 #define dispatch3(n,a,b,c)      ripper_dispatch3(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c))
00564 #define dispatch4(n,a,b,c,d)    ripper_dispatch4(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d))
00565 #define dispatch5(n,a,b,c,d,e)  ripper_dispatch5(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e))
00566 #define dispatch7(n,a,b,c,d,e,f,g) ripper_dispatch7(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e), (f), (g))
00567 
00568 #define yyparse ripper_yyparse
00569 
00570 #define ripper_intern(s) ID2SYM(rb_intern(s))
00571 static VALUE ripper_id2sym(ID);
00572 #ifdef __GNUC__
00573 #define ripper_id2sym(id) ((id) < 256 && rb_ispunct(id) ? \
00574                            ID2SYM(id) : ripper_id2sym(id))
00575 #endif
00576 
00577 #define arg_new() dispatch0(args_new)
00578 #define arg_add(l,a) dispatch2(args_add, (l), (a))
00579 #define arg_add_star(l,a) dispatch2(args_add_star, (l), (a))
00580 #define arg_add_block(l,b) dispatch2(args_add_block, (l), (b))
00581 #define arg_add_optblock(l,b) ((b)==Qundef? (l) : dispatch2(args_add_block, (l), (b)))
00582 #define bare_assoc(v) dispatch1(bare_assoc_hash, (v))
00583 #define arg_add_assocs(l,b) arg_add((l), bare_assoc(b))
00584 
00585 #define args2mrhs(a) dispatch1(mrhs_new_from_args, (a))
00586 #define mrhs_new() dispatch0(mrhs_new)
00587 #define mrhs_add(l,a) dispatch2(mrhs_add, (l), (a))
00588 #define mrhs_add_star(l,a) dispatch2(mrhs_add_star, (l), (a))
00589 
00590 #define mlhs_new() dispatch0(mlhs_new)
00591 #define mlhs_add(l,a) dispatch2(mlhs_add, (l), (a))
00592 #define mlhs_add_star(l,a) dispatch2(mlhs_add_star, (l), (a))
00593 
00594 #define params_new(pars, opts, rest, pars2, kws, kwrest, blk) \
00595         dispatch7(params, (pars), (opts), (rest), (pars2), (kws), (kwrest), (blk))
00596 
00597 #define blockvar_new(p,v) dispatch2(block_var, (p), (v))
00598 #define blockvar_add_star(l,a) dispatch2(block_var_add_star, (l), (a))
00599 #define blockvar_add_block(l,a) dispatch2(block_var_add_block, (l), (a))
00600 
00601 #define method_optarg(m,a) ((a)==Qundef ? (m) : dispatch2(method_add_arg,(m),(a)))
00602 #define method_arg(m,a) dispatch2(method_add_arg,(m),(a))
00603 #define method_add_block(m,b) dispatch2(method_add_block, (m), (b))
00604 
00605 #define escape_Qundef(x) ((x)==Qundef ? Qnil : (x))
00606 
00607 static inline VALUE
00608 new_args_gen(struct parser_params *parser, VALUE f, VALUE o, VALUE r, VALUE p, VALUE tail)
00609 {
00610     NODE *t = (NODE *)tail;
00611     VALUE k = t->u1.value, kr = t->u2.value, b = t->u3.value;
00612     return params_new(f, o, r, p, k, kr, escape_Qundef(b));
00613 }
00614 #define new_args(f,o,r,p,t) new_args_gen(parser, (f),(o),(r),(p),(t))
00615 
00616 static inline VALUE
00617 new_args_tail_gen(struct parser_params *parser, VALUE k, VALUE kr, VALUE b)
00618 {
00619     return (VALUE)rb_node_newnode(NODE_MEMO, k, kr, b);
00620 }
00621 #define new_args_tail(k,kr,b) new_args_tail_gen(parser, (k),(kr),(b))
00622 
00623 #define FIXME 0
00624 
00625 #endif /* RIPPER */
00626 
00627 #ifndef RIPPER
00628 # define Qnone 0
00629 # define ifndef_ripper(x) (x)
00630 #else
00631 # define Qnone Qnil
00632 # define ifndef_ripper(x)
00633 #endif
00634 
00635 #ifndef RIPPER
00636 # define rb_warn0(fmt)    rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))
00637 # define rb_warnI(fmt,a)  rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00638 # define rb_warnS(fmt,a)  rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00639 # define rb_warn4S(file,line,fmt,a)  rb_compile_warn((file), (line), (fmt), (a))
00640 # define rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))
00641 # define rb_warningS(fmt,a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00642 #else
00643 # define rb_warn0(fmt)    ripper_warn0(parser, (fmt))
00644 # define rb_warnI(fmt,a)  ripper_warnI(parser, (fmt), (a))
00645 # define rb_warnS(fmt,a)  ripper_warnS(parser, (fmt), (a))
00646 # define rb_warn4S(file,line,fmt,a)  ripper_warnS(parser, (fmt), (a))
00647 # define rb_warning0(fmt) ripper_warning0(parser, (fmt))
00648 # define rb_warningS(fmt,a) ripper_warningS(parser, (fmt), (a))
00649 static void ripper_warn0(struct parser_params*, const char*);
00650 static void ripper_warnI(struct parser_params*, const char*, int);
00651 static void ripper_warnS(struct parser_params*, const char*, const char*);
00652 static void ripper_warning0(struct parser_params*, const char*);
00653 static void ripper_warningS(struct parser_params*, const char*, const char*);
00654 #endif
00655 
00656 #ifdef RIPPER
00657 static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
00658 # define rb_compile_error ripper_compile_error
00659 # define compile_error ripper_compile_error
00660 # define PARSER_ARG parser,
00661 #else
00662 # define rb_compile_error rb_compile_error_with_enc
00663 # define compile_error parser->nerr++,rb_compile_error_with_enc
00664 # define PARSER_ARG ruby_sourcefile, ruby_sourceline, current_enc,
00665 #endif
00666 
00667 /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
00668    for instance).  This is too low for Ruby to parse some files, such as
00669    date/format.rb, therefore bump the value up to at least Bison's default. */
00670 #ifdef OLD_YACC
00671 #ifndef YYMAXDEPTH
00672 #define YYMAXDEPTH 10000
00673 #endif
00674 #endif
00675 
00676 #ifndef RIPPER
00677 static void token_info_push(struct parser_params*, const char *token);
00678 static void token_info_pop(struct parser_params*, const char *token);
00679 #define token_info_push(token) (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)
00680 #define token_info_pop(token) (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)
00681 #else
00682 #define token_info_push(token) /* nothing */
00683 #define token_info_pop(token) /* nothing */
00684 #endif
00685 %}
00686 
00687 %pure-parser
00688 %lex-param {struct parser_params *parser}
00689 %parse-param {struct parser_params *parser}
00690 
00691 %union {
00692     VALUE val;
00693     NODE *node;
00694     ID id;
00695     int num;
00696     const struct vtable *vars;
00697 }
00698 
00699 /*%%%*/
00700 %token
00701 /*%
00702 %token <val>
00703 %*/
00704         keyword_class
00705         keyword_module
00706         keyword_def
00707         keyword_undef
00708         keyword_begin
00709         keyword_rescue
00710         keyword_ensure
00711         keyword_end
00712         keyword_if
00713         keyword_unless
00714         keyword_then
00715         keyword_elsif
00716         keyword_else
00717         keyword_case
00718         keyword_when
00719         keyword_while
00720         keyword_until
00721         keyword_for
00722         keyword_break
00723         keyword_next
00724         keyword_redo
00725         keyword_retry
00726         keyword_in
00727         keyword_do
00728         keyword_do_cond
00729         keyword_do_block
00730         keyword_do_LAMBDA
00731         keyword_return
00732         keyword_yield
00733         keyword_super
00734         keyword_self
00735         keyword_nil
00736         keyword_true
00737         keyword_false
00738         keyword_and
00739         keyword_or
00740         keyword_not
00741         modifier_if
00742         modifier_unless
00743         modifier_while
00744         modifier_until
00745         modifier_rescue
00746         keyword_alias
00747         keyword_defined
00748         keyword_BEGIN
00749         keyword_END
00750         keyword__LINE__
00751         keyword__FILE__
00752         keyword__ENCODING__
00753 
00754 %token <id>   tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
00755 %token <node> tINTEGER tFLOAT tSTRING_CONTENT tCHAR
00756 %token <node> tNTH_REF tBACK_REF
00757 %token <num>  tREGEXP_END
00758 
00759 %type <node> singleton strings string string1 xstring regexp
00760 %type <node> string_contents xstring_contents regexp_contents string_content
00761 %type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
00762 %type <node> literal numeric dsym cpath
00763 %type <node> top_compstmt top_stmts top_stmt
00764 %type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
00765 %type <node> expr_value arg_value primary_value fcall
00766 %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
00767 %type <node> args call_args opt_call_args
00768 %type <node> paren_args opt_paren_args args_tail opt_args_tail block_args_tail opt_block_args_tail
00769 %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
00770 %type <node> command_asgn mrhs superclass block_call block_command
00771 %type <node> f_block_optarg f_block_opt
00772 %type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
00773 %type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
00774 %type <node> block_param opt_block_param block_param_def f_opt
00775 %type <node> f_kwarg f_kw f_block_kwarg f_block_kw
00776 %type <node> bv_decls opt_bv_decl bvar
00777 %type <node> lambda f_larglist lambda_body
00778 %type <node> brace_block cmd_brace_block do_block lhs none fitem
00779 %type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
00780 %type <id>   fsym keyword_variable user_variable sym symbol operation operation2 operation3
00781 %type <id>   cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
00782 %type <id>   f_kwrest
00783 /*%%%*/
00784 /*%
00785 %type <val> program reswords then do dot_or_colon
00786 %*/
00787 %token END_OF_INPUT 0   "end-of-input"
00788 %token tUPLUS           RUBY_TOKEN(UPLUS)  "unary+"
00789 %token tUMINUS          RUBY_TOKEN(UMINUS) "unary-"
00790 %token tPOW             RUBY_TOKEN(POW)    "**"
00791 %token tCMP             RUBY_TOKEN(CMP)    "<=>"
00792 %token tEQ              RUBY_TOKEN(EQ)     "=="
00793 %token tEQQ             RUBY_TOKEN(EQQ)    "==="
00794 %token tNEQ             RUBY_TOKEN(NEQ)    "!="
00795 %token tGEQ             RUBY_TOKEN(GEQ)    ">="
00796 %token tLEQ             RUBY_TOKEN(LEQ)    "<="
00797 %token tANDOP           "&&"
00798 %token tOROP            "||"
00799 %token tMATCH           RUBY_TOKEN(MATCH)  "=~"
00800 %token tNMATCH          RUBY_TOKEN(NMATCH) "!~"
00801 %token tDOT2            RUBY_TOKEN(DOT2)   ".."
00802 %token tDOT3            RUBY_TOKEN(DOT3)   "..."
00803 %token tAREF            RUBY_TOKEN(AREF)   "[]"
00804 %token tASET            RUBY_TOKEN(ASET)   "[]="
00805 %token tLSHFT           RUBY_TOKEN(LSHFT)  "<<"
00806 %token tRSHFT           RUBY_TOKEN(RSHFT)  ">>"
00807 %token tCOLON2          "::"
00808 %token tCOLON3          ":: at EXPR_BEG"
00809 %token <id> tOP_ASGN    /* +=, -=  etc. */
00810 %token tASSOC           "=>"
00811 %token tLPAREN          "("
00812 %token tLPAREN_ARG      "( arg"
00813 %token tRPAREN          ")"
00814 %token tLBRACK          "["
00815 %token tLBRACE          "{"
00816 %token tLBRACE_ARG      "{ arg"
00817 %token tSTAR            "*"
00818 %token tDSTAR           "**arg"
00819 %token tAMPER           "&"
00820 %token tLAMBDA          "->"
00821 %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG
00822 %token tSTRING_DBEG tSTRING_DEND tSTRING_DVAR tSTRING_END tLAMBEG
00823 
00824 /*
00825  *      precedence table
00826  */
00827 
00828 %nonassoc tLOWEST
00829 %nonassoc tLBRACE_ARG
00830 
00831 %nonassoc  modifier_if modifier_unless modifier_while modifier_until
00832 %left  keyword_or keyword_and
00833 %right keyword_not
00834 %nonassoc keyword_defined
00835 %right '=' tOP_ASGN
00836 %left modifier_rescue
00837 %right '?' ':'
00838 %nonassoc tDOT2 tDOT3
00839 %left  tOROP
00840 %left  tANDOP
00841 %nonassoc  tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
00842 %left  '>' tGEQ '<' tLEQ
00843 %left  '|' '^'
00844 %left  '&'
00845 %left  tLSHFT tRSHFT
00846 %left  '+' '-'
00847 %left  '*' '/' '%'
00848 %right tUMINUS_NUM tUMINUS
00849 %right tPOW
00850 %right '!' '~' tUPLUS
00851 
00852 %token tLAST_TOKEN
00853 
00854 %%
00855 program         :  {
00856                         lex_state = EXPR_BEG;
00857                     /*%%%*/
00858                         local_push(compile_for_eval || rb_parse_in_main());
00859                     /*%
00860                         local_push(0);
00861                     %*/
00862                     }
00863                   top_compstmt
00864                     {
00865                     /*%%%*/
00866                         if ($2 && !compile_for_eval) {
00867                             /* last expression should not be void */
00868                             if (nd_type($2) != NODE_BLOCK) void_expr($2);
00869                             else {
00870                                 NODE *node = $2;
00871                                 while (node->nd_next) {
00872                                     node = node->nd_next;
00873                                 }
00874                                 void_expr(node->nd_head);
00875                             }
00876                         }
00877                         ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2));
00878                     /*%
00879                         $$ = $2;
00880                         parser->result = dispatch1(program, $$);
00881                     %*/
00882                         local_pop();
00883                     }
00884                 ;
00885 
00886 top_compstmt    : top_stmts opt_terms
00887                     {
00888                     /*%%%*/
00889                         void_stmts($1);
00890                         fixup_nodes(&deferred_nodes);
00891                     /*%
00892                     %*/
00893                         $$ = $1;
00894                     }
00895                 ;
00896 
00897 top_stmts       : none
00898                     {
00899                     /*%%%*/
00900                         $$ = NEW_BEGIN(0);
00901                     /*%
00902                         $$ = dispatch2(stmts_add, dispatch0(stmts_new),
00903                                                   dispatch0(void_stmt));
00904                     %*/
00905                     }
00906                 | top_stmt
00907                     {
00908                     /*%%%*/
00909                         $$ = newline_node($1);
00910                     /*%
00911                         $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
00912                     %*/
00913                     }
00914                 | top_stmts terms top_stmt
00915                     {
00916                     /*%%%*/
00917                         $$ = block_append($1, newline_node($3));
00918                     /*%
00919                         $$ = dispatch2(stmts_add, $1, $3);
00920                     %*/
00921                     }
00922                 | error top_stmt
00923                     {
00924                         $$ = remove_begin($2);
00925                     }
00926                 ;
00927 
00928 top_stmt        : stmt
00929                 | keyword_BEGIN
00930                     {
00931                     /*%%%*/
00932                         /* local_push(0); */
00933                     /*%
00934                     %*/
00935                     }
00936                   '{' top_compstmt '}'
00937                     {
00938                     /*%%%*/
00939                         ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
00940                                                             $4);
00941                         /* NEW_PREEXE($4)); */
00942                         /* local_pop(); */
00943                         $$ = NEW_BEGIN(0);
00944                     /*%
00945                         $$ = dispatch1(BEGIN, $4);
00946                     %*/
00947                     }
00948                 ;
00949 
00950 bodystmt        : compstmt
00951                   opt_rescue
00952                   opt_else
00953                   opt_ensure
00954                     {
00955                     /*%%%*/
00956                         $$ = $1;
00957                         if ($2) {
00958                             $$ = NEW_RESCUE($1, $2, $3);
00959                         }
00960                         else if ($3) {
00961                             rb_warn0("else without rescue is useless");
00962                             $$ = block_append($$, $3);
00963                         }
00964                         if ($4) {
00965                             if ($$) {
00966                                 $$ = NEW_ENSURE($$, $4);
00967                             }
00968                             else {
00969                                 $$ = block_append($4, NEW_NIL());
00970                             }
00971                         }
00972                         fixpos($$, $1);
00973                     /*%
00974                         $$ = dispatch4(bodystmt,
00975                                        escape_Qundef($1),
00976                                        escape_Qundef($2),
00977                                        escape_Qundef($3),
00978                                        escape_Qundef($4));
00979                     %*/
00980                     }
00981                 ;
00982 
00983 compstmt        : stmts opt_terms
00984                     {
00985                     /*%%%*/
00986                         void_stmts($1);
00987                         fixup_nodes(&deferred_nodes);
00988                     /*%
00989                     %*/
00990                         $$ = $1;
00991                     }
00992                 ;
00993 
00994 stmts           : none
00995                     {
00996                     /*%%%*/
00997                         $$ = NEW_BEGIN(0);
00998                     /*%
00999                         $$ = dispatch2(stmts_add, dispatch0(stmts_new),
01000                                                   dispatch0(void_stmt));
01001                     %*/
01002                     }
01003                 | stmt_or_begin
01004                     {
01005                     /*%%%*/
01006                         $$ = newline_node($1);
01007                     /*%
01008                         $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
01009                     %*/
01010                     }
01011                 | stmts terms stmt_or_begin
01012                     {
01013                     /*%%%*/
01014                         $$ = block_append($1, newline_node($3));
01015                     /*%
01016                         $$ = dispatch2(stmts_add, $1, $3);
01017                     %*/
01018                     }
01019                 | error stmt
01020                     {
01021                         $$ = remove_begin($2);
01022                     }
01023                 ;
01024 
01025 stmt_or_begin   : stmt
01026                     {
01027                         $$ = $1;
01028                     }
01029                 | keyword_BEGIN
01030                     {
01031                         yyerror("BEGIN is permitted only at toplevel");
01032                     /*%%%*/
01033                         /* local_push(0); */
01034                     /*%
01035                     %*/
01036                     }
01037                   '{' top_compstmt '}'
01038                     {
01039                     /*%%%*/
01040                         ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
01041                                                             $4);
01042                         /* NEW_PREEXE($4)); */
01043                         /* local_pop(); */
01044                         $$ = NEW_BEGIN(0);
01045                     /*%
01046                         $$ = dispatch1(BEGIN, $4);
01047                     %*/
01048                     }
01049 
01050 stmt            : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
01051                     {
01052                     /*%%%*/
01053                         $$ = NEW_ALIAS($2, $4);
01054                     /*%
01055                         $$ = dispatch2(alias, $2, $4);
01056                     %*/
01057                     }
01058                 | keyword_alias tGVAR tGVAR
01059                     {
01060                     /*%%%*/
01061                         $$ = NEW_VALIAS($2, $3);
01062                     /*%
01063                         $$ = dispatch2(var_alias, $2, $3);
01064                     %*/
01065                     }
01066                 | keyword_alias tGVAR tBACK_REF
01067                     {
01068                     /*%%%*/
01069                         char buf[2];
01070                         buf[0] = '$';
01071                         buf[1] = (char)$3->nd_nth;
01072                         $$ = NEW_VALIAS($2, rb_intern2(buf, 2));
01073                     /*%
01074                         $$ = dispatch2(var_alias, $2, $3);
01075                     %*/
01076                     }
01077                 | keyword_alias tGVAR tNTH_REF
01078                     {
01079                     /*%%%*/
01080                         yyerror("can't make alias for the number variables");
01081                         $$ = NEW_BEGIN(0);
01082                     /*%
01083                         $$ = dispatch2(var_alias, $2, $3);
01084                         $$ = dispatch1(alias_error, $$);
01085                     %*/
01086                     }
01087                 | keyword_undef undef_list
01088                     {
01089                     /*%%%*/
01090                         $$ = $2;
01091                     /*%
01092                         $$ = dispatch1(undef, $2);
01093                     %*/
01094                     }
01095                 | stmt modifier_if expr_value
01096                     {
01097                     /*%%%*/
01098                         $$ = NEW_IF(cond($3), remove_begin($1), 0);
01099                         fixpos($$, $3);
01100                     /*%
01101                         $$ = dispatch2(if_mod, $3, $1);
01102                     %*/
01103                     }
01104                 | stmt modifier_unless expr_value
01105                     {
01106                     /*%%%*/
01107                         $$ = NEW_UNLESS(cond($3), remove_begin($1), 0);
01108                         fixpos($$, $3);
01109                     /*%
01110                         $$ = dispatch2(unless_mod, $3, $1);
01111                     %*/
01112                     }
01113                 | stmt modifier_while expr_value
01114                     {
01115                     /*%%%*/
01116                         if ($1 && nd_type($1) == NODE_BEGIN) {
01117                             $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
01118                         }
01119                         else {
01120                             $$ = NEW_WHILE(cond($3), $1, 1);
01121                         }
01122                     /*%
01123                         $$ = dispatch2(while_mod, $3, $1);
01124                     %*/
01125                     }
01126                 | stmt modifier_until expr_value
01127                     {
01128                     /*%%%*/
01129                         if ($1 && nd_type($1) == NODE_BEGIN) {
01130                             $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
01131                         }
01132                         else {
01133                             $$ = NEW_UNTIL(cond($3), $1, 1);
01134                         }
01135                     /*%
01136                         $$ = dispatch2(until_mod, $3, $1);
01137                     %*/
01138                     }
01139                 | stmt modifier_rescue stmt
01140                     {
01141                     /*%%%*/
01142                         NODE *resq = NEW_RESBODY(0, remove_begin($3), 0);
01143                         $$ = NEW_RESCUE(remove_begin($1), resq, 0);
01144                     /*%
01145                         $$ = dispatch2(rescue_mod, $1, $3);
01146                     %*/
01147                     }
01148                 | keyword_END '{' compstmt '}'
01149                     {
01150                         if (in_def || in_single) {
01151                             rb_warn0("END in method; use at_exit");
01152                         }
01153                     /*%%%*/
01154                         $$ = NEW_POSTEXE(NEW_NODE(
01155                             NODE_SCOPE, 0 /* tbl */, $3 /* body */, 0 /* args */));
01156                     /*%
01157                         $$ = dispatch1(END, $3);
01158                     %*/
01159                     }
01160                 | command_asgn
01161                 | mlhs '=' command_call
01162                     {
01163                     /*%%%*/
01164                         value_expr($3);
01165                         $1->nd_value = $3;
01166                         $$ = $1;
01167                     /*%
01168                         $$ = dispatch2(massign, $1, $3);
01169                     %*/
01170                     }
01171                 | var_lhs tOP_ASGN command_call
01172                     {
01173                         value_expr($3);
01174                         $$ = new_op_assign($1, $2, $3);
01175                     }
01176                 | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
01177                     {
01178                     /*%%%*/
01179                         NODE *args;
01180 
01181                         value_expr($6);
01182                         if (!$3) $3 = NEW_ZARRAY();
01183                         args = arg_concat($3, $6);
01184                         if ($5 == tOROP) {
01185                             $5 = 0;
01186                         }
01187                         else if ($5 == tANDOP) {
01188                             $5 = 1;
01189                         }
01190                         $$ = NEW_OP_ASGN1($1, $5, args);
01191                         fixpos($$, $1);
01192                     /*%
01193                         $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01194                         $$ = dispatch3(opassign, $$, $5, $6);
01195                     %*/
01196                     }
01197                 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
01198                     {
01199                         value_expr($5);
01200                         $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);
01201                     }
01202                 | primary_value '.' tCONSTANT tOP_ASGN command_call
01203                     {
01204                         value_expr($5);
01205                         $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);
01206                     }
01207                 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
01208                     {
01209                     /*%%%*/
01210                         $$ = NEW_COLON2($1, $3);
01211                         $$ = new_const_op_assign($$, $4, $5);
01212                     /*%
01213                         $$ = dispatch2(const_path_field, $1, $3);
01214                         $$ = dispatch3(opassign, $$, $4, $5);
01215                     %*/
01216                     }
01217                 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
01218                     {
01219                         value_expr($5);
01220                         $$ = new_attr_op_assign($1, ripper_intern("::"), $3, $4, $5);
01221                     }
01222                 | backref tOP_ASGN command_call
01223                     {
01224                     /*%%%*/
01225                         rb_backref_error($1);
01226                         $$ = NEW_BEGIN(0);
01227                     /*%
01228                         $$ = dispatch2(assign, dispatch1(var_field, $1), $3);
01229                         $$ = dispatch1(assign_error, $$);
01230                     %*/
01231                     }
01232                 | lhs '=' mrhs
01233                     {
01234                     /*%%%*/
01235                         value_expr($3);
01236                         $$ = node_assign($1, $3);
01237                     /*%
01238                         $$ = dispatch2(assign, $1, $3);
01239                     %*/
01240                     }
01241                 | mlhs '=' arg_value
01242                     {
01243                     /*%%%*/
01244                         $1->nd_value = $3;
01245                         $$ = $1;
01246                     /*%
01247                         $$ = dispatch2(massign, $1, $3);
01248                     %*/
01249                     }
01250                 | mlhs '=' mrhs
01251                     {
01252                     /*%%%*/
01253                         $1->nd_value = $3;
01254                         $$ = $1;
01255                     /*%
01256                         $$ = dispatch2(massign, $1, $3);
01257                     %*/
01258                     }
01259                 | expr
01260                 ;
01261 
01262 command_asgn    : lhs '=' command_call
01263                     {
01264                     /*%%%*/
01265                         value_expr($3);
01266                         $$ = node_assign($1, $3);
01267                     /*%
01268                         $$ = dispatch2(assign, $1, $3);
01269                     %*/
01270                     }
01271                 | lhs '=' command_asgn
01272                     {
01273                     /*%%%*/
01274                         value_expr($3);
01275                         $$ = node_assign($1, $3);
01276                     /*%
01277                         $$ = dispatch2(assign, $1, $3);
01278                     %*/
01279                     }
01280                 ;
01281 
01282 
01283 expr            : command_call
01284                 | expr keyword_and expr
01285                     {
01286                     /*%%%*/
01287                         $$ = logop(NODE_AND, $1, $3);
01288                     /*%
01289                         $$ = dispatch3(binary, $1, ripper_intern("and"), $3);
01290                     %*/
01291                     }
01292                 | expr keyword_or expr
01293                     {
01294                     /*%%%*/
01295                         $$ = logop(NODE_OR, $1, $3);
01296                     /*%
01297                         $$ = dispatch3(binary, $1, ripper_intern("or"), $3);
01298                     %*/
01299                     }
01300                 | keyword_not opt_nl expr
01301                     {
01302                     /*%%%*/
01303                         $$ = call_uni_op(cond($3), '!');
01304                     /*%
01305                         $$ = dispatch2(unary, ripper_intern("not"), $3);
01306                     %*/
01307                     }
01308                 | '!' command_call
01309                     {
01310                     /*%%%*/
01311                         $$ = call_uni_op(cond($2), '!');
01312                     /*%
01313                         $$ = dispatch2(unary, ripper_id2sym('!'), $2);
01314                     %*/
01315                     }
01316                 | arg
01317                 ;
01318 
01319 expr_value      : expr
01320                     {
01321                     /*%%%*/
01322                         value_expr($1);
01323                         $$ = $1;
01324                         if (!$$) $$ = NEW_NIL();
01325                     /*%
01326                         $$ = $1;
01327                     %*/
01328                     }
01329                 ;
01330 
01331 command_call    : command
01332                 | block_command
01333                 ;
01334 
01335 block_command   : block_call
01336                 | block_call dot_or_colon operation2 command_args
01337                     {
01338                     /*%%%*/
01339                         $$ = NEW_CALL($1, $3, $4);
01340                     /*%
01341                         $$ = dispatch3(call, $1, $2, $3);
01342                         $$ = method_arg($$, $4);
01343                     %*/
01344                     }
01345                 ;
01346 
01347 cmd_brace_block : tLBRACE_ARG
01348                     {
01349                         $<vars>1 = dyna_push();
01350                     /*%%%*/
01351                         $<num>$ = ruby_sourceline;
01352                     /*%
01353                     %*/
01354                     }
01355                   opt_block_param
01356                   compstmt
01357                   '}'
01358                     {
01359                     /*%%%*/
01360                         $$ = NEW_ITER($3,$4);
01361                         nd_set_line($$, $<num>2);
01362                     /*%
01363                         $$ = dispatch2(brace_block, escape_Qundef($3), $4);
01364                     %*/
01365                         dyna_pop($<vars>1);
01366                     }
01367                 ;
01368 
01369 fcall           : operation
01370                     {
01371                     /*%%%*/
01372                         $$ = NEW_FCALL($1, 0);
01373                         nd_set_line($$, tokline);
01374                     /*%
01375                     %*/
01376                     }
01377                 ;
01378 
01379 command         : fcall command_args       %prec tLOWEST
01380                     {
01381                     /*%%%*/
01382                         $$ = $1;
01383                         $$->nd_args = $2;
01384                     /*%
01385                         $$ = dispatch2(command, $1, $2);
01386                     %*/
01387                     }
01388                 | fcall command_args cmd_brace_block
01389                     {
01390                     /*%%%*/
01391                         block_dup_check($2,$3);
01392                         $1->nd_args = $2;
01393                         $3->nd_iter = $1;
01394                         $$ = $3;
01395                         fixpos($$, $1);
01396                     /*%
01397                         $$ = dispatch2(command, $1, $2);
01398                         $$ = method_add_block($$, $3);
01399                     %*/
01400                     }
01401                 | primary_value '.' operation2 command_args     %prec tLOWEST
01402                     {
01403                     /*%%%*/
01404                         $$ = NEW_CALL($1, $3, $4);
01405                         fixpos($$, $1);
01406                     /*%
01407                         $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01408                     %*/
01409                     }
01410                 | primary_value '.' operation2 command_args cmd_brace_block
01411                     {
01412                     /*%%%*/
01413                         block_dup_check($4,$5);
01414                         $5->nd_iter = NEW_CALL($1, $3, $4);
01415                         $$ = $5;
01416                         fixpos($$, $1);
01417                     /*%
01418                         $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01419                         $$ = method_add_block($$, $5);
01420                     %*/
01421                    }
01422                 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
01423                     {
01424                     /*%%%*/
01425                         $$ = NEW_CALL($1, $3, $4);
01426                         fixpos($$, $1);
01427                     /*%
01428                         $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01429                     %*/
01430                     }
01431                 | primary_value tCOLON2 operation2 command_args cmd_brace_block
01432                     {
01433                     /*%%%*/
01434                         block_dup_check($4,$5);
01435                         $5->nd_iter = NEW_CALL($1, $3, $4);
01436                         $$ = $5;
01437                         fixpos($$, $1);
01438                     /*%
01439                         $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01440                         $$ = method_add_block($$, $5);
01441                     %*/
01442                    }
01443                 | keyword_super command_args
01444                     {
01445                     /*%%%*/
01446                         $$ = NEW_SUPER($2);
01447                         fixpos($$, $2);
01448                     /*%
01449                         $$ = dispatch1(super, $2);
01450                     %*/
01451                     }
01452                 | keyword_yield command_args
01453                     {
01454                     /*%%%*/
01455                         $$ = new_yield($2);
01456                         fixpos($$, $2);
01457                     /*%
01458                         $$ = dispatch1(yield, $2);
01459                     %*/
01460                     }
01461                 | keyword_return call_args
01462                     {
01463                     /*%%%*/
01464                         $$ = NEW_RETURN(ret_args($2));
01465                     /*%
01466                         $$ = dispatch1(return, $2);
01467                     %*/
01468                     }
01469                 | keyword_break call_args
01470                     {
01471                     /*%%%*/
01472                         $$ = NEW_BREAK(ret_args($2));
01473                     /*%
01474                         $$ = dispatch1(break, $2);
01475                     %*/
01476                     }
01477                 | keyword_next call_args
01478                     {
01479                     /*%%%*/
01480                         $$ = NEW_NEXT(ret_args($2));
01481                     /*%
01482                         $$ = dispatch1(next, $2);
01483                     %*/
01484                     }
01485                 ;
01486 
01487 mlhs            : mlhs_basic
01488                 | tLPAREN mlhs_inner rparen
01489                     {
01490                     /*%%%*/
01491                         $$ = $2;
01492                     /*%
01493                         $$ = dispatch1(mlhs_paren, $2);
01494                     %*/
01495                     }
01496                 ;
01497 
01498 mlhs_inner      : mlhs_basic
01499                 | tLPAREN mlhs_inner rparen
01500                     {
01501                     /*%%%*/
01502                         $$ = NEW_MASGN(NEW_LIST($2), 0);
01503                     /*%
01504                         $$ = dispatch1(mlhs_paren, $2);
01505                     %*/
01506                     }
01507                 ;
01508 
01509 mlhs_basic      : mlhs_head
01510                     {
01511                     /*%%%*/
01512                         $$ = NEW_MASGN($1, 0);
01513                     /*%
01514                         $$ = $1;
01515                     %*/
01516                     }
01517                 | mlhs_head mlhs_item
01518                     {
01519                     /*%%%*/
01520                         $$ = NEW_MASGN(list_append($1,$2), 0);
01521                     /*%
01522                         $$ = mlhs_add($1, $2);
01523                     %*/
01524                     }
01525                 | mlhs_head tSTAR mlhs_node
01526                     {
01527                     /*%%%*/
01528                         $$ = NEW_MASGN($1, $3);
01529                     /*%
01530                         $$ = mlhs_add_star($1, $3);
01531                     %*/
01532                     }
01533                 | mlhs_head tSTAR mlhs_node ',' mlhs_post
01534                     {
01535                     /*%%%*/
01536                         $$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
01537                     /*%
01538                         $1 = mlhs_add_star($1, $3);
01539                         $$ = mlhs_add($1, $5);
01540                     %*/
01541                     }
01542                 | mlhs_head tSTAR
01543                     {
01544                     /*%%%*/
01545                         $$ = NEW_MASGN($1, -1);
01546                     /*%
01547                         $$ = mlhs_add_star($1, Qnil);
01548                     %*/
01549                     }
01550                 | mlhs_head tSTAR ',' mlhs_post
01551                     {
01552                     /*%%%*/
01553                         $$ = NEW_MASGN($1, NEW_POSTARG(-1, $4));
01554                     /*%
01555                         $1 = mlhs_add_star($1, Qnil);
01556                         $$ = mlhs_add($1, $4);
01557                     %*/
01558                     }
01559                 | tSTAR mlhs_node
01560                     {
01561                     /*%%%*/
01562                         $$ = NEW_MASGN(0, $2);
01563                     /*%
01564                         $$ = mlhs_add_star(mlhs_new(), $2);
01565                     %*/
01566                     }
01567                 | tSTAR mlhs_node ',' mlhs_post
01568                     {
01569                     /*%%%*/
01570                         $$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
01571                     /*%
01572                         $2 = mlhs_add_star(mlhs_new(), $2);
01573                         $$ = mlhs_add($2, $4);
01574                     %*/
01575                     }
01576                 | tSTAR
01577                     {
01578                     /*%%%*/
01579                         $$ = NEW_MASGN(0, -1);
01580                     /*%
01581                         $$ = mlhs_add_star(mlhs_new(), Qnil);
01582                     %*/
01583                     }
01584                 | tSTAR ',' mlhs_post
01585                     {
01586                     /*%%%*/
01587                         $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
01588                     /*%
01589                         $$ = mlhs_add_star(mlhs_new(), Qnil);
01590                         $$ = mlhs_add($$, $3);
01591                     %*/
01592                     }
01593                 ;
01594 
01595 mlhs_item       : mlhs_node
01596                 | tLPAREN mlhs_inner rparen
01597                     {
01598                     /*%%%*/
01599                         $$ = $2;
01600                     /*%
01601                         $$ = dispatch1(mlhs_paren, $2);
01602                     %*/
01603                     }
01604                 ;
01605 
01606 mlhs_head       : mlhs_item ','
01607                     {
01608                     /*%%%*/
01609                         $$ = NEW_LIST($1);
01610                     /*%
01611                         $$ = mlhs_add(mlhs_new(), $1);
01612                     %*/
01613                     }
01614                 | mlhs_head mlhs_item ','
01615                     {
01616                     /*%%%*/
01617                         $$ = list_append($1, $2);
01618                     /*%
01619                         $$ = mlhs_add($1, $2);
01620                     %*/
01621                     }
01622                 ;
01623 
01624 mlhs_post       : mlhs_item
01625                     {
01626                     /*%%%*/
01627                         $$ = NEW_LIST($1);
01628                     /*%
01629                         $$ = mlhs_add(mlhs_new(), $1);
01630                     %*/
01631                     }
01632                 | mlhs_post ',' mlhs_item
01633                     {
01634                     /*%%%*/
01635                         $$ = list_append($1, $3);
01636                     /*%
01637                         $$ = mlhs_add($1, $3);
01638                     %*/
01639                     }
01640                 ;
01641 
01642 mlhs_node       : user_variable
01643                     {
01644                         $$ = assignable($1, 0);
01645                     }
01646                 | keyword_variable
01647                     {
01648                         $$ = assignable($1, 0);
01649                     }
01650                 | primary_value '[' opt_call_args rbracket
01651                     {
01652                     /*%%%*/
01653                         $$ = aryset($1, $3);
01654                     /*%
01655                         $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01656                     %*/
01657                     }
01658                 | primary_value '.' tIDENTIFIER
01659                     {
01660                     /*%%%*/
01661                         $$ = attrset($1, $3);
01662                     /*%
01663                         $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01664                     %*/
01665                     }
01666                 | primary_value tCOLON2 tIDENTIFIER
01667                     {
01668                     /*%%%*/
01669                         $$ = attrset($1, $3);
01670                     /*%
01671                         $$ = dispatch2(const_path_field, $1, $3);
01672                     %*/
01673                     }
01674                 | primary_value '.' tCONSTANT
01675                     {
01676                     /*%%%*/
01677                         $$ = attrset($1, $3);
01678                     /*%
01679                         $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01680                     %*/
01681                     }
01682                 | primary_value tCOLON2 tCONSTANT
01683                     {
01684                     /*%%%*/
01685                         if (in_def || in_single)
01686                             yyerror("dynamic constant assignment");
01687                         $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01688                     /*%
01689                         if (in_def || in_single)
01690                             yyerror("dynamic constant assignment");
01691                         $$ = dispatch2(const_path_field, $1, $3);
01692                     %*/
01693                     }
01694                 | tCOLON3 tCONSTANT
01695                     {
01696                     /*%%%*/
01697                         if (in_def || in_single)
01698                             yyerror("dynamic constant assignment");
01699                         $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01700                     /*%
01701                         $$ = dispatch1(top_const_field, $2);
01702                     %*/
01703                     }
01704                 | backref
01705                     {
01706                     /*%%%*/
01707                         rb_backref_error($1);
01708                         $$ = NEW_BEGIN(0);
01709                     /*%
01710                         $$ = dispatch1(var_field, $1);
01711                         $$ = dispatch1(assign_error, $$);
01712                     %*/
01713                     }
01714                 ;
01715 
01716 lhs             : user_variable
01717                     {
01718                         $$ = assignable($1, 0);
01719                     /*%%%*/
01720                         if (!$$) $$ = NEW_BEGIN(0);
01721                     /*%
01722                         $$ = dispatch1(var_field, $$);
01723                     %*/
01724                     }
01725                 | keyword_variable
01726                     {
01727                         $$ = assignable($1, 0);
01728                     /*%%%*/
01729                         if (!$$) $$ = NEW_BEGIN(0);
01730                     /*%
01731                         $$ = dispatch1(var_field, $$);
01732                     %*/
01733                     }
01734                 | primary_value '[' opt_call_args rbracket
01735                     {
01736                     /*%%%*/
01737                         $$ = aryset($1, $3);
01738                     /*%
01739                         $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01740                     %*/
01741                     }
01742                 | primary_value '.' tIDENTIFIER
01743                     {
01744                     /*%%%*/
01745                         $$ = attrset($1, $3);
01746                     /*%
01747                         $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01748                     %*/
01749                     }
01750                 | primary_value tCOLON2 tIDENTIFIER
01751                     {
01752                     /*%%%*/
01753                         $$ = attrset($1, $3);
01754                     /*%
01755                         $$ = dispatch3(field, $1, ripper_intern("::"), $3);
01756                     %*/
01757                     }
01758                 | primary_value '.' tCONSTANT
01759                     {
01760                     /*%%%*/
01761                         $$ = attrset($1, $3);
01762                     /*%
01763                         $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01764                     %*/
01765                     }
01766                 | primary_value tCOLON2 tCONSTANT
01767                     {
01768                     /*%%%*/
01769                         if (in_def || in_single)
01770                             yyerror("dynamic constant assignment");
01771                         $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01772                     /*%
01773                         $$ = dispatch2(const_path_field, $1, $3);
01774                         if (in_def || in_single) {
01775                             $$ = dispatch1(assign_error, $$);
01776                         }
01777                     %*/
01778                     }
01779                 | tCOLON3 tCONSTANT
01780                     {
01781                     /*%%%*/
01782                         if (in_def || in_single)
01783                             yyerror("dynamic constant assignment");
01784                         $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01785                     /*%
01786                         $$ = dispatch1(top_const_field, $2);
01787                         if (in_def || in_single) {
01788                             $$ = dispatch1(assign_error, $$);
01789                         }
01790                     %*/
01791                     }
01792                 | backref
01793                     {
01794                     /*%%%*/
01795                         rb_backref_error($1);
01796                         $$ = NEW_BEGIN(0);
01797                     /*%
01798                         $$ = dispatch1(assign_error, $1);
01799                     %*/
01800                     }
01801                 ;
01802 
01803 cname           : tIDENTIFIER
01804                     {
01805                     /*%%%*/
01806                         yyerror("class/module name must be CONSTANT");
01807                     /*%
01808                         $$ = dispatch1(class_name_error, $1);
01809                     %*/
01810                     }
01811                 | tCONSTANT
01812                 ;
01813 
01814 cpath           : tCOLON3 cname
01815                     {
01816                     /*%%%*/
01817                         $$ = NEW_COLON3($2);
01818                     /*%
01819                         $$ = dispatch1(top_const_ref, $2);
01820                     %*/
01821                     }
01822                 | cname
01823                     {
01824                     /*%%%*/
01825                         $$ = NEW_COLON2(0, $$);
01826                     /*%
01827                         $$ = dispatch1(const_ref, $1);
01828                     %*/
01829                     }
01830                 | primary_value tCOLON2 cname
01831                     {
01832                     /*%%%*/
01833                         $$ = NEW_COLON2($1, $3);
01834                     /*%
01835                         $$ = dispatch2(const_path_ref, $1, $3);
01836                     %*/
01837                     }
01838                 ;
01839 
01840 fname           : tIDENTIFIER
01841                 | tCONSTANT
01842                 | tFID
01843                 | op
01844                     {
01845                         lex_state = EXPR_ENDFN;
01846                         $$ = $1;
01847                     }
01848                 | reswords
01849                     {
01850                         lex_state = EXPR_ENDFN;
01851                     /*%%%*/
01852                         $$ = $<id>1;
01853                     /*%
01854                         $$ = $1;
01855                     %*/
01856                     }
01857                 ;
01858 
01859 fsym            : fname
01860                 | symbol
01861                 ;
01862 
01863 fitem           : fsym
01864                     {
01865                     /*%%%*/
01866                         $$ = NEW_LIT(ID2SYM($1));
01867                     /*%
01868                         $$ = dispatch1(symbol_literal, $1);
01869                     %*/
01870                     }
01871                 | dsym
01872                 ;
01873 
01874 undef_list      : fitem
01875                     {
01876                     /*%%%*/
01877                         $$ = NEW_UNDEF($1);
01878                     /*%
01879                         $$ = rb_ary_new3(1, $1);
01880                     %*/
01881                     }
01882                 | undef_list ',' {lex_state = EXPR_FNAME;} fitem
01883                     {
01884                     /*%%%*/
01885                         $$ = block_append($1, NEW_UNDEF($4));
01886                     /*%
01887                         rb_ary_push($1, $4);
01888                     %*/
01889                     }
01890                 ;
01891 
01892 op              : '|'           { ifndef_ripper($$ = '|'); }
01893                 | '^'           { ifndef_ripper($$ = '^'); }
01894                 | '&'           { ifndef_ripper($$ = '&'); }
01895                 | tCMP          { ifndef_ripper($$ = tCMP); }
01896                 | tEQ           { ifndef_ripper($$ = tEQ); }
01897                 | tEQQ          { ifndef_ripper($$ = tEQQ); }
01898                 | tMATCH        { ifndef_ripper($$ = tMATCH); }
01899                 | tNMATCH       { ifndef_ripper($$ = tNMATCH); }
01900                 | '>'           { ifndef_ripper($$ = '>'); }
01901                 | tGEQ          { ifndef_ripper($$ = tGEQ); }
01902                 | '<'           { ifndef_ripper($$ = '<'); }
01903                 | tLEQ          { ifndef_ripper($$ = tLEQ); }
01904                 | tNEQ          { ifndef_ripper($$ = tNEQ); }
01905                 | tLSHFT        { ifndef_ripper($$ = tLSHFT); }
01906                 | tRSHFT        { ifndef_ripper($$ = tRSHFT); }
01907                 | '+'           { ifndef_ripper($$ = '+'); }
01908                 | '-'           { ifndef_ripper($$ = '-'); }
01909                 | '*'           { ifndef_ripper($$ = '*'); }
01910                 | tSTAR         { ifndef_ripper($$ = '*'); }
01911                 | '/'           { ifndef_ripper($$ = '/'); }
01912                 | '%'           { ifndef_ripper($$ = '%'); }
01913                 | tPOW          { ifndef_ripper($$ = tPOW); }
01914                 | tDSTAR        { ifndef_ripper($$ = tDSTAR); }
01915                 | '!'           { ifndef_ripper($$ = '!'); }
01916                 | '~'           { ifndef_ripper($$ = '~'); }
01917                 | tUPLUS        { ifndef_ripper($$ = tUPLUS); }
01918                 | tUMINUS       { ifndef_ripper($$ = tUMINUS); }
01919                 | tAREF         { ifndef_ripper($$ = tAREF); }
01920                 | tASET         { ifndef_ripper($$ = tASET); }
01921                 | '`'           { ifndef_ripper($$ = '`'); }
01922                 ;
01923 
01924 reswords        : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
01925                 | keyword_BEGIN | keyword_END
01926                 | keyword_alias | keyword_and | keyword_begin
01927                 | keyword_break | keyword_case | keyword_class | keyword_def
01928                 | keyword_defined | keyword_do | keyword_else | keyword_elsif
01929                 | keyword_end | keyword_ensure | keyword_false
01930                 | keyword_for | keyword_in | keyword_module | keyword_next
01931                 | keyword_nil | keyword_not | keyword_or | keyword_redo
01932                 | keyword_rescue | keyword_retry | keyword_return | keyword_self
01933                 | keyword_super | keyword_then | keyword_true | keyword_undef
01934                 | keyword_when | keyword_yield | keyword_if | keyword_unless
01935                 | keyword_while | keyword_until
01936                 ;
01937 
01938 arg             : lhs '=' arg
01939                     {
01940                     /*%%%*/
01941                         value_expr($3);
01942                         $$ = node_assign($1, $3);
01943                     /*%
01944                         $$ = dispatch2(assign, $1, $3);
01945                     %*/
01946                     }
01947                 | lhs '=' arg modifier_rescue arg
01948                     {
01949                     /*%%%*/
01950                         value_expr($3);
01951                         $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01952                         $$ = node_assign($1, $3);
01953                     /*%
01954                         $$ = dispatch2(assign, $1, dispatch2(rescue_mod, $3, $5));
01955                     %*/
01956                     }
01957                 | var_lhs tOP_ASGN arg
01958                     {
01959                         value_expr($3);
01960                         $$ = new_op_assign($1, $2, $3);
01961                     }
01962                 | var_lhs tOP_ASGN arg modifier_rescue arg
01963                     {
01964                     /*%%%*/
01965                         value_expr($3);
01966                         $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01967                     /*%
01968                         $3 = dispatch2(rescue_mod, $3, $5);
01969                     %*/
01970                         $$ = new_op_assign($1, $2, $3);
01971                     }
01972                 | primary_value '[' opt_call_args rbracket tOP_ASGN arg
01973                     {
01974                     /*%%%*/
01975                         NODE *args;
01976 
01977                         value_expr($6);
01978                         if (!$3) $3 = NEW_ZARRAY();
01979                         if (nd_type($3) == NODE_BLOCK_PASS) {
01980                             args = NEW_ARGSCAT($3, $6);
01981                         }
01982                         else {
01983                             args = arg_concat($3, $6);
01984                         }
01985                         if ($5 == tOROP) {
01986                             $5 = 0;
01987                         }
01988                         else if ($5 == tANDOP) {
01989                             $5 = 1;
01990                         }
01991                         $$ = NEW_OP_ASGN1($1, $5, args);
01992                         fixpos($$, $1);
01993                     /*%
01994                         $1 = dispatch2(aref_field, $1, escape_Qundef($3));
01995                         $$ = dispatch3(opassign, $1, $5, $6);
01996                     %*/
01997                     }
01998                 | primary_value '.' tIDENTIFIER tOP_ASGN arg
01999                     {
02000                         value_expr($5);
02001                         $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);
02002                     }
02003                 | primary_value '.' tCONSTANT tOP_ASGN arg
02004                     {
02005                         value_expr($5);
02006                         $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5);
02007                     }
02008                 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
02009                     {
02010                         value_expr($5);
02011                         $$ = new_attr_op_assign($1, ripper_intern("::"), $3, $4, $5);
02012                     }
02013                 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
02014                     {
02015                     /*%%%*/
02016                         $$ = NEW_COLON2($1, $3);
02017                         $$ = new_const_op_assign($$, $4, $5);
02018                     /*%
02019                         $$ = dispatch2(const_path_field, $1, $3);
02020                         $$ = dispatch3(opassign, $$, $4, $5);
02021                     %*/
02022                     }
02023                 | tCOLON3 tCONSTANT tOP_ASGN arg
02024                     {
02025                     /*%%%*/
02026                         $$ = NEW_COLON3($2);
02027                         $$ = new_const_op_assign($$, $3, $4);
02028                     /*%
02029                         $$ = dispatch1(top_const_field, $2);
02030                         $$ = dispatch3(opassign, $$, $3, $4);
02031                     %*/
02032                     }
02033                 | backref tOP_ASGN arg
02034                     {
02035                     /*%%%*/
02036                         rb_backref_error($1);
02037                         $$ = NEW_BEGIN(0);
02038                     /*%
02039                         $$ = dispatch1(var_field, $1);
02040                         $$ = dispatch3(opassign, $$, $2, $3);
02041                         $$ = dispatch1(assign_error, $$);
02042                     %*/
02043                     }
02044                 | arg tDOT2 arg
02045                     {
02046                     /*%%%*/
02047                         value_expr($1);
02048                         value_expr($3);
02049                         $$ = NEW_DOT2($1, $3);
02050                         if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02051                             nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02052                             deferred_nodes = list_append(deferred_nodes, $$);
02053                         }
02054                     /*%
02055                         $$ = dispatch2(dot2, $1, $3);
02056                     %*/
02057                     }
02058                 | arg tDOT3 arg
02059                     {
02060                     /*%%%*/
02061                         value_expr($1);
02062                         value_expr($3);
02063                         $$ = NEW_DOT3($1, $3);
02064                         if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02065                             nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02066                             deferred_nodes = list_append(deferred_nodes, $$);
02067                         }
02068                     /*%
02069                         $$ = dispatch2(dot3, $1, $3);
02070                     %*/
02071                     }
02072                 | arg '+' arg
02073                     {
02074                     /*%%%*/
02075                         $$ = call_bin_op($1, '+', $3);
02076                     /*%
02077                         $$ = dispatch3(binary, $1, ID2SYM('+'), $3);
02078                     %*/
02079                     }
02080                 | arg '-' arg
02081                     {
02082                     /*%%%*/
02083                         $$ = call_bin_op($1, '-', $3);
02084                     /*%
02085                         $$ = dispatch3(binary, $1, ID2SYM('-'), $3);
02086                     %*/
02087                     }
02088                 | arg '*' arg
02089                     {
02090                     /*%%%*/
02091                         $$ = call_bin_op($1, '*', $3);
02092                     /*%
02093                         $$ = dispatch3(binary, $1, ID2SYM('*'), $3);
02094                     %*/
02095                     }
02096                 | arg '/' arg
02097                     {
02098                     /*%%%*/
02099                         $$ = call_bin_op($1, '/', $3);
02100                     /*%
02101                         $$ = dispatch3(binary, $1, ID2SYM('/'), $3);
02102                     %*/
02103                     }
02104                 | arg '%' arg
02105                     {
02106                     /*%%%*/
02107                         $$ = call_bin_op($1, '%', $3);
02108                     /*%
02109                         $$ = dispatch3(binary, $1, ID2SYM('%'), $3);
02110                     %*/
02111                     }
02112                 | arg tPOW arg
02113                     {
02114                     /*%%%*/
02115                         $$ = call_bin_op($1, tPOW, $3);
02116                     /*%
02117                         $$ = dispatch3(binary, $1, ripper_intern("**"), $3);
02118                     %*/
02119                     }
02120                 | tUMINUS_NUM tINTEGER tPOW arg
02121                     {
02122                     /*%%%*/
02123                         $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02124                     /*%
02125                         $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02126                         $$ = dispatch2(unary, ripper_intern("-@"), $$);
02127                     %*/
02128                     }
02129                 | tUMINUS_NUM tFLOAT tPOW arg
02130                     {
02131                     /*%%%*/
02132                         $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02133                     /*%
02134                         $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02135                         $$ = dispatch2(unary, ripper_intern("-@"), $$);
02136                     %*/
02137                     }
02138                 | tUPLUS arg
02139                     {
02140                     /*%%%*/
02141                         $$ = call_uni_op($2, tUPLUS);
02142                     /*%
02143                         $$ = dispatch2(unary, ripper_intern("+@"), $2);
02144                     %*/
02145                     }
02146                 | tUMINUS arg
02147                     {
02148                     /*%%%*/
02149                         $$ = call_uni_op($2, tUMINUS);
02150                     /*%
02151                         $$ = dispatch2(unary, ripper_intern("-@"), $2);
02152                     %*/
02153                     }
02154                 | arg '|' arg
02155                     {
02156                     /*%%%*/
02157                         $$ = call_bin_op($1, '|', $3);
02158                     /*%
02159                         $$ = dispatch3(binary, $1, ID2SYM('|'), $3);
02160                     %*/
02161                     }
02162                 | arg '^' arg
02163                     {
02164                     /*%%%*/
02165                         $$ = call_bin_op($1, '^', $3);
02166                     /*%
02167                         $$ = dispatch3(binary, $1, ID2SYM('^'), $3);
02168                     %*/
02169                     }
02170                 | arg '&' arg
02171                     {
02172                     /*%%%*/
02173                         $$ = call_bin_op($1, '&', $3);
02174                     /*%
02175                         $$ = dispatch3(binary, $1, ID2SYM('&'), $3);
02176                     %*/
02177                     }
02178                 | arg tCMP arg
02179                     {
02180                     /*%%%*/
02181                         $$ = call_bin_op($1, tCMP, $3);
02182                     /*%
02183                         $$ = dispatch3(binary, $1, ripper_intern("<=>"), $3);
02184                     %*/
02185                     }
02186                 | arg '>' arg
02187                     {
02188                     /*%%%*/
02189                         $$ = call_bin_op($1, '>', $3);
02190                     /*%
02191                         $$ = dispatch3(binary, $1, ID2SYM('>'), $3);
02192                     %*/
02193                     }
02194                 | arg tGEQ arg
02195                     {
02196                     /*%%%*/
02197                         $$ = call_bin_op($1, tGEQ, $3);
02198                     /*%
02199                         $$ = dispatch3(binary, $1, ripper_intern(">="), $3);
02200                     %*/
02201                     }
02202                 | arg '<' arg
02203                     {
02204                     /*%%%*/
02205                         $$ = call_bin_op($1, '<', $3);
02206                     /*%
02207                         $$ = dispatch3(binary, $1, ID2SYM('<'), $3);
02208                     %*/
02209                     }
02210                 | arg tLEQ arg
02211                     {
02212                     /*%%%*/
02213                         $$ = call_bin_op($1, tLEQ, $3);
02214                     /*%
02215                         $$ = dispatch3(binary, $1, ripper_intern("<="), $3);
02216                     %*/
02217                     }
02218                 | arg tEQ arg
02219                     {
02220                     /*%%%*/
02221                         $$ = call_bin_op($1, tEQ, $3);
02222                     /*%
02223                         $$ = dispatch3(binary, $1, ripper_intern("=="), $3);
02224                     %*/
02225                     }
02226                 | arg tEQQ arg
02227                     {
02228                     /*%%%*/
02229                         $$ = call_bin_op($1, tEQQ, $3);
02230                     /*%
02231                         $$ = dispatch3(binary, $1, ripper_intern("==="), $3);
02232                     %*/
02233                     }
02234                 | arg tNEQ arg
02235                     {
02236                     /*%%%*/
02237                         $$ = call_bin_op($1, tNEQ, $3);
02238                     /*%
02239                         $$ = dispatch3(binary, $1, ripper_intern("!="), $3);
02240                     %*/
02241                     }
02242                 | arg tMATCH arg
02243                     {
02244                     /*%%%*/
02245                         $$ = match_op($1, $3);
02246                         if (nd_type($1) == NODE_LIT && RB_TYPE_P($1->nd_lit, T_REGEXP)) {
02247                             $$ = reg_named_capture_assign($1->nd_lit, $$);
02248                         }
02249                     /*%
02250                         $$ = dispatch3(binary, $1, ripper_intern("=~"), $3);
02251                     %*/
02252                     }
02253                 | arg tNMATCH arg
02254                     {
02255                     /*%%%*/
02256                         $$ = call_bin_op($1, tNMATCH, $3);
02257                     /*%
02258                         $$ = dispatch3(binary, $1, ripper_intern("!~"), $3);
02259                     %*/
02260                     }
02261                 | '!' arg
02262                     {
02263                     /*%%%*/
02264                         $$ = call_uni_op(cond($2), '!');
02265                     /*%
02266                         $$ = dispatch2(unary, ID2SYM('!'), $2);
02267                     %*/
02268                     }
02269                 | '~' arg
02270                     {
02271                     /*%%%*/
02272                         $$ = call_uni_op($2, '~');
02273                     /*%
02274                         $$ = dispatch2(unary, ID2SYM('~'), $2);
02275                     %*/
02276                     }
02277                 | arg tLSHFT arg
02278                     {
02279                     /*%%%*/
02280                         $$ = call_bin_op($1, tLSHFT, $3);
02281                     /*%
02282                         $$ = dispatch3(binary, $1, ripper_intern("<<"), $3);
02283                     %*/
02284                     }
02285                 | arg tRSHFT arg
02286                     {
02287                     /*%%%*/
02288                         $$ = call_bin_op($1, tRSHFT, $3);
02289                     /*%
02290                         $$ = dispatch3(binary, $1, ripper_intern(">>"), $3);
02291                     %*/
02292                     }
02293                 | arg tANDOP arg
02294                     {
02295                     /*%%%*/
02296                         $$ = logop(NODE_AND, $1, $3);
02297                     /*%
02298                         $$ = dispatch3(binary, $1, ripper_intern("&&"), $3);
02299                     %*/
02300                     }
02301                 | arg tOROP arg
02302                     {
02303                     /*%%%*/
02304                         $$ = logop(NODE_OR, $1, $3);
02305                     /*%
02306                         $$ = dispatch3(binary, $1, ripper_intern("||"), $3);
02307                     %*/
02308                     }
02309                 | keyword_defined opt_nl {in_defined = 1;} arg
02310                     {
02311                     /*%%%*/
02312                         in_defined = 0;
02313                         $$ = NEW_DEFINED($4);
02314                     /*%
02315                         in_defined = 0;
02316                         $$ = dispatch1(defined, $4);
02317                     %*/
02318                     }
02319                 | arg '?' arg opt_nl ':' arg
02320                     {
02321                     /*%%%*/
02322                         value_expr($1);
02323                         $$ = NEW_IF(cond($1), $3, $6);
02324                         fixpos($$, $1);
02325                     /*%
02326                         $$ = dispatch3(ifop, $1, $3, $6);
02327                     %*/
02328                     }
02329                 | primary
02330                     {
02331                         $$ = $1;
02332                     }
02333                 ;
02334 
02335 arg_value       : arg
02336                     {
02337                     /*%%%*/
02338                         value_expr($1);
02339                         $$ = $1;
02340                         if (!$$) $$ = NEW_NIL();
02341                     /*%
02342                         $$ = $1;
02343                     %*/
02344                     }
02345                 ;
02346 
02347 aref_args       : none
02348                 | args trailer
02349                     {
02350                         $$ = $1;
02351                     }
02352                 | args ',' assocs trailer
02353                     {
02354                     /*%%%*/
02355                         $$ = arg_append($1, NEW_HASH($3));
02356                     /*%
02357                         $$ = arg_add_assocs($1, $3);
02358                     %*/
02359                     }
02360                 | assocs trailer
02361                     {
02362                     /*%%%*/
02363                         $$ = NEW_LIST(NEW_HASH($1));
02364                     /*%
02365                         $$ = arg_add_assocs(arg_new(), $1);
02366                     %*/
02367                     }
02368                 ;
02369 
02370 paren_args      : '(' opt_call_args rparen
02371                     {
02372                     /*%%%*/
02373                         $$ = $2;
02374                     /*%
02375                         $$ = dispatch1(arg_paren, escape_Qundef($2));
02376                     %*/
02377                     }
02378                 ;
02379 
02380 opt_paren_args  : none
02381                 | paren_args
02382                 ;
02383 
02384 opt_call_args   : none
02385                 | call_args
02386                 | args ','
02387                     {
02388                       $$ = $1;
02389                     }
02390                 | args ',' assocs ','
02391                     {
02392                     /*%%%*/
02393                         $$ = arg_append($1, NEW_HASH($3));
02394                     /*%
02395                         $$ = arg_add_assocs($1, $3);
02396                     %*/
02397                     }
02398                 | assocs ','
02399                     {
02400                     /*%%%*/
02401                         $$ = NEW_LIST(NEW_HASH($1));
02402                     /*%
02403                         $$ = arg_add_assocs(arg_new(), $1);
02404                     %*/
02405                     }
02406                 ;
02407 
02408 call_args       : command
02409                     {
02410                     /*%%%*/
02411                         value_expr($1);
02412                         $$ = NEW_LIST($1);
02413                     /*%
02414                         $$ = arg_add(arg_new(), $1);
02415                     %*/
02416                     }
02417                 | args opt_block_arg
02418                     {
02419                     /*%%%*/
02420                         $$ = arg_blk_pass($1, $2);
02421                     /*%
02422                         $$ = arg_add_optblock($1, $2);
02423                     %*/
02424                     }
02425                 | assocs opt_block_arg
02426                     {
02427                     /*%%%*/
02428                         $$ = NEW_LIST(NEW_HASH($1));
02429                         $$ = arg_blk_pass($$, $2);
02430                     /*%
02431                         $$ = arg_add_assocs(arg_new(), $1);
02432                         $$ = arg_add_optblock($$, $2);
02433                     %*/
02434                     }
02435                 | args ',' assocs opt_block_arg
02436                     {
02437                     /*%%%*/
02438                         $$ = arg_append($1, NEW_HASH($3));
02439                         $$ = arg_blk_pass($$, $4);
02440                     /*%
02441                         $$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
02442                     %*/
02443                     }
02444                 | block_arg
02445                     /*%c%*/
02446                     /*%c
02447                     {
02448                         $$ = arg_add_block(arg_new(), $1);
02449                     }
02450                     %*/
02451                 ;
02452 
02453 command_args    :  {
02454                         $<val>$ = cmdarg_stack;
02455                         CMDARG_PUSH(1);
02456                     }
02457                   call_args
02458                     {
02459                         /* CMDARG_POP() */
02460                         cmdarg_stack = $<val>1;
02461                         $$ = $2;
02462                     }
02463                 ;
02464 
02465 block_arg       : tAMPER arg_value
02466                     {
02467                     /*%%%*/
02468                         $$ = NEW_BLOCK_PASS($2);
02469                     /*%
02470                         $$ = $2;
02471                     %*/
02472                     }
02473                 ;
02474 
02475 opt_block_arg   : ',' block_arg
02476                     {
02477                         $$ = $2;
02478                     }
02479                 | none
02480                     {
02481                         $$ = 0;
02482                     }
02483                 ;
02484 
02485 args            : arg_value
02486                     {
02487                     /*%%%*/
02488                         $$ = NEW_LIST($1);
02489                     /*%
02490                         $$ = arg_add(arg_new(), $1);
02491                     %*/
02492                     }
02493                 | tSTAR arg_value
02494                     {
02495                     /*%%%*/
02496                         $$ = NEW_SPLAT($2);
02497                     /*%
02498                         $$ = arg_add_star(arg_new(), $2);
02499                     %*/
02500                     }
02501                 | args ',' arg_value
02502                     {
02503                     /*%%%*/
02504                         NODE *n1;
02505                         if ((n1 = splat_array($1)) != 0) {
02506                             $$ = list_append(n1, $3);
02507                         }
02508                         else {
02509                             $$ = arg_append($1, $3);
02510                         }
02511                     /*%
02512                         $$ = arg_add($1, $3);
02513                     %*/
02514                     }
02515                 | args ',' tSTAR arg_value
02516                     {
02517                     /*%%%*/
02518                         NODE *n1;
02519                         if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
02520                             $$ = list_concat(n1, $4);
02521                         }
02522                         else {
02523                             $$ = arg_concat($1, $4);
02524                         }
02525                     /*%
02526                         $$ = arg_add_star($1, $4);
02527                     %*/
02528                     }
02529                 ;
02530 
02531 mrhs            : args ',' arg_value
02532                     {
02533                     /*%%%*/
02534                         NODE *n1;
02535                         if ((n1 = splat_array($1)) != 0) {
02536                             $$ = list_append(n1, $3);
02537                         }
02538                         else {
02539                             $$ = arg_append($1, $3);
02540                         }
02541                     /*%
02542                         $$ = mrhs_add(args2mrhs($1), $3);
02543                     %*/
02544                     }
02545                 | args ',' tSTAR arg_value
02546                     {
02547                     /*%%%*/
02548                         NODE *n1;
02549                         if (nd_type($4) == NODE_ARRAY &&
02550                             (n1 = splat_array($1)) != 0) {
02551                             $$ = list_concat(n1, $4);
02552                         }
02553                         else {
02554                             $$ = arg_concat($1, $4);
02555                         }
02556                     /*%
02557                         $$ = mrhs_add_star(args2mrhs($1), $4);
02558                     %*/
02559                     }
02560                 | tSTAR arg_value
02561                     {
02562                     /*%%%*/
02563                         $$ = NEW_SPLAT($2);
02564                     /*%
02565                         $$ = mrhs_add_star(mrhs_new(), $2);
02566                     %*/
02567                     }
02568                 ;
02569 
02570 primary         : literal
02571                 | strings
02572                 | xstring
02573                 | regexp
02574                 | words
02575                 | qwords
02576                 | symbols
02577                 | qsymbols
02578                 | var_ref
02579                 | backref
02580                 | tFID
02581                     {
02582                     /*%%%*/
02583                         $$ = NEW_FCALL($1, 0);
02584                     /*%
02585                         $$ = method_arg(dispatch1(fcall, $1), arg_new());
02586                     %*/
02587                     }
02588                 | k_begin
02589                     {
02590                         $<val>1 = cmdarg_stack;
02591                         cmdarg_stack = 0;
02592                     /*%%%*/
02593                         $<num>$ = ruby_sourceline;
02594                     /*%
02595                     %*/
02596                     }
02597                   bodystmt
02598                   k_end
02599                     {
02600                         cmdarg_stack = $<val>1;
02601                     /*%%%*/
02602                         if ($3 == NULL) {
02603                             $$ = NEW_NIL();
02604                         }
02605                         else {
02606                             if (nd_type($3) == NODE_RESCUE ||
02607                                 nd_type($3) == NODE_ENSURE)
02608                                 nd_set_line($3, $<num>2);
02609                             $$ = NEW_BEGIN($3);
02610                         }
02611                         nd_set_line($$, $<num>2);
02612                     /*%
02613                         $$ = dispatch1(begin, $3);
02614                     %*/
02615                     }
02616                 | tLPAREN_ARG {lex_state = EXPR_ENDARG;} rparen
02617                     {
02618                     /*%%%*/
02619                         $$ = 0;
02620                     /*%
02621                         $$ = dispatch1(paren, 0);
02622                     %*/
02623                     }
02624                 | tLPAREN_ARG
02625                     {
02626                         $<val>1 = cmdarg_stack;
02627                         cmdarg_stack = 0;
02628                     }
02629                   expr {lex_state = EXPR_ENDARG;} rparen
02630                     {
02631                         cmdarg_stack = $<val>1;
02632                     /*%%%*/
02633                         $$ = $3;
02634                     /*%
02635                         $$ = dispatch1(paren, $3);
02636                     %*/
02637                     }
02638                 | tLPAREN compstmt ')'
02639                     {
02640                     /*%%%*/
02641                         $$ = $2;
02642                     /*%
02643                         $$ = dispatch1(paren, $2);
02644                     %*/
02645                     }
02646                 | primary_value tCOLON2 tCONSTANT
02647                     {
02648                     /*%%%*/
02649                         $$ = NEW_COLON2($1, $3);
02650                     /*%
02651                         $$ = dispatch2(const_path_ref, $1, $3);
02652                     %*/
02653                     }
02654                 | tCOLON3 tCONSTANT
02655                     {
02656                     /*%%%*/
02657                         $$ = NEW_COLON3($2);
02658                     /*%
02659                         $$ = dispatch1(top_const_ref, $2);
02660                     %*/
02661                     }
02662                 | tLBRACK aref_args ']'
02663                     {
02664                     /*%%%*/
02665                         if ($2 == 0) {
02666                             $$ = NEW_ZARRAY(); /* zero length array*/
02667                         }
02668                         else {
02669                             $$ = $2;
02670                         }
02671                     /*%
02672                         $$ = dispatch1(array, escape_Qundef($2));
02673                     %*/
02674                     }
02675                 | tLBRACE assoc_list '}'
02676                     {
02677                     /*%%%*/
02678                         $$ = NEW_HASH($2);
02679                     /*%
02680                         $$ = dispatch1(hash, escape_Qundef($2));
02681                     %*/
02682                     }
02683                 | keyword_return
02684                     {
02685                     /*%%%*/
02686                         $$ = NEW_RETURN(0);
02687                     /*%
02688                         $$ = dispatch0(return0);
02689                     %*/
02690                     }
02691                 | keyword_yield '(' call_args rparen
02692                     {
02693                     /*%%%*/
02694                         $$ = new_yield($3);
02695                     /*%
02696                         $$ = dispatch1(yield, dispatch1(paren, $3));
02697                     %*/
02698                     }
02699                 | keyword_yield '(' rparen
02700                     {
02701                     /*%%%*/
02702                         $$ = NEW_YIELD(0);
02703                     /*%
02704                         $$ = dispatch1(yield, dispatch1(paren, arg_new()));
02705                     %*/
02706                     }
02707                 | keyword_yield
02708                     {
02709                     /*%%%*/
02710                         $$ = NEW_YIELD(0);
02711                     /*%
02712                         $$ = dispatch0(yield0);
02713                     %*/
02714                     }
02715                 | keyword_defined opt_nl '(' {in_defined = 1;} expr rparen
02716                     {
02717                     /*%%%*/
02718                         in_defined = 0;
02719                         $$ = NEW_DEFINED($5);
02720                     /*%
02721                         in_defined = 0;
02722                         $$ = dispatch1(defined, $5);
02723                     %*/
02724                     }
02725                 | keyword_not '(' expr rparen
02726                     {
02727                     /*%%%*/
02728                         $$ = call_uni_op(cond($3), '!');
02729                     /*%
02730                         $$ = dispatch2(unary, ripper_intern("not"), $3);
02731                     %*/
02732                     }
02733                 | keyword_not '(' rparen
02734                     {
02735                     /*%%%*/
02736                         $$ = call_uni_op(cond(NEW_NIL()), '!');
02737                     /*%
02738                         $$ = dispatch2(unary, ripper_intern("not"), Qnil);
02739                     %*/
02740                     }
02741                 | fcall brace_block
02742                     {
02743                     /*%%%*/
02744                         $2->nd_iter = $1;
02745                         $$ = $2;
02746                     /*%
02747                         $$ = method_arg(dispatch1(fcall, $1), arg_new());
02748                         $$ = method_add_block($$, $2);
02749                     %*/
02750                     }
02751                 | method_call
02752                 | method_call brace_block
02753                     {
02754                     /*%%%*/
02755                         block_dup_check($1->nd_args, $2);
02756                         $2->nd_iter = $1;
02757                         $$ = $2;
02758                     /*%
02759                         $$ = method_add_block($1, $2);
02760                     %*/
02761                     }
02762                 | tLAMBDA lambda
02763                     {
02764                         $$ = $2;
02765                     }
02766                 | k_if expr_value then
02767                   compstmt
02768                   if_tail
02769                   k_end
02770                     {
02771                     /*%%%*/
02772                         $$ = NEW_IF(cond($2), $4, $5);
02773                         fixpos($$, $2);
02774                     /*%
02775                         $$ = dispatch3(if, $2, $4, escape_Qundef($5));
02776                     %*/
02777                     }
02778                 | k_unless expr_value then
02779                   compstmt
02780                   opt_else
02781                   k_end
02782                     {
02783                     /*%%%*/
02784                         $$ = NEW_UNLESS(cond($2), $4, $5);
02785                         fixpos($$, $2);
02786                     /*%
02787                         $$ = dispatch3(unless, $2, $4, escape_Qundef($5));
02788                     %*/
02789                     }
02790                 | k_while {COND_PUSH(1);} expr_value do {COND_POP();}
02791                   compstmt
02792                   k_end
02793                     {
02794                     /*%%%*/
02795                         $$ = NEW_WHILE(cond($3), $6, 1);
02796                         fixpos($$, $3);
02797                     /*%
02798                         $$ = dispatch2(while, $3, $6);
02799                     %*/
02800                     }
02801                 | k_until {COND_PUSH(1);} expr_value do {COND_POP();}
02802                   compstmt
02803                   k_end
02804                     {
02805                     /*%%%*/
02806                         $$ = NEW_UNTIL(cond($3), $6, 1);
02807                         fixpos($$, $3);
02808                     /*%
02809                         $$ = dispatch2(until, $3, $6);
02810                     %*/
02811                     }
02812                 | k_case expr_value opt_terms
02813                   case_body
02814                   k_end
02815                     {
02816                     /*%%%*/
02817                         $$ = NEW_CASE($2, $4);
02818                         fixpos($$, $2);
02819                     /*%
02820                         $$ = dispatch2(case, $2, $4);
02821                     %*/
02822                     }
02823                 | k_case opt_terms case_body k_end
02824                     {
02825                     /*%%%*/
02826                         $$ = NEW_CASE(0, $3);
02827                     /*%
02828                         $$ = dispatch2(case, Qnil, $3);
02829                     %*/
02830                     }
02831                 | k_for for_var keyword_in
02832                   {COND_PUSH(1);}
02833                   expr_value do
02834                   {COND_POP();}
02835                   compstmt
02836                   k_end
02837                     {
02838                     /*%%%*/
02839                         /*
02840                          *  for a, b, c in e
02841                          *  #=>
02842                          *  e.each{|*x| a, b, c = x
02843                          *
02844                          *  for a in e
02845                          *  #=>
02846                          *  e.each{|x| a, = x}
02847                          */
02848                         ID id = internal_id();
02849                         ID *tbl = ALLOC_N(ID, 2);
02850                         NODE *m = NEW_ARGS_AUX(0, 0);
02851                         NODE *args, *scope;
02852 
02853                         if (nd_type($2) == NODE_MASGN) {
02854                             /* if args.length == 1 && args[0].kind_of?(Array)
02855                              *   args = args[0]
02856                              * end
02857                              */
02858                             NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
02859                             NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
02860                             m->nd_next = block_append(
02861                                 NEW_IF(
02862                                     NEW_NODE(NODE_AND,
02863                                              NEW_CALL(NEW_CALL(NEW_DVAR(id), idLength, 0),
02864                                                       idEq, one),
02865                                              NEW_CALL(NEW_CALL(NEW_DVAR(id), idAREF, zero),
02866                                                       rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
02867                                              0),
02868                                     NEW_DASGN_CURR(id,
02869                                                    NEW_CALL(NEW_DVAR(id), idAREF, zero)),
02870                                     0),
02871                                 node_assign($2, NEW_DVAR(id)));
02872 
02873                             args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0));
02874                         }
02875                         else {
02876                             if (nd_type($2) == NODE_LASGN ||
02877                                 nd_type($2) == NODE_DASGN ||
02878                                 nd_type($2) == NODE_DASGN_CURR) {
02879                                 $2->nd_value = NEW_DVAR(id);
02880                                 m->nd_plen = 1;
02881                                 m->nd_next = $2;
02882                                 args = new_args(m, 0, 0, 0, new_args_tail(0, 0, 0));
02883                             }
02884                             else {
02885                                 m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
02886                                 args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0));
02887                             }
02888                         }
02889                         scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
02890                         tbl[0] = 1; tbl[1] = id;
02891                         $$ = NEW_FOR(0, $5, scope);
02892                         fixpos($$, $2);
02893                     /*%
02894                         $$ = dispatch3(for, $2, $5, $8);
02895                     %*/
02896                     }
02897                 | k_class cpath superclass
02898                     {
02899                         if (in_def || in_single)
02900                             yyerror("class definition in method body");
02901                         local_push(0);
02902                     /*%%%*/
02903                         $<num>$ = ruby_sourceline;
02904                     /*%
02905                     %*/
02906                     }
02907                   bodystmt
02908                   k_end
02909                     {
02910                     /*%%%*/
02911                         $$ = NEW_CLASS($2, $5, $3);
02912                         nd_set_line($$, $<num>4);
02913                     /*%
02914                         $$ = dispatch3(class, $2, $3, $5);
02915                     %*/
02916                         local_pop();
02917                     }
02918                 | k_class tLSHFT expr
02919                     {
02920                         $<num>$ = in_def;
02921                         in_def = 0;
02922                     }
02923                   term
02924                     {
02925                         $<num>$ = in_single;
02926                         in_single = 0;
02927                         local_push(0);
02928                     }
02929                   bodystmt
02930                   k_end
02931                     {
02932                     /*%%%*/
02933                         $$ = NEW_SCLASS($3, $7);
02934                         fixpos($$, $3);
02935                     /*%
02936                         $$ = dispatch2(sclass, $3, $7);
02937                     %*/
02938                         local_pop();
02939                         in_def = $<num>4;
02940                         in_single = $<num>6;
02941                     }
02942                 | k_module cpath
02943                     {
02944                         if (in_def || in_single)
02945                             yyerror("module definition in method body");
02946                         local_push(0);
02947                     /*%%%*/
02948                         $<num>$ = ruby_sourceline;
02949                     /*%
02950                     %*/
02951                     }
02952                   bodystmt
02953                   k_end
02954                     {
02955                     /*%%%*/
02956                         $$ = NEW_MODULE($2, $4);
02957                         nd_set_line($$, $<num>3);
02958                     /*%
02959                         $$ = dispatch2(module, $2, $4);
02960                     %*/
02961                         local_pop();
02962                     }
02963                 | k_def fname
02964                     {
02965                         $<id>$ = cur_mid;
02966                         cur_mid = $2;
02967                         in_def++;
02968                         local_push(0);
02969                     }
02970                   f_arglist
02971                   bodystmt
02972                   k_end
02973                     {
02974                     /*%%%*/
02975                         NODE *body = remove_begin($5);
02976                         reduce_nodes(&body);
02977                         $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
02978                         nd_set_line($$, $<num>1);
02979                     /*%
02980                         $$ = dispatch3(def, $2, $4, $5);
02981                     %*/
02982                         local_pop();
02983                         in_def--;
02984                         cur_mid = $<id>3;
02985                     }
02986                 | k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
02987                     {
02988                         in_single++;
02989                         lex_state = EXPR_ENDFN; /* force for args */
02990                         local_push(0);
02991                     }
02992                   f_arglist
02993                   bodystmt
02994                   k_end
02995                     {
02996                     /*%%%*/
02997                         NODE *body = remove_begin($8);
02998                         reduce_nodes(&body);
02999                         $$ = NEW_DEFS($2, $5, $7, body);
03000                         nd_set_line($$, $<num>1);
03001                     /*%
03002                         $$ = dispatch5(defs, $2, $3, $5, $7, $8);
03003                     %*/
03004                         local_pop();
03005                         in_single--;
03006                     }
03007                 | keyword_break
03008                     {
03009                     /*%%%*/
03010                         $$ = NEW_BREAK(0);
03011                     /*%
03012                         $$ = dispatch1(break, arg_new());
03013                     %*/
03014                     }
03015                 | keyword_next
03016                     {
03017                     /*%%%*/
03018                         $$ = NEW_NEXT(0);
03019                     /*%
03020                         $$ = dispatch1(next, arg_new());
03021                     %*/
03022                     }
03023                 | keyword_redo
03024                     {
03025                     /*%%%*/
03026                         $$ = NEW_REDO();
03027                     /*%
03028                         $$ = dispatch0(redo);
03029                     %*/
03030                     }
03031                 | keyword_retry
03032                     {
03033                     /*%%%*/
03034                         $$ = NEW_RETRY();
03035                     /*%
03036                         $$ = dispatch0(retry);
03037                     %*/
03038                     }
03039                 ;
03040 
03041 primary_value   : primary
03042                     {
03043                     /*%%%*/
03044                         value_expr($1);
03045                         $$ = $1;
03046                         if (!$$) $$ = NEW_NIL();
03047                     /*%
03048                         $$ = $1;
03049                     %*/
03050                     }
03051                 ;
03052 
03053 k_begin         : keyword_begin
03054                     {
03055                         token_info_push("begin");
03056                     }
03057                 ;
03058 
03059 k_if            : keyword_if
03060                     {
03061                         token_info_push("if");
03062                     }
03063                 ;
03064 
03065 k_unless        : keyword_unless
03066                     {
03067                         token_info_push("unless");
03068                     }
03069                 ;
03070 
03071 k_while         : keyword_while
03072                     {
03073                         token_info_push("while");
03074                     }
03075                 ;
03076 
03077 k_until         : keyword_until
03078                     {
03079                         token_info_push("until");
03080                     }
03081                 ;
03082 
03083 k_case          : keyword_case
03084                     {
03085                         token_info_push("case");
03086                     }
03087                 ;
03088 
03089 k_for           : keyword_for
03090                     {
03091                         token_info_push("for");
03092                     }
03093                 ;
03094 
03095 k_class         : keyword_class
03096                     {
03097                         token_info_push("class");
03098                     }
03099                 ;
03100 
03101 k_module        : keyword_module
03102                     {
03103                         token_info_push("module");
03104                     }
03105                 ;
03106 
03107 k_def           : keyword_def
03108                     {
03109                         token_info_push("def");
03110                     /*%%%*/
03111                         $<num>$ = ruby_sourceline;
03112                     /*%
03113                     %*/
03114                     }
03115                 ;
03116 
03117 k_end           : keyword_end
03118                     {
03119                         token_info_pop("end");
03120                     }
03121                 ;
03122 
03123 then            : term
03124                     /*%c%*/
03125                     /*%c
03126                     { $$ = Qnil; }
03127                     %*/
03128                 | keyword_then
03129                 | term keyword_then
03130                     /*%c%*/
03131                     /*%c
03132                     { $$ = $2; }
03133                     %*/
03134                 ;
03135 
03136 do              : term
03137                     /*%c%*/
03138                     /*%c
03139                     { $$ = Qnil; }
03140                     %*/
03141                 | keyword_do_cond
03142                 ;
03143 
03144 if_tail         : opt_else
03145                 | keyword_elsif expr_value then
03146                   compstmt
03147                   if_tail
03148                     {
03149                     /*%%%*/
03150                         $$ = NEW_IF(cond($2), $4, $5);
03151                         fixpos($$, $2);
03152                     /*%
03153                         $$ = dispatch3(elsif, $2, $4, escape_Qundef($5));
03154                     %*/
03155                     }
03156                 ;
03157 
03158 opt_else        : none
03159                 | keyword_else compstmt
03160                     {
03161                     /*%%%*/
03162                         $$ = $2;
03163                     /*%
03164                         $$ = dispatch1(else, $2);
03165                     %*/
03166                     }
03167                 ;
03168 
03169 for_var         : lhs
03170                 | mlhs
03171                 ;
03172 
03173 f_marg          : f_norm_arg
03174                     {
03175                         $$ = assignable($1, 0);
03176                     /*%%%*/
03177                     /*%
03178                         $$ = dispatch1(mlhs_paren, $$);
03179                     %*/
03180                     }
03181                 | tLPAREN f_margs rparen
03182                     {
03183                     /*%%%*/
03184                         $$ = $2;
03185                     /*%
03186                         $$ = dispatch1(mlhs_paren, $2);
03187                     %*/
03188                     }
03189                 ;
03190 
03191 f_marg_list     : f_marg
03192                     {
03193                     /*%%%*/
03194                         $$ = NEW_LIST($1);
03195                     /*%
03196                         $$ = mlhs_add(mlhs_new(), $1);
03197                     %*/
03198                     }
03199                 | f_marg_list ',' f_marg
03200                     {
03201                     /*%%%*/
03202                         $$ = list_append($1, $3);
03203                     /*%
03204                         $$ = mlhs_add($1, $3);
03205                     %*/
03206                     }
03207                 ;
03208 
03209 f_margs         : f_marg_list
03210                     {
03211                     /*%%%*/
03212                         $$ = NEW_MASGN($1, 0);
03213                     /*%
03214                         $$ = $1;
03215                     %*/
03216                     }
03217                 | f_marg_list ',' tSTAR f_norm_arg
03218                     {
03219                         $$ = assignable($4, 0);
03220                     /*%%%*/
03221                         $$ = NEW_MASGN($1, $$);
03222                     /*%
03223                         $$ = mlhs_add_star($1, $$);
03224                     %*/
03225                     }
03226                 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
03227                     {
03228                         $$ = assignable($4, 0);
03229                     /*%%%*/
03230                         $$ = NEW_MASGN($1, NEW_POSTARG($$, $6));
03231                     /*%
03232                         $$ = mlhs_add_star($1, $$);
03233                     %*/
03234                     }
03235                 | f_marg_list ',' tSTAR
03236                     {
03237                     /*%%%*/
03238                         $$ = NEW_MASGN($1, -1);
03239                     /*%
03240                         $$ = mlhs_add_star($1, Qnil);
03241                     %*/
03242                     }
03243                 | f_marg_list ',' tSTAR ',' f_marg_list
03244                     {
03245                     /*%%%*/
03246                         $$ = NEW_MASGN($1, NEW_POSTARG(-1, $5));
03247                     /*%
03248                         $$ = mlhs_add_star($1, $5);
03249                     %*/
03250                     }
03251                 | tSTAR f_norm_arg
03252                     {
03253                         $$ = assignable($2, 0);
03254                     /*%%%*/
03255                         $$ = NEW_MASGN(0, $$);
03256                     /*%
03257                         $$ = mlhs_add_star(mlhs_new(), $$);
03258                     %*/
03259                     }
03260                 | tSTAR f_norm_arg ',' f_marg_list
03261                     {
03262                         $$ = assignable($2, 0);
03263                     /*%%%*/
03264                         $$ = NEW_MASGN(0, NEW_POSTARG($$, $4));
03265                     /*%
03266                       #if 0
03267                       TODO: Check me
03268                       #endif
03269                         $$ = mlhs_add_star($$, $4);
03270                     %*/
03271                     }
03272                 | tSTAR
03273                     {
03274                     /*%%%*/
03275                         $$ = NEW_MASGN(0, -1);
03276                     /*%
03277                         $$ = mlhs_add_star(mlhs_new(), Qnil);
03278                     %*/
03279                     }
03280                 | tSTAR ',' f_marg_list
03281                     {
03282                     /*%%%*/
03283                         $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
03284                     /*%
03285                         $$ = mlhs_add_star(mlhs_new(), Qnil);
03286                     %*/
03287                     }
03288                 ;
03289 
03290 
03291 block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
03292                     {
03293                         $$ = new_args_tail($1, $3, $4);
03294                     }
03295                 | f_block_kwarg opt_f_block_arg
03296                     {
03297                         $$ = new_args_tail($1, Qnone, $2);
03298                     }
03299                 | f_kwrest opt_f_block_arg
03300                     {
03301                         $$ = new_args_tail(Qnone, $1, $2);
03302                     }
03303                 | f_block_arg
03304                     {
03305                         $$ = new_args_tail(Qnone, Qnone, $1);
03306                     }
03307                 ;
03308 
03309 opt_block_args_tail : ',' block_args_tail
03310                     {
03311                         $$ = $2;
03312                     }
03313                 | /* none */
03314                     {
03315                         $$ = new_args_tail(Qnone, Qnone, Qnone);
03316                     }
03317                 ;
03318 
03319 block_param     : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
03320                     {
03321                         $$ = new_args($1, $3, $5, Qnone, $6);
03322                     }
03323                 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
03324                     {
03325                         $$ = new_args($1, $3, $5, $7, $8);
03326                     }
03327                 | f_arg ',' f_block_optarg opt_block_args_tail
03328                     {
03329                         $$ = new_args($1, $3, Qnone, Qnone, $4);
03330                     }
03331                 | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail
03332                     {
03333                         $$ = new_args($1, $3, Qnone, $5, $6);
03334                     }
03335                 | f_arg ',' f_rest_arg opt_block_args_tail
03336                     {
03337                         $$ = new_args($1, Qnone, $3, Qnone, $4);
03338                     }
03339                 | f_arg ','
03340                     {
03341                         $$ = new_args($1, Qnone, 1, Qnone, new_args_tail(Qnone, Qnone, Qnone));
03342                     /*%%%*/
03343                     /*%
03344                         dispatch1(excessed_comma, $$);
03345                     %*/
03346                     }
03347                 | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
03348                     {
03349                         $$ = new_args($1, Qnone, $3, $5, $6);
03350                     }
03351                 | f_arg opt_block_args_tail
03352                     {
03353                         $$ = new_args($1, Qnone, Qnone, Qnone, $2);
03354                     }
03355                 | f_block_optarg ',' f_rest_arg opt_block_args_tail
03356                     {
03357                         $$ = new_args(Qnone, $1, $3, Qnone, $4);
03358                     }
03359                 | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
03360                     {
03361                         $$ = new_args(Qnone, $1, $3, $5, $6);
03362                     }
03363                 | f_block_optarg opt_block_args_tail
03364                     {
03365                         $$ = new_args(Qnone, $1, Qnone, Qnone, $2);
03366                     }
03367                 | f_block_optarg ',' f_arg opt_block_args_tail
03368                     {
03369                         $$ = new_args(Qnone, $1, Qnone, $3, $4);
03370                     }
03371                 | f_rest_arg opt_block_args_tail
03372                     {
03373                         $$ = new_args(Qnone, Qnone, $1, Qnone, $2);
03374                     }
03375                 | f_rest_arg ',' f_arg opt_block_args_tail
03376                     {
03377                         $$ = new_args(Qnone, Qnone, $1, $3, $4);
03378                     }
03379                 | block_args_tail
03380                     {
03381                         $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1);
03382                     }
03383                 ;
03384 
03385 opt_block_param : none
03386                 | block_param_def
03387                     {
03388                         command_start = TRUE;
03389                     }
03390                 ;
03391 
03392 block_param_def : '|' opt_bv_decl '|'
03393                     {
03394                     /*%%%*/
03395                         $$ = 0;
03396                     /*%
03397                         $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil),
03398                                           escape_Qundef($2));
03399                     %*/
03400                     }
03401                 | tOROP
03402                     {
03403                     /*%%%*/
03404                         $$ = 0;
03405                     /*%
03406                         $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil),
03407                                           Qnil);
03408                     %*/
03409                     }
03410                 | '|' block_param opt_bv_decl '|'
03411                     {
03412                     /*%%%*/
03413                         $$ = $2;
03414                     /*%
03415                         $$ = blockvar_new(escape_Qundef($2), escape_Qundef($3));
03416                     %*/
03417                     }
03418                 ;
03419 
03420 
03421 opt_bv_decl     : opt_nl
03422                     {
03423                       $$ = 0;
03424                     }
03425                 | opt_nl ';' bv_decls opt_nl
03426                     {
03427                     /*%%%*/
03428                         $$ = 0;
03429                     /*%
03430                         $$ = $3;
03431                     %*/
03432                     }
03433                 ;
03434 
03435 bv_decls        : bvar
03436                     /*%c%*/
03437                     /*%c
03438                     {
03439                         $$ = rb_ary_new3(1, $1);
03440                     }
03441                     %*/
03442                 | bv_decls ',' bvar
03443                     /*%c%*/
03444                     /*%c
03445                     {
03446                         rb_ary_push($1, $3);
03447                     }
03448                     %*/
03449                 ;
03450 
03451 bvar            : tIDENTIFIER
03452                     {
03453                         new_bv(get_id($1));
03454                     /*%%%*/
03455                     /*%
03456                         $$ = get_value($1);
03457                     %*/
03458                     }
03459                 | f_bad_arg
03460                     {
03461                         $$ = 0;
03462                     }
03463                 ;
03464 
03465 lambda          :   {
03466                         $<vars>$ = dyna_push();
03467                     }
03468                     {
03469                         $<num>$ = lpar_beg;
03470                         lpar_beg = ++paren_nest;
03471                     }
03472                   f_larglist
03473                     {
03474                         $<num>$ = ruby_sourceline;
03475                     }
03476                   lambda_body
03477                     {
03478                         lpar_beg = $<num>2;
03479                     /*%%%*/
03480                         $$ = NEW_LAMBDA($3, $5);
03481                         nd_set_line($$, $<num>4);
03482                     /*%
03483                         $$ = dispatch2(lambda, $3, $5);
03484                     %*/
03485                         dyna_pop($<vars>1);
03486                     }
03487                 ;
03488 
03489 f_larglist      : '(' f_args opt_bv_decl ')'
03490                     {
03491                     /*%%%*/
03492                         $$ = $2;
03493                     /*%
03494                         $$ = dispatch1(paren, $2);
03495                     %*/
03496                     }
03497                 | f_args
03498                     {
03499                     /*%%%*/
03500                         $$ = $1;
03501                     /*%
03502                         $$ = $1;
03503                     %*/
03504                     }
03505                 ;
03506 
03507 lambda_body     : tLAMBEG compstmt '}'
03508                     {
03509                         $$ = $2;
03510                     }
03511                 | keyword_do_LAMBDA compstmt keyword_end
03512                     {
03513                         $$ = $2;
03514                     }
03515                 ;
03516 
03517 do_block        : keyword_do_block
03518                     {
03519                         $<vars>1 = dyna_push();
03520                     /*%%%*/
03521                         $<num>$ = ruby_sourceline;
03522                     /*% %*/
03523                     }
03524                   opt_block_param
03525                   compstmt
03526                   keyword_end
03527                     {
03528                     /*%%%*/
03529                         $$ = NEW_ITER($3,$4);
03530                         nd_set_line($$, $<num>2);
03531                     /*%
03532                         $$ = dispatch2(do_block, escape_Qundef($3), $4);
03533                     %*/
03534                         dyna_pop($<vars>1);
03535                     }
03536                 ;
03537 
03538 block_call      : command do_block
03539                     {
03540                     /*%%%*/
03541                         if (nd_type($1) == NODE_YIELD) {
03542                             compile_error(PARSER_ARG "block given to yield");
03543                         }
03544                         else {
03545                             block_dup_check($1->nd_args, $2);
03546                         }
03547                         $2->nd_iter = $1;
03548                         $$ = $2;
03549                         fixpos($$, $1);
03550                     /*%
03551                         $$ = method_add_block($1, $2);
03552                     %*/
03553                     }
03554                 | block_call dot_or_colon operation2 opt_paren_args
03555                     {
03556                     /*%%%*/
03557                         $$ = NEW_CALL($1, $3, $4);
03558                     /*%
03559                         $$ = dispatch3(call, $1, $2, $3);
03560                         $$ = method_optarg($$, $4);
03561                     %*/
03562                     }
03563                 | block_call dot_or_colon operation2 opt_paren_args brace_block
03564                     {
03565                     /*%%%*/
03566                         block_dup_check($4, $5);
03567                         $5->nd_iter = NEW_CALL($1, $3, $4);
03568                         $$ = $5;
03569                         fixpos($$, $1);
03570                     /*%
03571                         $$ = dispatch4(command_call, $1, $2, $3, $4);
03572                         $$ = method_add_block($$, $5);
03573                     %*/
03574                     }
03575                 | block_call dot_or_colon operation2 command_args do_block
03576                     {
03577                     /*%%%*/
03578                         block_dup_check($4, $5);
03579                         $5->nd_iter = NEW_CALL($1, $3, $4);
03580                         $$ = $5;
03581                         fixpos($$, $1);
03582                     /*%
03583                         $$ = dispatch4(command_call, $1, $2, $3, $4);
03584                         $$ = method_add_block($$, $5);
03585                     %*/
03586                     }
03587                 ;
03588 
03589 method_call     : fcall paren_args
03590                     {
03591                     /*%%%*/
03592                         $$ = $1;
03593                         $$->nd_args = $2;
03594                     /*%
03595                         $$ = method_arg(dispatch1(fcall, $1), $2);
03596                     %*/
03597                     }
03598                 | primary_value '.' operation2
03599                     {
03600                     /*%%%*/
03601                         $<num>$ = ruby_sourceline;
03602                     /*% %*/
03603                     }
03604                   opt_paren_args
03605                     {
03606                     /*%%%*/
03607                         $$ = NEW_CALL($1, $3, $5);
03608                         nd_set_line($$, $<num>4);
03609                     /*%
03610                         $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03611                         $$ = method_optarg($$, $5);
03612                     %*/
03613                     }
03614                 | primary_value tCOLON2 operation2
03615                     {
03616                     /*%%%*/
03617                         $<num>$ = ruby_sourceline;
03618                     /*% %*/
03619                     }
03620                   paren_args
03621                     {
03622                     /*%%%*/
03623                         $$ = NEW_CALL($1, $3, $5);
03624                         nd_set_line($$, $<num>4);
03625                     /*%
03626                         $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03627                         $$ = method_optarg($$, $5);
03628                     %*/
03629                     }
03630                 | primary_value tCOLON2 operation3
03631                     {
03632                     /*%%%*/
03633                         $$ = NEW_CALL($1, $3, 0);
03634                     /*%
03635                         $$ = dispatch3(call, $1, ripper_intern("::"), $3);
03636                     %*/
03637                     }
03638                 | primary_value '.'
03639                     {
03640                     /*%%%*/
03641                         $<num>$ = ruby_sourceline;
03642                     /*% %*/
03643                     }
03644                   paren_args
03645                     {
03646                     /*%%%*/
03647                         $$ = NEW_CALL($1, rb_intern("call"), $4);
03648                         nd_set_line($$, $<num>3);
03649                     /*%
03650                         $$ = dispatch3(call, $1, ripper_id2sym('.'),
03651                                        ripper_intern("call"));
03652                         $$ = method_optarg($$, $4);
03653                     %*/
03654                     }
03655                 | primary_value tCOLON2
03656                     {
03657                     /*%%%*/
03658                         $<num>$ = ruby_sourceline;
03659                     /*% %*/
03660                     }
03661                   paren_args
03662                     {
03663                     /*%%%*/
03664                         $$ = NEW_CALL($1, rb_intern("call"), $4);
03665                         nd_set_line($$, $<num>3);
03666                     /*%
03667                         $$ = dispatch3(call, $1, ripper_intern("::"),
03668                                        ripper_intern("call"));
03669                         $$ = method_optarg($$, $4);
03670                     %*/
03671                     }
03672                 | keyword_super paren_args
03673                     {
03674                     /*%%%*/
03675                         $$ = NEW_SUPER($2);
03676                     /*%
03677                         $$ = dispatch1(super, $2);
03678                     %*/
03679                     }
03680                 | keyword_super
03681                     {
03682                     /*%%%*/
03683                         $$ = NEW_ZSUPER();
03684                     /*%
03685                         $$ = dispatch0(zsuper);
03686                     %*/
03687                     }
03688                 | primary_value '[' opt_call_args rbracket
03689                     {
03690                     /*%%%*/
03691                         if ($1 && nd_type($1) == NODE_SELF)
03692                             $$ = NEW_FCALL(tAREF, $3);
03693                         else
03694                             $$ = NEW_CALL($1, tAREF, $3);
03695                         fixpos($$, $1);
03696                     /*%
03697                         $$ = dispatch2(aref, $1, escape_Qundef($3));
03698                     %*/
03699                     }
03700                 ;
03701 
03702 brace_block     : '{'
03703                     {
03704                         $<vars>1 = dyna_push();
03705                     /*%%%*/
03706                         $<num>$ = ruby_sourceline;
03707                     /*%
03708                     %*/
03709                     }
03710                   opt_block_param
03711                   compstmt '}'
03712                     {
03713                     /*%%%*/
03714                         $$ = NEW_ITER($3,$4);
03715                         nd_set_line($$, $<num>2);
03716                     /*%
03717                         $$ = dispatch2(brace_block, escape_Qundef($3), $4);
03718                     %*/
03719                         dyna_pop($<vars>1);
03720                     }
03721                 | keyword_do
03722                     {
03723                         $<vars>1 = dyna_push();
03724                     /*%%%*/
03725                         $<num>$ = ruby_sourceline;
03726                     /*%
03727                     %*/
03728                     }
03729                   opt_block_param
03730                   compstmt keyword_end
03731                     {
03732                     /*%%%*/
03733                         $$ = NEW_ITER($3,$4);
03734                         nd_set_line($$, $<num>2);
03735                     /*%
03736                         $$ = dispatch2(do_block, escape_Qundef($3), $4);
03737                     %*/
03738                         dyna_pop($<vars>1);
03739                     }
03740                 ;
03741 
03742 case_body       : keyword_when args then
03743                   compstmt
03744                   cases
03745                     {
03746                     /*%%%*/
03747                         $$ = NEW_WHEN($2, $4, $5);
03748                     /*%
03749                         $$ = dispatch3(when, $2, $4, escape_Qundef($5));
03750                     %*/
03751                     }
03752                 ;
03753 
03754 cases           : opt_else
03755                 | case_body
03756                 ;
03757 
03758 opt_rescue      : keyword_rescue exc_list exc_var then
03759                   compstmt
03760                   opt_rescue
03761                     {
03762                     /*%%%*/
03763                         if ($3) {
03764                             $3 = node_assign($3, NEW_ERRINFO());
03765                             $5 = block_append($3, $5);
03766                         }
03767                         $$ = NEW_RESBODY($2, $5, $6);
03768                         fixpos($$, $2?$2:$5);
03769                     /*%
03770                         $$ = dispatch4(rescue,
03771                                        escape_Qundef($2),
03772                                        escape_Qundef($3),
03773                                        escape_Qundef($5),
03774                                        escape_Qundef($6));
03775                     %*/
03776                     }
03777                 | none
03778                 ;
03779 
03780 exc_list        : arg_value
03781                     {
03782                     /*%%%*/
03783                         $$ = NEW_LIST($1);
03784                     /*%
03785                         $$ = rb_ary_new3(1, $1);
03786                     %*/
03787                     }
03788                 | mrhs
03789                     {
03790                     /*%%%*/
03791                         if (!($$ = splat_array($1))) $$ = $1;
03792                     /*%
03793                         $$ = $1;
03794                     %*/
03795                     }
03796                 | none
03797                 ;
03798 
03799 exc_var         : tASSOC lhs
03800                     {
03801                         $$ = $2;
03802                     }
03803                 | none
03804                 ;
03805 
03806 opt_ensure      : keyword_ensure compstmt
03807                     {
03808                     /*%%%*/
03809                         $$ = $2;
03810                     /*%
03811                         $$ = dispatch1(ensure, $2);
03812                     %*/
03813                     }
03814                 | none
03815                 ;
03816 
03817 literal         : numeric
03818                 | symbol
03819                     {
03820                     /*%%%*/
03821                         $$ = NEW_LIT(ID2SYM($1));
03822                     /*%
03823                         $$ = dispatch1(symbol_literal, $1);
03824                     %*/
03825                     }
03826                 | dsym
03827                 ;
03828 
03829 strings         : string
03830                     {
03831                     /*%%%*/
03832                         NODE *node = $1;
03833                         if (!node) {
03834                             node = NEW_STR(STR_NEW0());
03835                         }
03836                         else {
03837                             node = evstr2dstr(node);
03838                         }
03839                         $$ = node;
03840                     /*%
03841                         $$ = $1;
03842                     %*/
03843                     }
03844                 ;
03845 
03846 string          : tCHAR
03847                 | string1
03848                 | string string1
03849                     {
03850                     /*%%%*/
03851                         $$ = literal_concat($1, $2);
03852                     /*%
03853                         $$ = dispatch2(string_concat, $1, $2);
03854                     %*/
03855                     }
03856                 ;
03857 
03858 string1         : tSTRING_BEG string_contents tSTRING_END
03859                     {
03860                     /*%%%*/
03861                         $$ = $2;
03862                     /*%
03863                         $$ = dispatch1(string_literal, $2);
03864                     %*/
03865                     }
03866                 ;
03867 
03868 xstring         : tXSTRING_BEG xstring_contents tSTRING_END
03869                     {
03870                     /*%%%*/
03871                         NODE *node = $2;
03872                         if (!node) {
03873                             node = NEW_XSTR(STR_NEW0());
03874                         }
03875                         else {
03876                             switch (nd_type(node)) {
03877                               case NODE_STR:
03878                                 nd_set_type(node, NODE_XSTR);
03879                                 break;
03880                               case NODE_DSTR:
03881                                 nd_set_type(node, NODE_DXSTR);
03882                                 break;
03883                               default:
03884                                 node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node));
03885                                 break;
03886                             }
03887                         }
03888                         $$ = node;
03889                     /*%
03890                         $$ = dispatch1(xstring_literal, $2);
03891                     %*/
03892                     }
03893                 ;
03894 
03895 regexp          : tREGEXP_BEG regexp_contents tREGEXP_END
03896                     {
03897                     /*%%%*/
03898                         int options = $3;
03899                         NODE *node = $2;
03900                         NODE *list, *prev;
03901                         if (!node) {
03902                             node = NEW_LIT(reg_compile(STR_NEW0(), options));
03903                         }
03904                         else switch (nd_type(node)) {
03905                           case NODE_STR:
03906                             {
03907                                 VALUE src = node->nd_lit;
03908                                 nd_set_type(node, NODE_LIT);
03909                                 node->nd_lit = reg_compile(src, options);
03910                             }
03911                             break;
03912                           default:
03913                             node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node));
03914                           case NODE_DSTR:
03915                             if (options & RE_OPTION_ONCE) {
03916                                 nd_set_type(node, NODE_DREGX_ONCE);
03917                             }
03918                             else {
03919                                 nd_set_type(node, NODE_DREGX);
03920                             }
03921                             node->nd_cflag = options & RE_OPTION_MASK;
03922                             if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options);
03923                             for (list = (prev = node)->nd_next; list; list = list->nd_next) {
03924                                 if (nd_type(list->nd_head) == NODE_STR) {
03925                                     VALUE tail = list->nd_head->nd_lit;
03926                                     if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) {
03927                                         VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
03928                                         if (!literal_concat0(parser, lit, tail)) {
03929                                             node = 0;
03930                                             break;
03931                                         }
03932                                         rb_str_resize(tail, 0);
03933                                         prev->nd_next = list->nd_next;
03934                                         rb_gc_force_recycle((VALUE)list->nd_head);
03935                                         rb_gc_force_recycle((VALUE)list);
03936                                         list = prev;
03937                                     }
03938                                     else {
03939                                         prev = list;
03940                                     }
03941                                 }
03942                                 else {
03943                                     prev = 0;
03944                                 }
03945                             }
03946                             if (!node->nd_next) {
03947                                 VALUE src = node->nd_lit;
03948                                 nd_set_type(node, NODE_LIT);
03949                                 node->nd_lit = reg_compile(src, options);
03950                             }
03951                             break;
03952                         }
03953                         $$ = node;
03954                     /*%
03955                         $$ = dispatch2(regexp_literal, $2, $3);
03956                     %*/
03957                     }
03958                 ;
03959 
03960 words           : tWORDS_BEG ' ' tSTRING_END
03961                     {
03962                     /*%%%*/
03963                         $$ = NEW_ZARRAY();
03964                     /*%
03965                         $$ = dispatch0(words_new);
03966                         $$ = dispatch1(array, $$);
03967                     %*/
03968                     }
03969                 | tWORDS_BEG word_list tSTRING_END
03970                     {
03971                     /*%%%*/
03972                         $$ = $2;
03973                     /*%
03974                         $$ = dispatch1(array, $2);
03975                     %*/
03976                     }
03977                 ;
03978 
03979 word_list       : /* none */
03980                     {
03981                     /*%%%*/
03982                         $$ = 0;
03983                     /*%
03984                         $$ = dispatch0(words_new);
03985                     %*/
03986                     }
03987                 | word_list word ' '
03988                     {
03989                     /*%%%*/
03990                         $$ = list_append($1, evstr2dstr($2));
03991                     /*%
03992                         $$ = dispatch2(words_add, $1, $2);
03993                     %*/
03994                     }
03995                 ;
03996 
03997 word            : string_content
03998                     /*%c%*/
03999                     /*%c
04000                     {
04001                         $$ = dispatch0(word_new);
04002                         $$ = dispatch2(word_add, $$, $1);
04003                     }
04004                     %*/
04005                 | word string_content
04006                     {
04007                     /*%%%*/
04008                         $$ = literal_concat($1, $2);
04009                     /*%
04010                         $$ = dispatch2(word_add, $1, $2);
04011                     %*/
04012                     }
04013                 ;
04014 
04015 symbols         : tSYMBOLS_BEG ' ' tSTRING_END
04016                     {
04017                     /*%%%*/
04018                         $$ = NEW_ZARRAY();
04019                     /*%
04020                         $$ = dispatch0(symbols_new);
04021                         $$ = dispatch1(array, $$);
04022                     %*/
04023                     }
04024                 | tSYMBOLS_BEG symbol_list tSTRING_END
04025                     {
04026                     /*%%%*/
04027                         $$ = $2;
04028                     /*%
04029                         $$ = dispatch1(array, $2);
04030                     %*/
04031                     }
04032                 ;
04033 
04034 symbol_list     : /* none */
04035                     {
04036                     /*%%%*/
04037                         $$ = 0;
04038                     /*%
04039                         $$ = dispatch0(symbols_new);
04040                     %*/
04041                     }
04042                 | symbol_list word ' '
04043                     {
04044                     /*%%%*/
04045                         $2 = evstr2dstr($2);
04046                         nd_set_type($2, NODE_DSYM);
04047                         $$ = list_append($1, $2);
04048                     /*%
04049                         $$ = dispatch2(symbols_add, $1, $2);
04050                     %*/
04051                     }
04052                 ;
04053 
04054 qwords          : tQWORDS_BEG ' ' tSTRING_END
04055                     {
04056                     /*%%%*/
04057                         $$ = NEW_ZARRAY();
04058                     /*%
04059                         $$ = dispatch0(qwords_new);
04060                         $$ = dispatch1(array, $$);
04061                     %*/
04062                     }
04063                 | tQWORDS_BEG qword_list tSTRING_END
04064                     {
04065                     /*%%%*/
04066                         $$ = $2;
04067                     /*%
04068                         $$ = dispatch1(array, $2);
04069                     %*/
04070                     }
04071                 ;
04072 
04073 qsymbols        : tQSYMBOLS_BEG ' ' tSTRING_END
04074                     {
04075                     /*%%%*/
04076                         $$ = NEW_ZARRAY();
04077                     /*%
04078                         $$ = dispatch0(qsymbols_new);
04079                         $$ = dispatch1(array, $$);
04080                     %*/
04081                     }
04082                 | tQSYMBOLS_BEG qsym_list tSTRING_END
04083                     {
04084                     /*%%%*/
04085                         $$ = $2;
04086                     /*%
04087                         $$ = dispatch1(array, $2);
04088                     %*/
04089                     }
04090                 ;
04091 
04092 qword_list      : /* none */
04093                     {
04094                     /*%%%*/
04095                         $$ = 0;
04096                     /*%
04097                         $$ = dispatch0(qwords_new);
04098                     %*/
04099                     }
04100                 | qword_list tSTRING_CONTENT ' '
04101                     {
04102                     /*%%%*/
04103                         $$ = list_append($1, $2);
04104                     /*%
04105                         $$ = dispatch2(qwords_add, $1, $2);
04106                     %*/
04107                     }
04108                 ;
04109 
04110 qsym_list       : /* none */
04111                     {
04112                     /*%%%*/
04113                         $$ = 0;
04114                     /*%
04115                         $$ = dispatch0(qsymbols_new);
04116                     %*/
04117                     }
04118                 | qsym_list tSTRING_CONTENT ' '
04119                     {
04120                     /*%%%*/
04121                         VALUE lit;
04122                         lit = $2->nd_lit;
04123                         $2->nd_lit = ID2SYM(rb_intern_str(lit));
04124                         nd_set_type($2, NODE_LIT);
04125                         $$ = list_append($1, $2);
04126                     /*%
04127                         $$ = dispatch2(qsymbols_add, $1, $2);
04128                     %*/
04129                     }
04130                 ;
04131 
04132 string_contents : /* none */
04133                     {
04134                     /*%%%*/
04135                         $$ = 0;
04136                     /*%
04137                         $$ = dispatch0(string_content);
04138                     %*/
04139                     }
04140                 | string_contents string_content
04141                     {
04142                     /*%%%*/
04143                         $$ = literal_concat($1, $2);
04144                     /*%
04145                         $$ = dispatch2(string_add, $1, $2);
04146                     %*/
04147                     }
04148                 ;
04149 
04150 xstring_contents: /* none */
04151                     {
04152                     /*%%%*/
04153                         $$ = 0;
04154                     /*%
04155                         $$ = dispatch0(xstring_new);
04156                     %*/
04157                     }
04158                 | xstring_contents string_content
04159                     {
04160                     /*%%%*/
04161                         $$ = literal_concat($1, $2);
04162                     /*%
04163                         $$ = dispatch2(xstring_add, $1, $2);
04164                     %*/
04165                     }
04166                 ;
04167 
04168 regexp_contents: /* none */
04169                     {
04170                     /*%%%*/
04171                         $$ = 0;
04172                     /*%
04173                         $$ = dispatch0(regexp_new);
04174                     %*/
04175                     }
04176                 | regexp_contents string_content
04177                     {
04178                     /*%%%*/
04179                         NODE *head = $1, *tail = $2;
04180                         if (!head) {
04181                             $$ = tail;
04182                         }
04183                         else if (!tail) {
04184                             $$ = head;
04185                         }
04186                         else {
04187                             switch (nd_type(head)) {
04188                               case NODE_STR:
04189                                 nd_set_type(head, NODE_DSTR);
04190                                 break;
04191                               case NODE_DSTR:
04192                                 break;
04193                               default:
04194                                 head = list_append(NEW_DSTR(Qnil), head);
04195                                 break;
04196                             }
04197                             $$ = list_append(head, tail);
04198                         }
04199                     /*%
04200                         $$ = dispatch2(regexp_add, $1, $2);
04201                     %*/
04202                     }
04203                 ;
04204 
04205 string_content  : tSTRING_CONTENT
04206                 | tSTRING_DVAR
04207                     {
04208                         $<node>$ = lex_strterm;
04209                         lex_strterm = 0;
04210                         lex_state = EXPR_BEG;
04211                     }
04212                   string_dvar
04213                     {
04214                     /*%%%*/
04215                         lex_strterm = $<node>2;
04216                         $$ = NEW_EVSTR($3);
04217                     /*%
04218                         lex_strterm = $<node>2;
04219                         $$ = dispatch1(string_dvar, $3);
04220                     %*/
04221                     }
04222                 | tSTRING_DBEG
04223                     {
04224                         $<val>1 = cond_stack;
04225                         $<val>$ = cmdarg_stack;
04226                         cond_stack = 0;
04227                         cmdarg_stack = 0;
04228                     }
04229                     {
04230                         $<node>$ = lex_strterm;
04231                         lex_strterm = 0;
04232                         lex_state = EXPR_BEG;
04233                     }
04234                     {
04235                         $<num>$ = brace_nest;
04236                         brace_nest = 0;
04237                     }
04238                   compstmt tSTRING_DEND
04239                     {
04240                         cond_stack = $<val>1;
04241                         cmdarg_stack = $<val>2;
04242                         lex_strterm = $<node>3;
04243                         brace_nest = $<num>4;
04244                     /*%%%*/
04245                         if ($5) $5->flags &= ~NODE_FL_NEWLINE;
04246                         $$ = new_evstr($5);
04247                     /*%
04248                         $$ = dispatch1(string_embexpr, $5);
04249                     %*/
04250                     }
04251                 ;
04252 
04253 string_dvar     : tGVAR
04254                     {
04255                     /*%%%*/
04256                         $$ = NEW_GVAR($1);
04257                     /*%
04258                         $$ = dispatch1(var_ref, $1);
04259                     %*/
04260                     }
04261                 | tIVAR
04262                     {
04263                     /*%%%*/
04264                         $$ = NEW_IVAR($1);
04265                     /*%
04266                         $$ = dispatch1(var_ref, $1);
04267                     %*/
04268                     }
04269                 | tCVAR
04270                     {
04271                     /*%%%*/
04272                         $$ = NEW_CVAR($1);
04273                     /*%
04274                         $$ = dispatch1(var_ref, $1);
04275                     %*/
04276                     }
04277                 | backref
04278                 ;
04279 
04280 symbol          : tSYMBEG sym
04281                     {
04282                         lex_state = EXPR_END;
04283                     /*%%%*/
04284                         $$ = $2;
04285                     /*%
04286                         $$ = dispatch1(symbol, $2);
04287                     %*/
04288                     }
04289                 ;
04290 
04291 sym             : fname
04292                 | tIVAR
04293                 | tGVAR
04294                 | tCVAR
04295                 ;
04296 
04297 dsym            : tSYMBEG xstring_contents tSTRING_END
04298                     {
04299                         lex_state = EXPR_END;
04300                     /*%%%*/
04301                         $$ = dsym_node($2);
04302                     /*%
04303                         $$ = dispatch1(dyna_symbol, $2);
04304                     %*/
04305                     }
04306                 ;
04307 
04308 numeric         : tINTEGER
04309                 | tFLOAT
04310                 | tUMINUS_NUM tINTEGER         %prec tLOWEST
04311                     {
04312                     /*%%%*/
04313                         $$ = negate_lit($2);
04314                     /*%
04315                         $$ = dispatch2(unary, ripper_intern("-@"), $2);
04316                     %*/
04317                     }
04318                 | tUMINUS_NUM tFLOAT           %prec tLOWEST
04319                     {
04320                     /*%%%*/
04321                         $$ = negate_lit($2);
04322                     /*%
04323                         $$ = dispatch2(unary, ripper_intern("-@"), $2);
04324                     %*/
04325                     }
04326                 ;
04327 
04328 user_variable   : tIDENTIFIER
04329                 | tIVAR
04330                 | tGVAR
04331                 | tCONSTANT
04332                 | tCVAR
04333                 ;
04334 
04335 keyword_variable: keyword_nil {ifndef_ripper($$ = keyword_nil);}
04336                 | keyword_self {ifndef_ripper($$ = keyword_self);}
04337                 | keyword_true {ifndef_ripper($$ = keyword_true);}
04338                 | keyword_false {ifndef_ripper($$ = keyword_false);}
04339                 | keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);}
04340                 | keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);}
04341                 | keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);}
04342                 ;
04343 
04344 var_ref         : user_variable
04345                     {
04346                     /*%%%*/
04347                         if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
04348                     /*%
04349                         if (id_is_var(get_id($1))) {
04350                             $$ = dispatch1(var_ref, $1);
04351                         }
04352                         else {
04353                             $$ = dispatch1(vcall, $1);
04354                         }
04355                     %*/
04356                     }
04357                 | keyword_variable
04358                     {
04359                     /*%%%*/
04360                         if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
04361                     /*%
04362                         $$ = dispatch1(var_ref, $1);
04363                     %*/
04364                     }
04365                 ;
04366 
04367 var_lhs         : user_variable
04368                     {
04369                         $$ = assignable($1, 0);
04370                     /*%%%*/
04371                     /*%
04372                         $$ = dispatch1(var_field, $$);
04373                     %*/
04374                     }
04375                 | keyword_variable
04376                     {
04377                         $$ = assignable($1, 0);
04378                     /*%%%*/
04379                     /*%
04380                         $$ = dispatch1(var_field, $$);
04381                     %*/
04382                     }
04383                 ;
04384 
04385 backref         : tNTH_REF
04386                 | tBACK_REF
04387                 ;
04388 
04389 superclass      : term
04390                     {
04391                     /*%%%*/
04392                         $$ = 0;
04393                     /*%
04394                         $$ = Qnil;
04395                     %*/
04396                     }
04397                 | '<'
04398                     {
04399                         lex_state = EXPR_BEG;
04400                         command_start = TRUE;
04401                     }
04402                   expr_value term
04403                     {
04404                         $$ = $3;
04405                     }
04406                 | error term
04407                     {
04408                     /*%%%*/
04409                         yyerrok;
04410                         $$ = 0;
04411                     /*%
04412                         yyerrok;
04413                         $$ = Qnil;
04414                     %*/
04415                     }
04416                 ;
04417 
04418 f_arglist       : '(' f_args rparen
04419                     {
04420                     /*%%%*/
04421                         $$ = $2;
04422                     /*%
04423                         $$ = dispatch1(paren, $2);
04424                     %*/
04425                         lex_state = EXPR_BEG;
04426                         command_start = TRUE;
04427                     }
04428                 | f_args term
04429                     {
04430                         $$ = $1;
04431                         lex_state = EXPR_BEG;
04432                         command_start = TRUE;
04433                     }
04434                 ;
04435 
04436 args_tail       : f_kwarg ',' f_kwrest opt_f_block_arg
04437                     {
04438                         $$ = new_args_tail($1, $3, $4);
04439                     }
04440                 | f_kwarg opt_f_block_arg
04441                     {
04442                         $$ = new_args_tail($1, Qnone, $2);
04443                     }
04444                 | f_kwrest opt_f_block_arg
04445                     {
04446                         $$ = new_args_tail(Qnone, $1, $2);
04447                     }
04448                 | f_block_arg
04449                     {
04450                         $$ = new_args_tail(Qnone, Qnone, $1);
04451                     }
04452                 ;
04453 
04454 opt_args_tail   : ',' args_tail
04455                     {
04456                         $$ = $2;
04457                     }
04458                 | /* none */
04459                     {
04460                         $$ = new_args_tail(Qnone, Qnone, Qnone);
04461                     }
04462                 ;
04463 
04464 f_args          : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
04465                     {
04466                         $$ = new_args($1, $3, $5, Qnone, $6);
04467                     }
04468                 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
04469                     {
04470                         $$ = new_args($1, $3, $5, $7, $8);
04471                     }
04472                 | f_arg ',' f_optarg opt_args_tail
04473                     {
04474                         $$ = new_args($1, $3, Qnone, Qnone, $4);
04475                     }
04476                 | f_arg ',' f_optarg ',' f_arg opt_args_tail
04477                     {
04478                         $$ = new_args($1, $3, Qnone, $5, $6);
04479                     }
04480                 | f_arg ',' f_rest_arg opt_args_tail
04481                     {
04482                         $$ = new_args($1, Qnone, $3, Qnone, $4);
04483                     }
04484                 | f_arg ',' f_rest_arg ',' f_arg opt_args_tail
04485                     {
04486                         $$ = new_args($1, Qnone, $3, $5, $6);
04487                     }
04488                 | f_arg opt_args_tail
04489                     {
04490                         $$ = new_args($1, Qnone, Qnone, Qnone, $2);
04491                     }
04492                 | f_optarg ',' f_rest_arg opt_args_tail
04493                     {
04494                         $$ = new_args(Qnone, $1, $3, Qnone, $4);
04495                     }
04496                 | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
04497                     {
04498                         $$ = new_args(Qnone, $1, $3, $5, $6);
04499                     }
04500                 | f_optarg opt_args_tail
04501                     {
04502                         $$ = new_args(Qnone, $1, Qnone, Qnone, $2);
04503                     }
04504                 | f_optarg ',' f_arg opt_args_tail
04505                     {
04506                         $$ = new_args(Qnone, $1, Qnone, $3, $4);
04507                     }
04508                 | f_rest_arg opt_args_tail
04509                     {
04510                         $$ = new_args(Qnone, Qnone, $1, Qnone, $2);
04511                     }
04512                 | f_rest_arg ',' f_arg opt_args_tail
04513                     {
04514                         $$ = new_args(Qnone, Qnone, $1, $3, $4);
04515                     }
04516                 | args_tail
04517                     {
04518                         $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1);
04519                     }
04520                 | /* none */
04521                     {
04522                         $$ = new_args_tail(Qnone, Qnone, Qnone);
04523                         $$ = new_args(Qnone, Qnone, Qnone, Qnone, $$);
04524                     }
04525                 ;
04526 
04527 f_bad_arg       : tCONSTANT
04528                     {
04529                     /*%%%*/
04530                         yyerror("formal argument cannot be a constant");
04531                         $$ = 0;
04532                     /*%
04533                         $$ = dispatch1(param_error, $1);
04534                     %*/
04535                     }
04536                 | tIVAR
04537                     {
04538                     /*%%%*/
04539                         yyerror("formal argument cannot be an instance variable");
04540                         $$ = 0;
04541                     /*%
04542                         $$ = dispatch1(param_error, $1);
04543                     %*/
04544                     }
04545                 | tGVAR
04546                     {
04547                     /*%%%*/
04548                         yyerror("formal argument cannot be a global variable");
04549                         $$ = 0;
04550                     /*%
04551                         $$ = dispatch1(param_error, $1);
04552                     %*/
04553                     }
04554                 | tCVAR
04555                     {
04556                     /*%%%*/
04557                         yyerror("formal argument cannot be a class variable");
04558                         $$ = 0;
04559                     /*%
04560                         $$ = dispatch1(param_error, $1);
04561                     %*/
04562                     }
04563                 ;
04564 
04565 f_norm_arg      : f_bad_arg
04566                 | tIDENTIFIER
04567                     {
04568                         formal_argument(get_id($1));
04569                         $$ = $1;
04570                     }
04571                 ;
04572 
04573 f_arg_item      : f_norm_arg
04574                     {
04575                         arg_var(get_id($1));
04576                     /*%%%*/
04577                         $$ = NEW_ARGS_AUX($1, 1);
04578                     /*%
04579                         $$ = get_value($1);
04580                     %*/
04581                     }
04582                 | tLPAREN f_margs rparen
04583                     {
04584                         ID tid = internal_id();
04585                         arg_var(tid);
04586                     /*%%%*/
04587                         if (dyna_in_block()) {
04588                             $2->nd_value = NEW_DVAR(tid);
04589                         }
04590                         else {
04591                             $2->nd_value = NEW_LVAR(tid);
04592                         }
04593                         $$ = NEW_ARGS_AUX(tid, 1);
04594                         $$->nd_next = $2;
04595                     /*%
04596                         $$ = dispatch1(mlhs_paren, $2);
04597                     %*/
04598                     }
04599                 ;
04600 
04601 f_arg           : f_arg_item
04602                     /*%c%*/
04603                     /*%c
04604                     {
04605                         $$ = rb_ary_new3(1, $1);
04606                     }
04607                     c%*/
04608                 | f_arg ',' f_arg_item
04609                     {
04610                     /*%%%*/
04611                         $$ = $1;
04612                         $$->nd_plen++;
04613                         $$->nd_next = block_append($$->nd_next, $3->nd_next);
04614                         rb_gc_force_recycle((VALUE)$3);
04615                     /*%
04616                         $$ = rb_ary_push($1, $3);
04617                     %*/
04618                     }
04619                 ;
04620 
04621 f_kw            : tLABEL arg_value
04622                     {
04623                         arg_var(formal_argument(get_id($1)));
04624                         $$ = assignable($1, $2);
04625                     /*%%%*/
04626                         $$ = NEW_KW_ARG(0, $$);
04627                     /*%
04628                         $$ = rb_assoc_new($$, $2);
04629                     %*/
04630                     }
04631                 ;
04632 
04633 f_block_kw      : tLABEL primary_value
04634                     {
04635                         arg_var(formal_argument(get_id($1)));
04636                         $$ = assignable($1, $2);
04637                     /*%%%*/
04638                         $$ = NEW_KW_ARG(0, $$);
04639                     /*%
04640                         $$ = rb_assoc_new($$, $2);
04641                     %*/
04642                     }
04643                 ;
04644 
04645 f_block_kwarg   : f_block_kw
04646                     {
04647                     /*%%%*/
04648                         $$ = $1;
04649                     /*%
04650                         $$ = rb_ary_new3(1, $1);
04651                     %*/
04652                     }
04653                 | f_block_kwarg ',' f_block_kw
04654                     {
04655                     /*%%%*/
04656                         NODE *kws = $1;
04657 
04658                         while (kws->nd_next) {
04659                             kws = kws->nd_next;
04660                         }
04661                         kws->nd_next = $3;
04662                         $$ = $1;
04663                     /*%
04664                         $$ = rb_ary_push($1, $3);
04665                     %*/
04666                     }
04667                 ;
04668 
04669 
04670 f_kwarg         : f_kw
04671                     {
04672                     /*%%%*/
04673                         $$ = $1;
04674                     /*%
04675                         $$ = rb_ary_new3(1, $1);
04676                     %*/
04677                     }
04678                 | f_kwarg ',' f_kw
04679                     {
04680                     /*%%%*/
04681                         NODE *kws = $1;
04682 
04683                         while (kws->nd_next) {
04684                             kws = kws->nd_next;
04685                         }
04686                         kws->nd_next = $3;
04687                         $$ = $1;
04688                     /*%
04689                         $$ = rb_ary_push($1, $3);
04690                     %*/
04691                     }
04692                 ;
04693 
04694 kwrest_mark     : tPOW
04695                 | tDSTAR
04696                 ;
04697 
04698 f_kwrest        : kwrest_mark tIDENTIFIER
04699                     {
04700                         shadowing_lvar(get_id($2));
04701                         $$ = $2;
04702                     }
04703                 | kwrest_mark
04704                     {
04705                         $$ = internal_id();
04706                     }
04707                 ;
04708 
04709 f_opt           : tIDENTIFIER '=' arg_value
04710                     {
04711                         arg_var(formal_argument(get_id($1)));
04712                         $$ = assignable($1, $3);
04713                     /*%%%*/
04714                         $$ = NEW_OPT_ARG(0, $$);
04715                     /*%
04716                         $$ = rb_assoc_new($$, $3);
04717                     %*/
04718                     }
04719                 ;
04720 
04721 f_block_opt     : tIDENTIFIER '=' primary_value
04722                     {
04723                         arg_var(formal_argument(get_id($1)));
04724                         $$ = assignable($1, $3);
04725                     /*%%%*/
04726                         $$ = NEW_OPT_ARG(0, $$);
04727                     /*%
04728                         $$ = rb_assoc_new($$, $3);
04729                     %*/
04730                     }
04731                 ;
04732 
04733 f_block_optarg  : f_block_opt
04734                     {
04735                     /*%%%*/
04736                         $$ = $1;
04737                     /*%
04738                         $$ = rb_ary_new3(1, $1);
04739                     %*/
04740                     }
04741                 | f_block_optarg ',' f_block_opt
04742                     {
04743                     /*%%%*/
04744                         NODE *opts = $1;
04745 
04746                         while (opts->nd_next) {
04747                             opts = opts->nd_next;
04748                         }
04749                         opts->nd_next = $3;
04750                         $$ = $1;
04751                     /*%
04752                         $$ = rb_ary_push($1, $3);
04753                     %*/
04754                     }
04755                 ;
04756 
04757 f_optarg        : f_opt
04758                     {
04759                     /*%%%*/
04760                         $$ = $1;
04761                     /*%
04762                         $$ = rb_ary_new3(1, $1);
04763                     %*/
04764                     }
04765                 | f_optarg ',' f_opt
04766                     {
04767                     /*%%%*/
04768                         NODE *opts = $1;
04769 
04770                         while (opts->nd_next) {
04771                             opts = opts->nd_next;
04772                         }
04773                         opts->nd_next = $3;
04774                         $$ = $1;
04775                     /*%
04776                         $$ = rb_ary_push($1, $3);
04777                     %*/
04778                     }
04779                 ;
04780 
04781 restarg_mark    : '*'
04782                 | tSTAR
04783                 ;
04784 
04785 f_rest_arg      : restarg_mark tIDENTIFIER
04786                     {
04787                     /*%%%*/
04788                         if (!is_local_id($2))
04789                             yyerror("rest argument must be local variable");
04790                     /*% %*/
04791                         arg_var(shadowing_lvar(get_id($2)));
04792                     /*%%%*/
04793                         $$ = $2;
04794                     /*%
04795                         $$ = dispatch1(rest_param, $2);
04796                     %*/
04797                     }
04798                 | restarg_mark
04799                     {
04800                     /*%%%*/
04801                         $$ = internal_id();
04802                         arg_var($$);
04803                     /*%
04804                         $$ = dispatch1(rest_param, Qnil);
04805                     %*/
04806                     }
04807                 ;
04808 
04809 blkarg_mark     : '&'
04810                 | tAMPER
04811                 ;
04812 
04813 f_block_arg     : blkarg_mark tIDENTIFIER
04814                     {
04815                     /*%%%*/
04816                         if (!is_local_id($2))
04817                             yyerror("block argument must be local variable");
04818                         else if (!dyna_in_block() && local_id($2))
04819                             yyerror("duplicated block argument name");
04820                     /*% %*/
04821                         arg_var(shadowing_lvar(get_id($2)));
04822                     /*%%%*/
04823                         $$ = $2;
04824                     /*%
04825                         $$ = dispatch1(blockarg, $2);
04826                     %*/
04827                     }
04828                 ;
04829 
04830 opt_f_block_arg : ',' f_block_arg
04831                     {
04832                         $$ = $2;
04833                     }
04834                 | none
04835                     {
04836                     /*%%%*/
04837                         $$ = 0;
04838                     /*%
04839                         $$ = Qundef;
04840                     %*/
04841                     }
04842                 ;
04843 
04844 singleton       : var_ref
04845                     {
04846                     /*%%%*/
04847                         value_expr($1);
04848                         $$ = $1;
04849                         if (!$$) $$ = NEW_NIL();
04850                     /*%
04851                         $$ = $1;
04852                     %*/
04853                     }
04854                 | '(' {lex_state = EXPR_BEG;} expr rparen
04855                     {
04856                     /*%%%*/
04857                         if ($3 == 0) {
04858                             yyerror("can't define singleton method for ().");
04859                         }
04860                         else {
04861                             switch (nd_type($3)) {
04862                               case NODE_STR:
04863                               case NODE_DSTR:
04864                               case NODE_XSTR:
04865                               case NODE_DXSTR:
04866                               case NODE_DREGX:
04867                               case NODE_LIT:
04868                               case NODE_ARRAY:
04869                               case NODE_ZARRAY:
04870                                 yyerror("can't define singleton method for literals");
04871                               default:
04872                                 value_expr($3);
04873                                 break;
04874                             }
04875                         }
04876                         $$ = $3;
04877                     /*%
04878                         $$ = dispatch1(paren, $3);
04879                     %*/
04880                     }
04881                 ;
04882 
04883 assoc_list      : none
04884                 | assocs trailer
04885                     {
04886                     /*%%%*/
04887                         $$ = $1;
04888                     /*%
04889                         $$ = dispatch1(assoclist_from_args, $1);
04890                     %*/
04891                     }
04892                 ;
04893 
04894 assocs          : assoc
04895                     /*%c%*/
04896                     /*%c
04897                     {
04898                         $$ = rb_ary_new3(1, $1);
04899                     }
04900                     %*/
04901                 | assocs ',' assoc
04902                     {
04903                     /*%%%*/
04904                         $$ = list_concat($1, $3);
04905                     /*%
04906                         $$ = rb_ary_push($1, $3);
04907                     %*/
04908                     }
04909                 ;
04910 
04911 assoc           : arg_value tASSOC arg_value
04912                     {
04913                     /*%%%*/
04914                         $$ = list_append(NEW_LIST($1), $3);
04915                     /*%
04916                         $$ = dispatch2(assoc_new, $1, $3);
04917                     %*/
04918                     }
04919                 | tLABEL arg_value
04920                     {
04921                     /*%%%*/
04922                         $$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
04923                     /*%
04924                         $$ = dispatch2(assoc_new, $1, $2);
04925                     %*/
04926                     }
04927                 | tDSTAR arg_value
04928                     {
04929                     /*%%%*/
04930                         $$ = list_append(NEW_LIST(0), $2);
04931                     /*%
04932                         $$ = dispatch1(assoc_splat, $2);
04933                     %*/
04934                     }
04935                 ;
04936 
04937                 ;
04938 
04939 operation       : tIDENTIFIER
04940                 | tCONSTANT
04941                 | tFID
04942                 ;
04943 
04944 operation2      : tIDENTIFIER
04945                 | tCONSTANT
04946                 | tFID
04947                 | op
04948                 ;
04949 
04950 operation3      : tIDENTIFIER
04951                 | tFID
04952                 | op
04953                 ;
04954 
04955 dot_or_colon    : '.'
04956                     /*%c%*/
04957                     /*%c
04958                     { $$ = $<val>1; }
04959                     %*/
04960                 | tCOLON2
04961                     /*%c%*/
04962                     /*%c
04963                     { $$ = $<val>1; }
04964                     %*/
04965                 ;
04966 
04967 opt_terms       : /* none */
04968                 | terms
04969                 ;
04970 
04971 opt_nl          : /* none */
04972                 | '\n'
04973                 ;
04974 
04975 rparen          : opt_nl ')'
04976                 ;
04977 
04978 rbracket        : opt_nl ']'
04979                 ;
04980 
04981 trailer         : /* none */
04982                 | '\n'
04983                 | ','
04984                 ;
04985 
04986 term            : ';' {yyerrok;}
04987                 | '\n'
04988                 ;
04989 
04990 terms           : term
04991                 | terms ';' {yyerrok;}
04992                 ;
04993 
04994 none            : /* none */
04995                     {
04996                     /*%%%*/
04997                         $$ = 0;
04998                     /*%
04999                         $$ = Qundef;
05000                     %*/
05001                     }
05002                 ;
05003 %%
05004 # undef parser
05005 # undef yylex
05006 # undef yylval
05007 # define yylval  (*((YYSTYPE*)(parser->parser_yylval)))
05008 
05009 static int parser_regx_options(struct parser_params*);
05010 static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);
05011 static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);
05012 static int parser_parse_string(struct parser_params*,NODE*);
05013 static int parser_here_document(struct parser_params*,NODE*);
05014 
05015 
05016 # define nextc()                   parser_nextc(parser)
05017 # define pushback(c)               parser_pushback(parser, (c))
05018 # define newtok()                  parser_newtok(parser)
05019 # define tokspace(n)               parser_tokspace(parser, (n))
05020 # define tokadd(c)                 parser_tokadd(parser, (c))
05021 # define tok_hex(numlen)           parser_tok_hex(parser, (numlen))
05022 # define read_escape(flags,e)      parser_read_escape(parser, (flags), (e))
05023 # define tokadd_escape(e)          parser_tokadd_escape(parser, (e))
05024 # define regx_options()            parser_regx_options(parser)
05025 # define tokadd_string(f,t,p,n,e)  parser_tokadd_string(parser,(f),(t),(p),(n),(e))
05026 # define parse_string(n)           parser_parse_string(parser,(n))
05027 # define tokaddmbc(c, enc)         parser_tokaddmbc(parser, (c), (enc))
05028 # define here_document(n)          parser_here_document(parser,(n))
05029 # define heredoc_identifier()      parser_heredoc_identifier(parser)
05030 # define heredoc_restore(n)        parser_heredoc_restore(parser,(n))
05031 # define whole_match_p(e,l,i)      parser_whole_match_p(parser,(e),(l),(i))
05032 
05033 #ifndef RIPPER
05034 # define set_yylval_str(x) (yylval.node = NEW_STR(x))
05035 # define set_yylval_num(x) (yylval.num = (x))
05036 # define set_yylval_id(x)  (yylval.id = (x))
05037 # define set_yylval_name(x)  (yylval.id = (x))
05038 # define set_yylval_literal(x) (yylval.node = NEW_LIT(x))
05039 # define set_yylval_node(x) (yylval.node = (x))
05040 # define yylval_id() (yylval.id)
05041 #else
05042 static inline VALUE
05043 ripper_yylval_id(ID x)
05044 {
05045     return (VALUE)NEW_LASGN(x, ID2SYM(x));
05046 }
05047 # define set_yylval_str(x) (void)(x)
05048 # define set_yylval_num(x) (void)(x)
05049 # define set_yylval_id(x)  (void)(x)
05050 # define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(x))
05051 # define set_yylval_literal(x) (void)(x)
05052 # define set_yylval_node(x) (void)(x)
05053 # define yylval_id() yylval.id
05054 #endif
05055 
05056 #ifndef RIPPER
05057 #define ripper_flush(p) (void)(p)
05058 #else
05059 #define ripper_flush(p) ((p)->tokp = (p)->parser_lex_p)
05060 
05061 #define yylval_rval (*(RB_TYPE_P(yylval.val, T_NODE) ? &yylval.node->nd_rval : &yylval.val))
05062 
05063 static int
05064 ripper_has_scan_event(struct parser_params *parser)
05065 {
05066 
05067     if (lex_p < parser->tokp) rb_raise(rb_eRuntimeError, "lex_p < tokp");
05068     return lex_p > parser->tokp;
05069 }
05070 
05071 static VALUE
05072 ripper_scan_event_val(struct parser_params *parser, int t)
05073 {
05074     VALUE str = STR_NEW(parser->tokp, lex_p - parser->tokp);
05075     VALUE rval = ripper_dispatch1(parser, ripper_token2eventid(t), str);
05076     ripper_flush(parser);
05077     return rval;
05078 }
05079 
05080 static void
05081 ripper_dispatch_scan_event(struct parser_params *parser, int t)
05082 {
05083     if (!ripper_has_scan_event(parser)) return;
05084     yylval_rval = ripper_scan_event_val(parser, t);
05085 }
05086 
05087 static void
05088 ripper_dispatch_ignored_scan_event(struct parser_params *parser, int t)
05089 {
05090     if (!ripper_has_scan_event(parser)) return;
05091     (void)ripper_scan_event_val(parser, t);
05092 }
05093 
05094 static void
05095 ripper_dispatch_delayed_token(struct parser_params *parser, int t)
05096 {
05097     int saved_line = ruby_sourceline;
05098     const char *saved_tokp = parser->tokp;
05099 
05100     ruby_sourceline = parser->delayed_line;
05101     parser->tokp = lex_pbeg + parser->delayed_col;
05102     yylval_rval = ripper_dispatch1(parser, ripper_token2eventid(t), parser->delayed);
05103     parser->delayed = Qnil;
05104     ruby_sourceline = saved_line;
05105     parser->tokp = saved_tokp;
05106 }
05107 #endif /* RIPPER */
05108 
05109 #include "ruby/regex.h"
05110 #include "ruby/util.h"
05111 
05112 /* We remove any previous definition of `SIGN_EXTEND_CHAR',
05113    since ours (we hope) works properly with all combinations of
05114    machines, compilers, `char' and `unsigned char' argument types.
05115    (Per Bothner suggested the basic approach.)  */
05116 #undef SIGN_EXTEND_CHAR
05117 #if __STDC__
05118 # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
05119 #else  /* not __STDC__ */
05120 /* As in Harbison and Steele.  */
05121 # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
05122 #endif
05123 
05124 #define parser_encoding_name()  (current_enc->name)
05125 #define parser_mbclen()  mbclen((lex_p-1),lex_pend,current_enc)
05126 #define parser_precise_mbclen()  rb_enc_precise_mbclen((lex_p-1),lex_pend,current_enc)
05127 #define is_identchar(p,e,enc) (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))
05128 #define parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,current_enc))
05129 
05130 #define parser_isascii() ISASCII(*(lex_p-1))
05131 
05132 #ifndef RIPPER
05133 static int
05134 token_info_get_column(struct parser_params *parser, const char *token)
05135 {
05136     int column = 1;
05137     const char *p, *pend = lex_p - strlen(token);
05138     for (p = lex_pbeg; p < pend; p++) {
05139         if (*p == '\t') {
05140             column = (((column - 1) / 8) + 1) * 8;
05141         }
05142         column++;
05143     }
05144     return column;
05145 }
05146 
05147 static int
05148 token_info_has_nonspaces(struct parser_params *parser, const char *token)
05149 {
05150     const char *p, *pend = lex_p - strlen(token);
05151     for (p = lex_pbeg; p < pend; p++) {
05152         if (*p != ' ' && *p != '\t') {
05153             return 1;
05154         }
05155     }
05156     return 0;
05157 }
05158 
05159 #undef token_info_push
05160 static void
05161 token_info_push(struct parser_params *parser, const char *token)
05162 {
05163     token_info *ptinfo;
05164 
05165     if (!parser->parser_token_info_enabled) return;
05166     ptinfo = ALLOC(token_info);
05167     ptinfo->token = token;
05168     ptinfo->linenum = ruby_sourceline;
05169     ptinfo->column = token_info_get_column(parser, token);
05170     ptinfo->nonspc = token_info_has_nonspaces(parser, token);
05171     ptinfo->next = parser->parser_token_info;
05172 
05173     parser->parser_token_info = ptinfo;
05174 }
05175 
05176 #undef token_info_pop
05177 static void
05178 token_info_pop(struct parser_params *parser, const char *token)
05179 {
05180     int linenum;
05181     token_info *ptinfo = parser->parser_token_info;
05182 
05183     if (!ptinfo) return;
05184     parser->parser_token_info = ptinfo->next;
05185     if (token_info_get_column(parser, token) == ptinfo->column) { /* OK */
05186         goto finish;
05187     }
05188     linenum = ruby_sourceline;
05189     if (linenum == ptinfo->linenum) { /* SKIP */
05190         goto finish;
05191     }
05192     if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) { /* SKIP */
05193         goto finish;
05194     }
05195     if (parser->parser_token_info_enabled) {
05196         rb_compile_warn(ruby_sourcefile, linenum,
05197                         "mismatched indentations at '%s' with '%s' at %d",
05198                         token, ptinfo->token, ptinfo->linenum);
05199     }
05200 
05201   finish:
05202     xfree(ptinfo);
05203 }
05204 #endif  /* RIPPER */
05205 
05206 static int
05207 parser_yyerror(struct parser_params *parser, const char *msg)
05208 {
05209 #ifndef RIPPER
05210     const int max_line_margin = 30;
05211     const char *p, *pe;
05212     char *buf;
05213     long len;
05214     int i;
05215 
05216     compile_error(PARSER_ARG "%s", msg);
05217     p = lex_p;
05218     while (lex_pbeg <= p) {
05219         if (*p == '\n') break;
05220         p--;
05221     }
05222     p++;
05223 
05224     pe = lex_p;
05225     while (pe < lex_pend) {
05226         if (*pe == '\n') break;
05227         pe++;
05228     }
05229 
05230     len = pe - p;
05231     if (len > 4) {
05232         char *p2;
05233         const char *pre = "", *post = "";
05234 
05235         if (len > max_line_margin * 2 + 10) {
05236             if (lex_p - p > max_line_margin) {
05237                 p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline));
05238                 pre = "...";
05239             }
05240             if (pe - lex_p > max_line_margin) {
05241                 pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline));
05242                 post = "...";
05243             }
05244             len = pe - p;
05245         }
05246         buf = ALLOCA_N(char, len+2);
05247         MEMCPY(buf, p, char, len);
05248         buf[len] = '\0';
05249         rb_compile_error_with_enc(NULL, 0, (void *)current_enc, "%s%s%s", pre, buf, post);
05250 
05251         i = (int)(lex_p - p);
05252         p2 = buf; pe = buf + len;
05253 
05254         while (p2 < pe) {
05255             if (*p2 != '\t') *p2 = ' ';
05256             p2++;
05257         }
05258         buf[i] = '^';
05259         buf[i+1] = '\0';
05260         rb_compile_error_append("%s%s", pre, buf);
05261     }
05262 #else
05263     dispatch1(parse_error, STR_NEW2(msg));
05264 #endif /* !RIPPER */
05265     return 0;
05266 }
05267 
05268 static void parser_prepare(struct parser_params *parser);
05269 
05270 #ifndef RIPPER
05271 static VALUE
05272 debug_lines(VALUE fname)
05273 {
05274     ID script_lines;
05275     CONST_ID(script_lines, "SCRIPT_LINES__");
05276     if (rb_const_defined_at(rb_cObject, script_lines)) {
05277         VALUE hash = rb_const_get_at(rb_cObject, script_lines);
05278         if (RB_TYPE_P(hash, T_HASH)) {
05279             VALUE lines = rb_ary_new();
05280             rb_hash_aset(hash, fname, lines);
05281             return lines;
05282         }
05283     }
05284     return 0;
05285 }
05286 
05287 static VALUE
05288 coverage(VALUE fname, int n)
05289 {
05290     VALUE coverages = rb_get_coverages();
05291     if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
05292         VALUE lines = rb_ary_new2(n);
05293         int i;
05294         RBASIC(lines)->klass = 0;
05295         for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
05296         RARRAY(lines)->as.heap.len = n;
05297         rb_hash_aset(coverages, fname, lines);
05298         return lines;
05299     }
05300     return 0;
05301 }
05302 
05303 static int
05304 e_option_supplied(struct parser_params *parser)
05305 {
05306     return strcmp(ruby_sourcefile, "-e") == 0;
05307 }
05308 
05309 static VALUE
05310 yycompile0(VALUE arg)
05311 {
05312     int n;
05313     NODE *tree;
05314     struct parser_params *parser = (struct parser_params *)arg;
05315 
05316     if (!compile_for_eval && rb_safe_level() == 0) {
05317         ruby_debug_lines = debug_lines(ruby_sourcefile_string);
05318         if (ruby_debug_lines && ruby_sourceline > 0) {
05319             VALUE str = STR_NEW0();
05320             n = ruby_sourceline;
05321             do {
05322                 rb_ary_push(ruby_debug_lines, str);
05323             } while (--n);
05324         }
05325 
05326         if (!e_option_supplied(parser)) {
05327             ruby_coverage = coverage(ruby_sourcefile_string, ruby_sourceline);
05328         }
05329     }
05330 
05331     parser_prepare(parser);
05332     deferred_nodes = 0;
05333 #ifndef RIPPER
05334     parser->parser_token_info_enabled = !compile_for_eval && RTEST(ruby_verbose);
05335 #endif
05336 #ifndef RIPPER
05337     if (RUBY_DTRACE_PARSE_BEGIN_ENABLED()) {
05338         RUBY_DTRACE_PARSE_BEGIN(parser->parser_ruby_sourcefile,
05339                                 parser->parser_ruby_sourceline);
05340     }
05341 #endif
05342     n = yyparse((void*)parser);
05343 #ifndef RIPPER
05344     if (RUBY_DTRACE_PARSE_END_ENABLED()) {
05345         RUBY_DTRACE_PARSE_END(parser->parser_ruby_sourcefile,
05346                               parser->parser_ruby_sourceline);
05347     }
05348 #endif
05349     ruby_debug_lines = 0;
05350     ruby_coverage = 0;
05351     compile_for_eval = 0;
05352 
05353     lex_strterm = 0;
05354     lex_p = lex_pbeg = lex_pend = 0;
05355     lex_lastline = lex_nextline = 0;
05356     if (parser->nerr) {
05357         return 0;
05358     }
05359     tree = ruby_eval_tree;
05360     if (!tree) {
05361         tree = NEW_NIL();
05362     }
05363     else if (ruby_eval_tree_begin) {
05364         tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body);
05365     }
05366     return (VALUE)tree;
05367 }
05368 
05369 static NODE*
05370 yycompile(struct parser_params *parser, VALUE fname, int line)
05371 {
05372     ruby_sourcefile_string = rb_str_new_frozen(fname);
05373     ruby_sourcefile = RSTRING_PTR(fname);
05374     ruby_sourceline = line - 1;
05375     return (NODE *)rb_suppress_tracing(yycompile0, (VALUE)parser);
05376 }
05377 #endif /* !RIPPER */
05378 
05379 static rb_encoding *
05380 must_be_ascii_compatible(VALUE s)
05381 {
05382     rb_encoding *enc = rb_enc_get(s);
05383     if (!rb_enc_asciicompat(enc)) {
05384         rb_raise(rb_eArgError, "invalid source encoding");
05385     }
05386     return enc;
05387 }
05388 
05389 static VALUE
05390 lex_get_str(struct parser_params *parser, VALUE s)
05391 {
05392     char *beg, *end, *pend;
05393     rb_encoding *enc = must_be_ascii_compatible(s);
05394 
05395     beg = RSTRING_PTR(s);
05396     if (lex_gets_ptr) {
05397         if (RSTRING_LEN(s) == lex_gets_ptr) return Qnil;
05398         beg += lex_gets_ptr;
05399     }
05400     pend = RSTRING_PTR(s) + RSTRING_LEN(s);
05401     end = beg;
05402     while (end < pend) {
05403         if (*end++ == '\n') break;
05404     }
05405     lex_gets_ptr = end - RSTRING_PTR(s);
05406     return rb_enc_str_new(beg, end - beg, enc);
05407 }
05408 
05409 static VALUE
05410 lex_getline(struct parser_params *parser)
05411 {
05412     VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input);
05413     if (NIL_P(line)) return line;
05414     must_be_ascii_compatible(line);
05415 #ifndef RIPPER
05416     if (ruby_debug_lines) {
05417         rb_enc_associate(line, current_enc);
05418         rb_ary_push(ruby_debug_lines, line);
05419     }
05420     if (ruby_coverage) {
05421         rb_ary_push(ruby_coverage, Qnil);
05422     }
05423 #endif
05424     return line;
05425 }
05426 
05427 #ifdef RIPPER
05428 static rb_data_type_t parser_data_type;
05429 #else
05430 static const rb_data_type_t parser_data_type;
05431 
05432 static NODE*
05433 parser_compile_string(volatile VALUE vparser, VALUE fname, VALUE s, int line)
05434 {
05435     struct parser_params *parser;
05436     NODE *node;
05437 
05438     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05439     lex_gets = lex_get_str;
05440     lex_gets_ptr = 0;
05441     lex_input = s;
05442     lex_pbeg = lex_p = lex_pend = 0;
05443     compile_for_eval = rb_parse_in_eval();
05444 
05445     node = yycompile(parser, fname, line);
05446     RB_GC_GUARD(vparser); /* prohibit tail call optimization */
05447 
05448     return node;
05449 }
05450 
05451 NODE*
05452 rb_compile_string(const char *f, VALUE s, int line)
05453 {
05454     must_be_ascii_compatible(s);
05455     return parser_compile_string(rb_parser_new(), rb_filesystem_str_new_cstr(f), s, line);
05456 }
05457 
05458 NODE*
05459 rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
05460 {
05461     return rb_parser_compile_string_path(vparser, rb_filesystem_str_new_cstr(f), s, line);
05462 }
05463 
05464 NODE*
05465 rb_parser_compile_string_path(volatile VALUE vparser, VALUE f, VALUE s, int line)
05466 {
05467     must_be_ascii_compatible(s);
05468     return parser_compile_string(vparser, f, s, line);
05469 }
05470 
05471 NODE*
05472 rb_compile_cstr(const char *f, const char *s, int len, int line)
05473 {
05474     VALUE str = rb_str_new(s, len);
05475     return parser_compile_string(rb_parser_new(), rb_filesystem_str_new_cstr(f), str, line);
05476 }
05477 
05478 NODE*
05479 rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line)
05480 {
05481     VALUE str = rb_str_new(s, len);
05482     return parser_compile_string(vparser, rb_filesystem_str_new_cstr(f), str, line);
05483 }
05484 
05485 static VALUE
05486 lex_io_gets(struct parser_params *parser, VALUE io)
05487 {
05488     return rb_io_gets(io);
05489 }
05490 
05491 NODE*
05492 rb_compile_file(const char *f, VALUE file, int start)
05493 {
05494     VALUE volatile vparser = rb_parser_new();
05495 
05496     return rb_parser_compile_file(vparser, f, file, start);
05497 }
05498 
05499 NODE*
05500 rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start)
05501 {
05502     return rb_parser_compile_file_path(vparser, rb_filesystem_str_new_cstr(f), file, start);
05503 }
05504 
05505 NODE*
05506 rb_parser_compile_file_path(volatile VALUE vparser, VALUE fname, VALUE file, int start)
05507 {
05508     struct parser_params *parser;
05509     NODE *node;
05510 
05511     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05512     lex_gets = lex_io_gets;
05513     lex_input = file;
05514     lex_pbeg = lex_p = lex_pend = 0;
05515     compile_for_eval = rb_parse_in_eval();
05516 
05517     node = yycompile(parser, fname, start);
05518     RB_GC_GUARD(vparser); /* prohibit tail call optimization */
05519 
05520     return node;
05521 }
05522 #endif  /* !RIPPER */
05523 
05524 #define STR_FUNC_ESCAPE 0x01
05525 #define STR_FUNC_EXPAND 0x02
05526 #define STR_FUNC_REGEXP 0x04
05527 #define STR_FUNC_QWORDS 0x08
05528 #define STR_FUNC_SYMBOL 0x10
05529 #define STR_FUNC_INDENT 0x20
05530 
05531 enum string_type {
05532     str_squote = (0),
05533     str_dquote = (STR_FUNC_EXPAND),
05534     str_xquote = (STR_FUNC_EXPAND),
05535     str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
05536     str_sword  = (STR_FUNC_QWORDS),
05537     str_dword  = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
05538     str_ssym   = (STR_FUNC_SYMBOL),
05539     str_dsym   = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
05540 };
05541 
05542 static VALUE
05543 parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0)
05544 {
05545     VALUE str;
05546 
05547     str = rb_enc_str_new(p, n, enc);
05548     if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
05549         if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
05550         }
05551         else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
05552             rb_enc_associate(str, rb_ascii8bit_encoding());
05553         }
05554     }
05555 
05556     return str;
05557 }
05558 
05559 #define lex_goto_eol(parser) ((parser)->parser_lex_p = (parser)->parser_lex_pend)
05560 #define lex_eol_p() (lex_p >= lex_pend)
05561 #define peek(c) peek_n((c), 0)
05562 #define peek_n(c,n) (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])
05563 
05564 static inline int
05565 parser_nextc(struct parser_params *parser)
05566 {
05567     int c;
05568 
05569     if (lex_p == lex_pend) {
05570         VALUE v = lex_nextline;
05571         lex_nextline = 0;
05572         if (!v) {
05573             if (parser->eofp)
05574                 return -1;
05575 
05576             if (!lex_input || NIL_P(v = lex_getline(parser))) {
05577                 parser->eofp = Qtrue;
05578                 lex_goto_eol(parser);
05579                 return -1;
05580             }
05581         }
05582         {
05583 #ifdef RIPPER
05584             if (parser->tokp < lex_pend) {
05585                 if (NIL_P(parser->delayed)) {
05586                     parser->delayed = rb_str_buf_new(1024);
05587                     rb_enc_associate(parser->delayed, current_enc);
05588                     rb_str_buf_cat(parser->delayed,
05589                                    parser->tokp, lex_pend - parser->tokp);
05590                     parser->delayed_line = ruby_sourceline;
05591                     parser->delayed_col = (int)(parser->tokp - lex_pbeg);
05592                 }
05593                 else {
05594                     rb_str_buf_cat(parser->delayed,
05595                                    parser->tokp, lex_pend - parser->tokp);
05596                 }
05597             }
05598 #endif
05599             if (heredoc_end > 0) {
05600                 ruby_sourceline = heredoc_end;
05601                 heredoc_end = 0;
05602             }
05603             ruby_sourceline++;
05604             parser->line_count++;
05605             lex_pbeg = lex_p = RSTRING_PTR(v);
05606             lex_pend = lex_p + RSTRING_LEN(v);
05607             ripper_flush(parser);
05608             lex_lastline = v;
05609         }
05610     }
05611     c = (unsigned char)*lex_p++;
05612     if (c == '\r' && peek('\n')) {
05613         lex_p++;
05614         c = '\n';
05615     }
05616 
05617     return c;
05618 }
05619 
05620 static void
05621 parser_pushback(struct parser_params *parser, int c)
05622 {
05623     if (c == -1) return;
05624     lex_p--;
05625     if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') {
05626         lex_p--;
05627     }
05628 }
05629 
05630 #define was_bol() (lex_p == lex_pbeg + 1)
05631 
05632 #define tokfix() (tokenbuf[tokidx]='\0')
05633 #define tok() tokenbuf
05634 #define toklen() tokidx
05635 #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
05636 
05637 static char*
05638 parser_newtok(struct parser_params *parser)
05639 {
05640     tokidx = 0;
05641     tokline = ruby_sourceline;
05642     if (!tokenbuf) {
05643         toksiz = 60;
05644         tokenbuf = ALLOC_N(char, 60);
05645     }
05646     if (toksiz > 4096) {
05647         toksiz = 60;
05648         REALLOC_N(tokenbuf, char, 60);
05649     }
05650     return tokenbuf;
05651 }
05652 
05653 static char *
05654 parser_tokspace(struct parser_params *parser, int n)
05655 {
05656     tokidx += n;
05657 
05658     if (tokidx >= toksiz) {
05659         do {toksiz *= 2;} while (toksiz < tokidx);
05660         REALLOC_N(tokenbuf, char, toksiz);
05661     }
05662     return &tokenbuf[tokidx-n];
05663 }
05664 
05665 static void
05666 parser_tokadd(struct parser_params *parser, int c)
05667 {
05668     tokenbuf[tokidx++] = (char)c;
05669     if (tokidx >= toksiz) {
05670         toksiz *= 2;
05671         REALLOC_N(tokenbuf, char, toksiz);
05672     }
05673 }
05674 
05675 static int
05676 parser_tok_hex(struct parser_params *parser, size_t *numlen)
05677 {
05678     int c;
05679 
05680     c = scan_hex(lex_p, 2, numlen);
05681     if (!*numlen) {
05682         yyerror("invalid hex escape");
05683         return 0;
05684     }
05685     lex_p += *numlen;
05686     return c;
05687 }
05688 
05689 #define tokcopy(n) memcpy(tokspace(n), lex_p - (n), (n))
05690 
05691 /* return value is for ?\u3042 */
05692 static int
05693 parser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp,
05694                    int string_literal, int symbol_literal, int regexp_literal)
05695 {
05696     /*
05697      * If string_literal is true, then we allow multiple codepoints
05698      * in \u{}, and add the codepoints to the current token.
05699      * Otherwise we're parsing a character literal and return a single
05700      * codepoint without adding it
05701      */
05702 
05703     int codepoint;
05704     size_t numlen;
05705 
05706     if (regexp_literal) { tokadd('\\'); tokadd('u'); }
05707 
05708     if (peek('{')) {  /* handle \u{...} form */
05709         do {
05710             if (regexp_literal) { tokadd(*lex_p); }
05711             nextc();
05712             codepoint = scan_hex(lex_p, 6, &numlen);
05713             if (numlen == 0)  {
05714                 yyerror("invalid Unicode escape");
05715                 return 0;
05716             }
05717             if (codepoint > 0x10ffff) {
05718                 yyerror("invalid Unicode codepoint (too large)");
05719                 return 0;
05720             }
05721             lex_p += numlen;
05722             if (regexp_literal) {
05723                 tokcopy((int)numlen);
05724             }
05725             else if (codepoint >= 0x80) {
05726                 *encp = rb_utf8_encoding();
05727                 if (string_literal) tokaddmbc(codepoint, *encp);
05728             }
05729             else if (string_literal) {
05730                 tokadd(codepoint);
05731             }
05732         } while (string_literal && (peek(' ') || peek('\t')));
05733 
05734         if (!peek('}')) {
05735             yyerror("unterminated Unicode escape");
05736             return 0;
05737         }
05738 
05739         if (regexp_literal) { tokadd('}'); }
05740         nextc();
05741     }
05742     else {                      /* handle \uxxxx form */
05743         codepoint = scan_hex(lex_p, 4, &numlen);
05744         if (numlen < 4) {
05745             yyerror("invalid Unicode escape");
05746             return 0;
05747         }
05748         lex_p += 4;
05749         if (regexp_literal) {
05750             tokcopy(4);
05751         }
05752         else if (codepoint >= 0x80) {
05753             *encp = rb_utf8_encoding();
05754             if (string_literal) tokaddmbc(codepoint, *encp);
05755         }
05756         else if (string_literal) {
05757             tokadd(codepoint);
05758         }
05759     }
05760 
05761     return codepoint;
05762 }
05763 
05764 #define ESCAPE_CONTROL 1
05765 #define ESCAPE_META    2
05766 
05767 static int
05768 parser_read_escape(struct parser_params *parser, int flags,
05769                    rb_encoding **encp)
05770 {
05771     int c;
05772     size_t numlen;
05773 
05774     switch (c = nextc()) {
05775       case '\\':        /* Backslash */
05776         return c;
05777 
05778       case 'n': /* newline */
05779         return '\n';
05780 
05781       case 't': /* horizontal tab */
05782         return '\t';
05783 
05784       case 'r': /* carriage-return */
05785         return '\r';
05786 
05787       case 'f': /* form-feed */
05788         return '\f';
05789 
05790       case 'v': /* vertical tab */
05791         return '\13';
05792 
05793       case 'a': /* alarm(bell) */
05794         return '\007';
05795 
05796       case 'e': /* escape */
05797         return 033;
05798 
05799       case '0': case '1': case '2': case '3': /* octal constant */
05800       case '4': case '5': case '6': case '7':
05801         pushback(c);
05802         c = scan_oct(lex_p, 3, &numlen);
05803         lex_p += numlen;
05804         return c;
05805 
05806       case 'x': /* hex constant */
05807         c = tok_hex(&numlen);
05808         if (numlen == 0) return 0;
05809         return c;
05810 
05811       case 'b': /* backspace */
05812         return '\010';
05813 
05814       case 's': /* space */
05815         return ' ';
05816 
05817       case 'M':
05818         if (flags & ESCAPE_META) goto eof;
05819         if ((c = nextc()) != '-') {
05820             pushback(c);
05821             goto eof;
05822         }
05823         if ((c = nextc()) == '\\') {
05824             if (peek('u')) goto eof;
05825             return read_escape(flags|ESCAPE_META, encp) | 0x80;
05826         }
05827         else if (c == -1 || !ISASCII(c)) goto eof;
05828         else {
05829             return ((c & 0xff) | 0x80);
05830         }
05831 
05832       case 'C':
05833         if ((c = nextc()) != '-') {
05834             pushback(c);
05835             goto eof;
05836         }
05837       case 'c':
05838         if (flags & ESCAPE_CONTROL) goto eof;
05839         if ((c = nextc())== '\\') {
05840             if (peek('u')) goto eof;
05841             c = read_escape(flags|ESCAPE_CONTROL, encp);
05842         }
05843         else if (c == '?')
05844             return 0177;
05845         else if (c == -1 || !ISASCII(c)) goto eof;
05846         return c & 0x9f;
05847 
05848       eof:
05849       case -1:
05850         yyerror("Invalid escape character syntax");
05851         return '\0';
05852 
05853       default:
05854         return c;
05855     }
05856 }
05857 
05858 static void
05859 parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc)
05860 {
05861     int len = rb_enc_codelen(c, enc);
05862     rb_enc_mbcput(c, tokspace(len), enc);
05863 }
05864 
05865 static int
05866 parser_tokadd_escape(struct parser_params *parser, rb_encoding **encp)
05867 {
05868     int c;
05869     int flags = 0;
05870     size_t numlen;
05871 
05872   first:
05873     switch (c = nextc()) {
05874       case '\n':
05875         return 0;               /* just ignore */
05876 
05877       case '0': case '1': case '2': case '3': /* octal constant */
05878       case '4': case '5': case '6': case '7':
05879         {
05880             ruby_scan_oct(--lex_p, 3, &numlen);
05881             if (numlen == 0) goto eof;
05882             lex_p += numlen;
05883             tokcopy((int)numlen + 1);
05884         }
05885         return 0;
05886 
05887       case 'x': /* hex constant */
05888         {
05889             tok_hex(&numlen);
05890             if (numlen == 0) return -1;
05891             tokcopy((int)numlen + 2);
05892         }
05893         return 0;
05894 
05895       case 'M':
05896         if (flags & ESCAPE_META) goto eof;
05897         if ((c = nextc()) != '-') {
05898             pushback(c);
05899             goto eof;
05900         }
05901         tokcopy(3);
05902         flags |= ESCAPE_META;
05903         goto escaped;
05904 
05905       case 'C':
05906         if (flags & ESCAPE_CONTROL) goto eof;
05907         if ((c = nextc()) != '-') {
05908             pushback(c);
05909             goto eof;
05910         }
05911         tokcopy(3);
05912         goto escaped;
05913 
05914       case 'c':
05915         if (flags & ESCAPE_CONTROL) goto eof;
05916         tokcopy(2);
05917         flags |= ESCAPE_CONTROL;
05918       escaped:
05919         if ((c = nextc()) == '\\') {
05920             goto first;
05921         }
05922         else if (c == -1) goto eof;
05923         tokadd(c);
05924         return 0;
05925 
05926       eof:
05927       case -1:
05928         yyerror("Invalid escape character syntax");
05929         return -1;
05930 
05931       default:
05932         tokadd('\\');
05933         tokadd(c);
05934     }
05935     return 0;
05936 }
05937 
05938 static int
05939 parser_regx_options(struct parser_params *parser)
05940 {
05941     int kcode = 0;
05942     int kopt = 0;
05943     int options = 0;
05944     int c, opt, kc;
05945 
05946     newtok();
05947     while (c = nextc(), ISALPHA(c)) {
05948         if (c == 'o') {
05949             options |= RE_OPTION_ONCE;
05950         }
05951         else if (rb_char_to_option_kcode(c, &opt, &kc)) {
05952             if (kc >= 0) {
05953                 if (kc != rb_ascii8bit_encindex()) kcode = c;
05954                 kopt = opt;
05955             }
05956             else {
05957                 options |= opt;
05958             }
05959         }
05960         else {
05961             tokadd(c);
05962         }
05963     }
05964     options |= kopt;
05965     pushback(c);
05966     if (toklen()) {
05967         tokfix();
05968         compile_error(PARSER_ARG "unknown regexp option%s - %s",
05969                       toklen() > 1 ? "s" : "", tok());
05970     }
05971     return options | RE_OPTION_ENCODING(kcode);
05972 }
05973 
05974 static void
05975 dispose_string(VALUE str)
05976 {
05977     rb_str_free(str);
05978     rb_gc_force_recycle(str);
05979 }
05980 
05981 static int
05982 parser_tokadd_mbchar(struct parser_params *parser, int c)
05983 {
05984     int len = parser_precise_mbclen();
05985     if (!MBCLEN_CHARFOUND_P(len)) {
05986         compile_error(PARSER_ARG "invalid multibyte char (%s)", parser_encoding_name());
05987         return -1;
05988     }
05989     tokadd(c);
05990     lex_p += --len;
05991     if (len > 0) tokcopy(len);
05992     return c;
05993 }
05994 
05995 #define tokadd_mbchar(c) parser_tokadd_mbchar(parser, (c))
05996 
05997 static inline int
05998 simple_re_meta(int c)
05999 {
06000     switch (c) {
06001       case '$': case '*': case '+': case '.':
06002       case '?': case '^': case '|':
06003       case ')': case ']': case '}': case '>':
06004         return TRUE;
06005       default:
06006         return FALSE;
06007     }
06008 }
06009 
06010 static int
06011 parser_tokadd_string(struct parser_params *parser,
06012                      int func, int term, int paren, long *nest,
06013                      rb_encoding **encp)
06014 {
06015     int c;
06016     int has_nonascii = 0;
06017     rb_encoding *enc = *encp;
06018     char *errbuf = 0;
06019     static const char mixed_msg[] = "%s mixed within %s source";
06020 
06021 #define mixed_error(enc1, enc2) if (!errbuf) {  \
06022         size_t len = sizeof(mixed_msg) - 4;     \
06023         len += strlen(rb_enc_name(enc1));       \
06024         len += strlen(rb_enc_name(enc2));       \
06025         errbuf = ALLOCA_N(char, len);           \
06026         snprintf(errbuf, len, mixed_msg,        \
06027                  rb_enc_name(enc1),             \
06028                  rb_enc_name(enc2));            \
06029         yyerror(errbuf);                        \
06030     }
06031 #define mixed_escape(beg, enc1, enc2) do {      \
06032         const char *pos = lex_p;                \
06033         lex_p = (beg);                          \
06034         mixed_error((enc1), (enc2));            \
06035         lex_p = pos;                            \
06036     } while (0)
06037 
06038     while ((c = nextc()) != -1) {
06039         if (paren && c == paren) {
06040             ++*nest;
06041         }
06042         else if (c == term) {
06043             if (!nest || !*nest) {
06044                 pushback(c);
06045                 break;
06046             }
06047             --*nest;
06048         }
06049         else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
06050             int c2 = *lex_p;
06051             if (c2 == '$' || c2 == '@' || c2 == '{') {
06052                 pushback(c);
06053                 break;
06054             }
06055         }
06056         else if (c == '\\') {
06057             const char *beg = lex_p - 1;
06058             c = nextc();
06059             switch (c) {
06060               case '\n':
06061                 if (func & STR_FUNC_QWORDS) break;
06062                 if (func & STR_FUNC_EXPAND) continue;
06063                 tokadd('\\');
06064                 break;
06065 
06066               case '\\':
06067                 if (func & STR_FUNC_ESCAPE) tokadd(c);
06068                 break;
06069 
06070               case 'u':
06071                 if ((func & STR_FUNC_EXPAND) == 0) {
06072                     tokadd('\\');
06073                     break;
06074                 }
06075                 parser_tokadd_utf8(parser, &enc, 1,
06076                                    func & STR_FUNC_SYMBOL,
06077                                    func & STR_FUNC_REGEXP);
06078                 if (has_nonascii && enc != *encp) {
06079                     mixed_escape(beg, enc, *encp);
06080                 }
06081                 continue;
06082 
06083               default:
06084                 if (c == -1) return -1;
06085                 if (!ISASCII(c)) {
06086                     if ((func & STR_FUNC_EXPAND) == 0) tokadd('\\');
06087                     goto non_ascii;
06088                 }
06089                 if (func & STR_FUNC_REGEXP) {
06090                     if (c == term && !simple_re_meta(c)) {
06091                         tokadd(c);
06092                         continue;
06093                     }
06094                     pushback(c);
06095                     if ((c = tokadd_escape(&enc)) < 0)
06096                         return -1;
06097                     if (has_nonascii && enc != *encp) {
06098                         mixed_escape(beg, enc, *encp);
06099                     }
06100                     continue;
06101                 }
06102                 else if (func & STR_FUNC_EXPAND) {
06103                     pushback(c);
06104                     if (func & STR_FUNC_ESCAPE) tokadd('\\');
06105                     c = read_escape(0, &enc);
06106                 }
06107                 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
06108                     /* ignore backslashed spaces in %w */
06109                 }
06110                 else if (c != term && !(paren && c == paren)) {
06111                     tokadd('\\');
06112                     pushback(c);
06113                     continue;
06114                 }
06115             }
06116         }
06117         else if (!parser_isascii()) {
06118           non_ascii:
06119             has_nonascii = 1;
06120             if (enc != *encp) {
06121                 mixed_error(enc, *encp);
06122                 continue;
06123             }
06124             if (tokadd_mbchar(c) == -1) return -1;
06125             continue;
06126         }
06127         else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
06128             pushback(c);
06129             break;
06130         }
06131         if (c & 0x80) {
06132             has_nonascii = 1;
06133             if (enc != *encp) {
06134                 mixed_error(enc, *encp);
06135                 continue;
06136             }
06137         }
06138         tokadd(c);
06139     }
06140     *encp = enc;
06141     return c;
06142 }
06143 
06144 #define NEW_STRTERM(func, term, paren) \
06145         rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
06146 
06147 #ifdef RIPPER
06148 static void
06149 ripper_flush_string_content(struct parser_params *parser, rb_encoding *enc)
06150 {
06151     if (!NIL_P(parser->delayed)) {
06152         ptrdiff_t len = lex_p - parser->tokp;
06153         if (len > 0) {
06154             rb_enc_str_buf_cat(parser->delayed, parser->tokp, len, enc);
06155         }
06156         ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06157         parser->tokp = lex_p;
06158     }
06159 }
06160 
06161 #define flush_string_content(enc) ripper_flush_string_content(parser, (enc))
06162 #else
06163 #define flush_string_content(enc) ((void)(enc))
06164 #endif
06165 
06166 RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
06167 /* this can be shared with ripper, since it's independent from struct
06168  * parser_params. */
06169 #ifndef RIPPER
06170 #define BIT(c, idx) (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
06171 #define SPECIAL_PUNCT(idx) ( \
06172         BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
06173         BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
06174         BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
06175         BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
06176         BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
06177         BIT('0', idx))
06178 const unsigned int ruby_global_name_punct_bits[] = {
06179     SPECIAL_PUNCT(0),
06180     SPECIAL_PUNCT(1),
06181     SPECIAL_PUNCT(2),
06182 };
06183 #undef BIT
06184 #undef SPECIAL_PUNCT
06185 #endif
06186 
06187 static inline int
06188 is_global_name_punct(const char c)
06189 {
06190     if (c <= 0x20 || 0x7e < c) return 0;
06191     return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;
06192 }
06193 
06194 static int
06195 parser_peek_variable_name(struct parser_params *parser)
06196 {
06197     int c;
06198     const char *p = lex_p;
06199 
06200     if (p + 1 >= lex_pend) return 0;
06201     c = *p++;
06202     switch (c) {
06203       case '$':
06204         if ((c = *p) == '-') {
06205             if (++p >= lex_pend) return 0;
06206             c = *p;
06207         }
06208         else if (is_global_name_punct(c) || ISDIGIT(c)) {
06209             return tSTRING_DVAR;
06210         }
06211         break;
06212       case '@':
06213         if ((c = *p) == '@') {
06214             if (++p >= lex_pend) return 0;
06215             c = *p;
06216         }
06217         break;
06218       case '{':
06219         lex_p = p;
06220         command_start = TRUE;
06221         return tSTRING_DBEG;
06222       default:
06223         return 0;
06224     }
06225     if (!ISASCII(c) || c == '_' || ISALPHA(c))
06226         return tSTRING_DVAR;
06227     return 0;
06228 }
06229 
06230 static int
06231 parser_parse_string(struct parser_params *parser, NODE *quote)
06232 {
06233     int func = (int)quote->nd_func;
06234     int term = nd_term(quote);
06235     int paren = nd_paren(quote);
06236     int c, space = 0;
06237     rb_encoding *enc = current_enc;
06238 
06239     if (func == -1) return tSTRING_END;
06240     c = nextc();
06241     if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
06242         do {c = nextc();} while (ISSPACE(c));
06243         space = 1;
06244     }
06245     if (c == term && !quote->nd_nest) {
06246         if (func & STR_FUNC_QWORDS) {
06247             quote->nd_func = -1;
06248             return ' ';
06249         }
06250         if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
06251         set_yylval_num(regx_options());
06252         return tREGEXP_END;
06253     }
06254     if (space) {
06255         pushback(c);
06256         return ' ';
06257     }
06258     newtok();
06259     if ((func & STR_FUNC_EXPAND) && c == '#') {
06260         int t = parser_peek_variable_name(parser);
06261         if (t) return t;
06262         tokadd('#');
06263         c = nextc();
06264     }
06265     pushback(c);
06266     if (tokadd_string(func, term, paren, &quote->nd_nest,
06267                       &enc) == -1) {
06268         ruby_sourceline = nd_line(quote);
06269         if (func & STR_FUNC_REGEXP) {
06270             if (parser->eofp)
06271                 compile_error(PARSER_ARG "unterminated regexp meets end of file");
06272             return tREGEXP_END;
06273         }
06274         else {
06275             if (parser->eofp)
06276                 compile_error(PARSER_ARG "unterminated string meets end of file");
06277             return tSTRING_END;
06278         }
06279     }
06280 
06281     tokfix();
06282     set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06283     flush_string_content(enc);
06284 
06285     return tSTRING_CONTENT;
06286 }
06287 
06288 static int
06289 parser_heredoc_identifier(struct parser_params *parser)
06290 {
06291     int c = nextc(), term, func = 0;
06292     long len;
06293 
06294     if (c == '-') {
06295         c = nextc();
06296         func = STR_FUNC_INDENT;
06297     }
06298     switch (c) {
06299       case '\'':
06300         func |= str_squote; goto quoted;
06301       case '"':
06302         func |= str_dquote; goto quoted;
06303       case '`':
06304         func |= str_xquote;
06305       quoted:
06306         newtok();
06307         tokadd(func);
06308         term = c;
06309         while ((c = nextc()) != -1 && c != term) {
06310             if (tokadd_mbchar(c) == -1) return 0;
06311         }
06312         if (c == -1) {
06313             compile_error(PARSER_ARG "unterminated here document identifier");
06314             return 0;
06315         }
06316         break;
06317 
06318       default:
06319         if (!parser_is_identchar()) {
06320             pushback(c);
06321             if (func & STR_FUNC_INDENT) {
06322                 pushback('-');
06323             }
06324             return 0;
06325         }
06326         newtok();
06327         term = '"';
06328         tokadd(func |= str_dquote);
06329         do {
06330             if (tokadd_mbchar(c) == -1) return 0;
06331         } while ((c = nextc()) != -1 && parser_is_identchar());
06332         pushback(c);
06333         break;
06334     }
06335 
06336     tokfix();
06337 #ifdef RIPPER
06338     ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
06339 #endif
06340     len = lex_p - lex_pbeg;
06341     lex_goto_eol(parser);
06342     lex_strterm = rb_node_newnode(NODE_HEREDOC,
06343                                   STR_NEW(tok(), toklen()),     /* nd_lit */
06344                                   len,                          /* nd_nth */
06345                                   lex_lastline);                /* nd_orig */
06346     nd_set_line(lex_strterm, ruby_sourceline);
06347     ripper_flush(parser);
06348     return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
06349 }
06350 
06351 static void
06352 parser_heredoc_restore(struct parser_params *parser, NODE *here)
06353 {
06354     VALUE line;
06355 
06356     line = here->nd_orig;
06357     lex_lastline = line;
06358     lex_pbeg = RSTRING_PTR(line);
06359     lex_pend = lex_pbeg + RSTRING_LEN(line);
06360     lex_p = lex_pbeg + here->nd_nth;
06361     heredoc_end = ruby_sourceline;
06362     ruby_sourceline = nd_line(here);
06363     dispose_string(here->nd_lit);
06364     rb_gc_force_recycle((VALUE)here);
06365     ripper_flush(parser);
06366 }
06367 
06368 static int
06369 parser_whole_match_p(struct parser_params *parser,
06370     const char *eos, long len, int indent)
06371 {
06372     const char *p = lex_pbeg;
06373     long n;
06374 
06375     if (indent) {
06376         while (*p && ISSPACE(*p)) p++;
06377     }
06378     n = lex_pend - (p + len);
06379     if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE;
06380     return strncmp(eos, p, len) == 0;
06381 }
06382 
06383 #ifdef RIPPER
06384 static void
06385 ripper_dispatch_heredoc_end(struct parser_params *parser)
06386 {
06387     if (!NIL_P(parser->delayed))
06388         ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06389     lex_goto_eol(parser);
06390     ripper_dispatch_ignored_scan_event(parser, tHEREDOC_END);
06391 }
06392 
06393 #define dispatch_heredoc_end() ripper_dispatch_heredoc_end(parser)
06394 #else
06395 #define dispatch_heredoc_end() ((void)0)
06396 #endif
06397 
06398 static int
06399 parser_here_document(struct parser_params *parser, NODE *here)
06400 {
06401     int c, func, indent = 0;
06402     const char *eos, *p, *pend;
06403     long len;
06404     VALUE str = 0;
06405     rb_encoding *enc = current_enc;
06406 
06407     eos = RSTRING_PTR(here->nd_lit);
06408     len = RSTRING_LEN(here->nd_lit) - 1;
06409     indent = (func = *eos++) & STR_FUNC_INDENT;
06410 
06411     if ((c = nextc()) == -1) {
06412       error:
06413         compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
06414 #ifdef RIPPER
06415         if (NIL_P(parser->delayed)) {
06416             ripper_dispatch_scan_event(parser, tSTRING_CONTENT);
06417         }
06418         else {
06419             if (str ||
06420                 ((len = lex_p - parser->tokp) > 0 &&
06421                  (str = STR_NEW3(parser->tokp, len, enc, func), 1))) {
06422                 rb_str_append(parser->delayed, str);
06423             }
06424             ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06425         }
06426         lex_goto_eol(parser);
06427 #endif
06428       restore:
06429         heredoc_restore(lex_strterm);
06430         lex_strterm = 0;
06431         return 0;
06432     }
06433     if (was_bol() && whole_match_p(eos, len, indent)) {
06434         dispatch_heredoc_end();
06435         heredoc_restore(lex_strterm);
06436         return tSTRING_END;
06437     }
06438 
06439     if (!(func & STR_FUNC_EXPAND)) {
06440         do {
06441             p = RSTRING_PTR(lex_lastline);
06442             pend = lex_pend;
06443             if (pend > p) {
06444                 switch (pend[-1]) {
06445                   case '\n':
06446                     if (--pend == p || pend[-1] != '\r') {
06447                         pend++;
06448                         break;
06449                     }
06450                   case '\r':
06451                     --pend;
06452                 }
06453             }
06454             if (str)
06455                 rb_str_cat(str, p, pend - p);
06456             else
06457                 str = STR_NEW(p, pend - p);
06458             if (pend < lex_pend) rb_str_cat(str, "\n", 1);
06459             lex_goto_eol(parser);
06460             if (nextc() == -1) {
06461                 if (str) {
06462                     dispose_string(str);
06463                     str = 0;
06464                 }
06465                 goto error;
06466             }
06467         } while (!whole_match_p(eos, len, indent));
06468     }
06469     else {
06470         /*      int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
06471         newtok();
06472         if (c == '#') {
06473             int t = parser_peek_variable_name(parser);
06474             if (t) return t;
06475             tokadd('#');
06476             c = nextc();
06477         }
06478         do {
06479             pushback(c);
06480             if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) {
06481                 if (parser->eofp) goto error;
06482                 goto restore;
06483             }
06484             if (c != '\n') {
06485                 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06486                 flush_string_content(enc);
06487                 return tSTRING_CONTENT;
06488             }
06489             tokadd(nextc());
06490             /*      if (mbp && mb == ENC_CODERANGE_UNKNOWN) mbp = 0;*/
06491             if ((c = nextc()) == -1) goto error;
06492         } while (!whole_match_p(eos, len, indent));
06493         str = STR_NEW3(tok(), toklen(), enc, func);
06494     }
06495     dispatch_heredoc_end();
06496     heredoc_restore(lex_strterm);
06497     lex_strterm = NEW_STRTERM(-1, 0, 0);
06498     set_yylval_str(str);
06499     return tSTRING_CONTENT;
06500 }
06501 
06502 #include "lex.c"
06503 
06504 static void
06505 arg_ambiguous_gen(struct parser_params *parser)
06506 {
06507 #ifndef RIPPER
06508     rb_warning0("ambiguous first argument; put parentheses or even spaces");
06509 #else
06510     dispatch0(arg_ambiguous);
06511 #endif
06512 }
06513 #define arg_ambiguous() (arg_ambiguous_gen(parser), 1)
06514 
06515 static ID
06516 formal_argument_gen(struct parser_params *parser, ID lhs)
06517 {
06518 #ifndef RIPPER
06519     if (!is_local_id(lhs))
06520         yyerror("formal argument must be local variable");
06521 #endif
06522     shadowing_lvar(lhs);
06523     return lhs;
06524 }
06525 
06526 static int
06527 lvar_defined_gen(struct parser_params *parser, ID id)
06528 {
06529     return (dyna_in_block() && dvar_defined_get(id)) || local_id(id);
06530 }
06531 
06532 /* emacsen -*- hack */
06533 static long
06534 parser_encode_length(struct parser_params *parser, const char *name, long len)
06535 {
06536     long nlen;
06537 
06538     if (len > 5 && name[nlen = len - 5] == '-') {
06539         if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0)
06540             return nlen;
06541     }
06542     if (len > 4 && name[nlen = len - 4] == '-') {
06543         if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0)
06544             return nlen;
06545         if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0 &&
06546             !(len == 8 && rb_memcicmp(name, "utf8-mac", len) == 0))
06547             /* exclude UTF8-MAC because the encoding named "UTF8" doesn't exist in Ruby */
06548             return nlen;
06549     }
06550     return len;
06551 }
06552 
06553 static void
06554 parser_set_encode(struct parser_params *parser, const char *name)
06555 {
06556     int idx = rb_enc_find_index(name);
06557     rb_encoding *enc;
06558     VALUE excargs[3];
06559 
06560     if (idx < 0) {
06561         excargs[1] = rb_sprintf("unknown encoding name: %s", name);
06562       error:
06563         excargs[0] = rb_eArgError;
06564         excargs[2] = rb_make_backtrace();
06565         rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));
06566         rb_exc_raise(rb_make_exception(3, excargs));
06567     }
06568     enc = rb_enc_from_index(idx);
06569     if (!rb_enc_asciicompat(enc)) {
06570         excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));
06571         goto error;
06572     }
06573     parser->enc = enc;
06574 #ifndef RIPPER
06575     if (ruby_debug_lines) {
06576         long i, n = RARRAY_LEN(ruby_debug_lines);
06577         const VALUE *p = RARRAY_PTR(ruby_debug_lines);
06578         for (i = 0; i < n; ++i) {
06579             rb_enc_associate_index(*p, idx);
06580         }
06581     }
06582 #endif
06583 }
06584 
06585 static int
06586 comment_at_top(struct parser_params *parser)
06587 {
06588     const char *p = lex_pbeg, *pend = lex_p - 1;
06589     if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0;
06590     while (p < pend) {
06591         if (!ISSPACE(*p)) return 0;
06592         p++;
06593     }
06594     return 1;
06595 }
06596 
06597 #ifndef RIPPER
06598 typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);
06599 typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
06600 
06601 static void
06602 magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
06603 {
06604     if (!comment_at_top(parser)) {
06605         return;
06606     }
06607     parser_set_encode(parser, val);
06608 }
06609 
06610 static void
06611 parser_set_token_info(struct parser_params *parser, const char *name, const char *val)
06612 {
06613     int *p = &parser->parser_token_info_enabled;
06614 
06615     switch (*val) {
06616       case 't': case 'T':
06617         if (strcasecmp(val, "true") == 0) {
06618             *p = TRUE;
06619             return;
06620         }
06621         break;
06622       case 'f': case 'F':
06623         if (strcasecmp(val, "false") == 0) {
06624             *p = FALSE;
06625             return;
06626         }
06627         break;
06628     }
06629     rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);
06630 }
06631 
06632 struct magic_comment {
06633     const char *name;
06634     rb_magic_comment_setter_t func;
06635     rb_magic_comment_length_t length;
06636 };
06637 
06638 static const struct magic_comment magic_comments[] = {
06639     {"coding", magic_comment_encoding, parser_encode_length},
06640     {"encoding", magic_comment_encoding, parser_encode_length},
06641     {"warn_indent", parser_set_token_info},
06642 };
06643 #endif
06644 
06645 static const char *
06646 magic_comment_marker(const char *str, long len)
06647 {
06648     long i = 2;
06649 
06650     while (i < len) {
06651         switch (str[i]) {
06652           case '-':
06653             if (str[i-1] == '*' && str[i-2] == '-') {
06654                 return str + i + 1;
06655             }
06656             i += 2;
06657             break;
06658           case '*':
06659             if (i + 1 >= len) return 0;
06660             if (str[i+1] != '-') {
06661                 i += 4;
06662             }
06663             else if (str[i-1] != '-') {
06664                 i += 2;
06665             }
06666             else {
06667                 return str + i + 2;
06668             }
06669             break;
06670           default:
06671             i += 3;
06672             break;
06673         }
06674     }
06675     return 0;
06676 }
06677 
06678 static int
06679 parser_magic_comment(struct parser_params *parser, const char *str, long len)
06680 {
06681     VALUE name = 0, val = 0;
06682     const char *beg, *end, *vbeg, *vend;
06683 #define str_copy(_s, _p, _n) ((_s) \
06684         ? (void)(rb_str_resize((_s), (_n)), \
06685            MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
06686         : (void)((_s) = STR_NEW((_p), (_n))))
06687 
06688     if (len <= 7) return FALSE;
06689     if (!(beg = magic_comment_marker(str, len))) return FALSE;
06690     if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE;
06691     str = beg;
06692     len = end - beg - 3;
06693 
06694     /* %r"([^\\s\'\":;]+)\\s*:\\s*(\"(?:\\\\.|[^\"])*\"|[^\"\\s;]+)[\\s;]*" */
06695     while (len > 0) {
06696 #ifndef RIPPER
06697         const struct magic_comment *p = magic_comments;
06698 #endif
06699         char *s;
06700         int i;
06701         long n = 0;
06702 
06703         for (; len > 0 && *str; str++, --len) {
06704             switch (*str) {
06705               case '\'': case '"': case ':': case ';':
06706                 continue;
06707             }
06708             if (!ISSPACE(*str)) break;
06709         }
06710         for (beg = str; len > 0; str++, --len) {
06711             switch (*str) {
06712               case '\'': case '"': case ':': case ';':
06713                 break;
06714               default:
06715                 if (ISSPACE(*str)) break;
06716                 continue;
06717             }
06718             break;
06719         }
06720         for (end = str; len > 0 && ISSPACE(*str); str++, --len);
06721         if (!len) break;
06722         if (*str != ':') continue;
06723 
06724         do str++; while (--len > 0 && ISSPACE(*str));
06725         if (!len) break;
06726         if (*str == '"') {
06727             for (vbeg = ++str; --len > 0 && *str != '"'; str++) {
06728                 if (*str == '\\') {
06729                     --len;
06730                     ++str;
06731                 }
06732             }
06733             vend = str;
06734             if (len) {
06735                 --len;
06736                 ++str;
06737             }
06738         }
06739         else {
06740             for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++);
06741             vend = str;
06742         }
06743         while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++;
06744 
06745         n = end - beg;
06746         str_copy(name, beg, n);
06747         s = RSTRING_PTR(name);
06748         for (i = 0; i < n; ++i) {
06749             if (s[i] == '-') s[i] = '_';
06750         }
06751 #ifndef RIPPER
06752         do {
06753             if (STRNCASECMP(p->name, s, n) == 0) {
06754                 n = vend - vbeg;
06755                 if (p->length) {
06756                     n = (*p->length)(parser, vbeg, n);
06757                 }
06758                 str_copy(val, vbeg, n);
06759                 (*p->func)(parser, s, RSTRING_PTR(val));
06760                 break;
06761             }
06762         } while (++p < magic_comments + numberof(magic_comments));
06763 #else
06764         str_copy(val, vbeg, vend - vbeg);
06765         dispatch2(magic_comment, name, val);
06766 #endif
06767     }
06768 
06769     return TRUE;
06770 }
06771 
06772 static void
06773 set_file_encoding(struct parser_params *parser, const char *str, const char *send)
06774 {
06775     int sep = 0;
06776     const char *beg = str;
06777     VALUE s;
06778 
06779     for (;;) {
06780         if (send - str <= 6) return;
06781         switch (str[6]) {
06782           case 'C': case 'c': str += 6; continue;
06783           case 'O': case 'o': str += 5; continue;
06784           case 'D': case 'd': str += 4; continue;
06785           case 'I': case 'i': str += 3; continue;
06786           case 'N': case 'n': str += 2; continue;
06787           case 'G': case 'g': str += 1; continue;
06788           case '=': case ':':
06789             sep = 1;
06790             str += 6;
06791             break;
06792           default:
06793             str += 6;
06794             if (ISSPACE(*str)) break;
06795             continue;
06796         }
06797         if (STRNCASECMP(str-6, "coding", 6) == 0) break;
06798     }
06799     for (;;) {
06800         do {
06801             if (++str >= send) return;
06802         } while (ISSPACE(*str));
06803         if (sep) break;
06804         if (*str != '=' && *str != ':') return;
06805         sep = 1;
06806         str++;
06807     }
06808     beg = str;
06809     while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send);
06810     s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg));
06811     parser_set_encode(parser, RSTRING_PTR(s));
06812     rb_str_resize(s, 0);
06813 }
06814 
06815 static void
06816 parser_prepare(struct parser_params *parser)
06817 {
06818     int c = nextc();
06819     switch (c) {
06820       case '#':
06821         if (peek('!')) parser->has_shebang = 1;
06822         break;
06823       case 0xef:                /* UTF-8 BOM marker */
06824         if (lex_pend - lex_p >= 2 &&
06825             (unsigned char)lex_p[0] == 0xbb &&
06826             (unsigned char)lex_p[1] == 0xbf) {
06827             parser->enc = rb_utf8_encoding();
06828             lex_p += 2;
06829             lex_pbeg = lex_p;
06830             return;
06831         }
06832         break;
06833       case EOF:
06834         return;
06835     }
06836     pushback(c);
06837     parser->enc = rb_enc_get(lex_lastline);
06838 }
06839 
06840 #define IS_ARG() IS_lex_state(EXPR_ARG_ANY)
06841 #define IS_END() IS_lex_state(EXPR_END_ANY)
06842 #define IS_BEG() IS_lex_state(EXPR_BEG_ANY)
06843 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
06844 #define IS_LABEL_POSSIBLE() ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())
06845 #define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1))
06846 #define IS_AFTER_OPERATOR() IS_lex_state(EXPR_FNAME | EXPR_DOT)
06847 
06848 #ifndef RIPPER
06849 #define ambiguous_operator(op, syn) ( \
06850     rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
06851     rb_warning0("even though it seems like "syn""))
06852 #else
06853 #define ambiguous_operator(op, syn) dispatch2(operator_ambiguous, ripper_intern(op), rb_str_new_cstr(syn))
06854 #endif
06855 #define warn_balanced(op, syn) ((void) \
06856     (!IS_lex_state_for(last_state, EXPR_CLASS|EXPR_DOT|EXPR_FNAME|EXPR_ENDFN|EXPR_ENDARG) && \
06857      space_seen && !ISSPACE(c) && \
06858      (ambiguous_operator(op, syn), 0)))
06859 
06860 static int
06861 parser_yylex(struct parser_params *parser)
06862 {
06863     register int c;
06864     int space_seen = 0;
06865     int cmd_state;
06866     enum lex_state_e last_state;
06867     rb_encoding *enc;
06868     int mb;
06869 #ifdef RIPPER
06870     int fallthru = FALSE;
06871 #endif
06872 
06873     if (lex_strterm) {
06874         int token;
06875         if (nd_type(lex_strterm) == NODE_HEREDOC) {
06876             token = here_document(lex_strterm);
06877             if (token == tSTRING_END) {
06878                 lex_strterm = 0;
06879                 lex_state = EXPR_END;
06880             }
06881         }
06882         else {
06883             token = parse_string(lex_strterm);
06884             if (token == tSTRING_END || token == tREGEXP_END) {
06885                 rb_gc_force_recycle((VALUE)lex_strterm);
06886                 lex_strterm = 0;
06887                 lex_state = EXPR_END;
06888             }
06889         }
06890         return token;
06891     }
06892     cmd_state = command_start;
06893     command_start = FALSE;
06894   retry:
06895     last_state = lex_state;
06896     switch (c = nextc()) {
06897       case '\0':                /* NUL */
06898       case '\004':              /* ^D */
06899       case '\032':              /* ^Z */
06900       case -1:                  /* end of script. */
06901         return 0;
06902 
06903         /* white spaces */
06904       case ' ': case '\t': case '\f': case '\r':
06905       case '\13': /* '\v' */
06906         space_seen = 1;
06907 #ifdef RIPPER
06908         while ((c = nextc())) {
06909             switch (c) {
06910               case ' ': case '\t': case '\f': case '\r':
06911               case '\13': /* '\v' */
06912                 break;
06913               default:
06914                 goto outofloop;
06915             }
06916         }
06917       outofloop:
06918         pushback(c);
06919         ripper_dispatch_scan_event(parser, tSP);
06920 #endif
06921         goto retry;
06922 
06923       case '#':         /* it's a comment */
06924         /* no magic_comment in shebang line */
06925         if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
06926             if (comment_at_top(parser)) {
06927                 set_file_encoding(parser, lex_p, lex_pend);
06928             }
06929         }
06930         lex_p = lex_pend;
06931 #ifdef RIPPER
06932         ripper_dispatch_scan_event(parser, tCOMMENT);
06933         fallthru = TRUE;
06934 #endif
06935         /* fall through */
06936       case '\n':
06937         if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT)) {
06938 #ifdef RIPPER
06939             if (!fallthru) {
06940                 ripper_dispatch_scan_event(parser, tIGNORED_NL);
06941             }
06942             fallthru = FALSE;
06943 #endif
06944             goto retry;
06945         }
06946         while ((c = nextc())) {
06947             switch (c) {
06948               case ' ': case '\t': case '\f': case '\r':
06949               case '\13': /* '\v' */
06950                 space_seen = 1;
06951                 break;
06952               case '.': {
06953                   if ((c = nextc()) != '.') {
06954                       pushback(c);
06955                       pushback('.');
06956                       goto retry;
06957                   }
06958               }
06959               default:
06960                 --ruby_sourceline;
06961                 lex_nextline = lex_lastline;
06962               case -1:          /* EOF no decrement*/
06963                 lex_goto_eol(parser);
06964 #ifdef RIPPER
06965                 if (c != -1) {
06966                     parser->tokp = lex_p;
06967                 }
06968 #endif
06969                 goto normal_newline;
06970             }
06971         }
06972       normal_newline:
06973         command_start = TRUE;
06974         lex_state = EXPR_BEG;
06975         return '\n';
06976 
06977       case '*':
06978         if ((c = nextc()) == '*') {
06979             if ((c = nextc()) == '=') {
06980                 set_yylval_id(tPOW);
06981                 lex_state = EXPR_BEG;
06982                 return tOP_ASGN;
06983             }
06984             pushback(c);
06985             if (IS_SPCARG(c)) {
06986                 rb_warning0("`**' interpreted as argument prefix");
06987                 c = tDSTAR;
06988             }
06989             else if (IS_BEG()) {
06990                 c = tDSTAR;
06991             }
06992             else {
06993                 warn_balanced("**", "argument prefix");
06994                 c = tPOW;
06995             }
06996         }
06997         else {
06998             if (c == '=') {
06999                 set_yylval_id('*');
07000                 lex_state = EXPR_BEG;
07001                 return tOP_ASGN;
07002             }
07003             pushback(c);
07004             if (IS_SPCARG(c)) {
07005                 rb_warning0("`*' interpreted as argument prefix");
07006                 c = tSTAR;
07007             }
07008             else if (IS_BEG()) {
07009                 c = tSTAR;
07010             }
07011             else {
07012                 warn_balanced("*", "argument prefix");
07013                 c = '*';
07014             }
07015         }
07016         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07017         return c;
07018 
07019       case '!':
07020         c = nextc();
07021         if (IS_AFTER_OPERATOR()) {
07022             lex_state = EXPR_ARG;
07023             if (c == '@') {
07024                 return '!';
07025             }
07026         }
07027         else {
07028             lex_state = EXPR_BEG;
07029         }
07030         if (c == '=') {
07031             return tNEQ;
07032         }
07033         if (c == '~') {
07034             return tNMATCH;
07035         }
07036         pushback(c);
07037         return '!';
07038 
07039       case '=':
07040         if (was_bol()) {
07041             /* skip embedded rd document */
07042             if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
07043 #ifdef RIPPER
07044                 int first_p = TRUE;
07045 
07046                 lex_goto_eol(parser);
07047                 ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
07048 #endif
07049                 for (;;) {
07050                     lex_goto_eol(parser);
07051 #ifdef RIPPER
07052                     if (!first_p) {
07053                         ripper_dispatch_scan_event(parser, tEMBDOC);
07054                     }
07055                     first_p = FALSE;
07056 #endif
07057                     c = nextc();
07058                     if (c == -1) {
07059                         compile_error(PARSER_ARG "embedded document meets end of file");
07060                         return 0;
07061                     }
07062                     if (c != '=') continue;
07063                     if (strncmp(lex_p, "end", 3) == 0 &&
07064                         (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
07065                         break;
07066                     }
07067                 }
07068                 lex_goto_eol(parser);
07069 #ifdef RIPPER
07070                 ripper_dispatch_scan_event(parser, tEMBDOC_END);
07071 #endif
07072                 goto retry;
07073             }
07074         }
07075 
07076         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07077         if ((c = nextc()) == '=') {
07078             if ((c = nextc()) == '=') {
07079                 return tEQQ;
07080             }
07081             pushback(c);
07082             return tEQ;
07083         }
07084         if (c == '~') {
07085             return tMATCH;
07086         }
07087         else if (c == '>') {
07088             return tASSOC;
07089         }
07090         pushback(c);
07091         return '=';
07092 
07093       case '<':
07094         last_state = lex_state;
07095         c = nextc();
07096         if (c == '<' &&
07097             !IS_lex_state(EXPR_DOT | EXPR_CLASS) &&
07098             !IS_END() &&
07099             (!IS_ARG() || space_seen)) {
07100             int token = heredoc_identifier();
07101             if (token) return token;
07102         }
07103         if (IS_AFTER_OPERATOR()) {
07104             lex_state = EXPR_ARG;
07105         }
07106         else {
07107             if (IS_lex_state(EXPR_CLASS))
07108                 command_start = TRUE;
07109             lex_state = EXPR_BEG;
07110         }
07111         if (c == '=') {
07112             if ((c = nextc()) == '>') {
07113                 return tCMP;
07114             }
07115             pushback(c);
07116             return tLEQ;
07117         }
07118         if (c == '<') {
07119             if ((c = nextc()) == '=') {
07120                 set_yylval_id(tLSHFT);
07121                 lex_state = EXPR_BEG;
07122                 return tOP_ASGN;
07123             }
07124             pushback(c);
07125             warn_balanced("<<", "here document");
07126             return tLSHFT;
07127         }
07128         pushback(c);
07129         return '<';
07130 
07131       case '>':
07132         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07133         if ((c = nextc()) == '=') {
07134             return tGEQ;
07135         }
07136         if (c == '>') {
07137             if ((c = nextc()) == '=') {
07138                 set_yylval_id(tRSHFT);
07139                 lex_state = EXPR_BEG;
07140                 return tOP_ASGN;
07141             }
07142             pushback(c);
07143             return tRSHFT;
07144         }
07145         pushback(c);
07146         return '>';
07147 
07148       case '"':
07149         lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
07150         return tSTRING_BEG;
07151 
07152       case '`':
07153         if (IS_lex_state(EXPR_FNAME)) {
07154             lex_state = EXPR_ENDFN;
07155             return c;
07156         }
07157         if (IS_lex_state(EXPR_DOT)) {
07158             if (cmd_state)
07159                 lex_state = EXPR_CMDARG;
07160             else
07161                 lex_state = EXPR_ARG;
07162             return c;
07163         }
07164         lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
07165         return tXSTRING_BEG;
07166 
07167       case '\'':
07168         lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
07169         return tSTRING_BEG;
07170 
07171       case '?':
07172         if (IS_END()) {
07173             lex_state = EXPR_VALUE;
07174             return '?';
07175         }
07176         c = nextc();
07177         if (c == -1) {
07178             compile_error(PARSER_ARG "incomplete character syntax");
07179             return 0;
07180         }
07181         if (rb_enc_isspace(c, current_enc)) {
07182             if (!IS_ARG()) {
07183                 int c2 = 0;
07184                 switch (c) {
07185                   case ' ':
07186                     c2 = 's';
07187                     break;
07188                   case '\n':
07189                     c2 = 'n';
07190                     break;
07191                   case '\t':
07192                     c2 = 't';
07193                     break;
07194                   case '\v':
07195                     c2 = 'v';
07196                     break;
07197                   case '\r':
07198                     c2 = 'r';
07199                     break;
07200                   case '\f':
07201                     c2 = 'f';
07202                     break;
07203                 }
07204                 if (c2) {
07205                     rb_warnI("invalid character syntax; use ?\\%c", c2);
07206                 }
07207             }
07208           ternary:
07209             pushback(c);
07210             lex_state = EXPR_VALUE;
07211             return '?';
07212         }
07213         newtok();
07214         enc = current_enc;
07215         if (!parser_isascii()) {
07216             if (tokadd_mbchar(c) == -1) return 0;
07217         }
07218         else if ((rb_enc_isalnum(c, current_enc) || c == '_') &&
07219                  lex_p < lex_pend && is_identchar(lex_p, lex_pend, current_enc)) {
07220             goto ternary;
07221         }
07222         else if (c == '\\') {
07223             if (peek('u')) {
07224                 nextc();
07225                 c = parser_tokadd_utf8(parser, &enc, 0, 0, 0);
07226                 if (0x80 <= c) {
07227                     tokaddmbc(c, enc);
07228                 }
07229                 else {
07230                     tokadd(c);
07231                 }
07232             }
07233             else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) {
07234                 nextc();
07235                 if (tokadd_mbchar(c) == -1) return 0;
07236             }
07237             else {
07238                 c = read_escape(0, &enc);
07239                 tokadd(c);
07240             }
07241         }
07242         else {
07243             tokadd(c);
07244         }
07245         tokfix();
07246         set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0));
07247         lex_state = EXPR_END;
07248         return tCHAR;
07249 
07250       case '&':
07251         if ((c = nextc()) == '&') {
07252             lex_state = EXPR_BEG;
07253             if ((c = nextc()) == '=') {
07254                 set_yylval_id(tANDOP);
07255                 lex_state = EXPR_BEG;
07256                 return tOP_ASGN;
07257             }
07258             pushback(c);
07259             return tANDOP;
07260         }
07261         else if (c == '=') {
07262             set_yylval_id('&');
07263             lex_state = EXPR_BEG;
07264             return tOP_ASGN;
07265         }
07266         pushback(c);
07267         if (IS_SPCARG(c)) {
07268             rb_warning0("`&' interpreted as argument prefix");
07269             c = tAMPER;
07270         }
07271         else if (IS_BEG()) {
07272             c = tAMPER;
07273         }
07274         else {
07275             warn_balanced("&", "argument prefix");
07276             c = '&';
07277         }
07278         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07279         return c;
07280 
07281       case '|':
07282         if ((c = nextc()) == '|') {
07283             lex_state = EXPR_BEG;
07284             if ((c = nextc()) == '=') {
07285                 set_yylval_id(tOROP);
07286                 lex_state = EXPR_BEG;
07287                 return tOP_ASGN;
07288             }
07289             pushback(c);
07290             return tOROP;
07291         }
07292         if (c == '=') {
07293             set_yylval_id('|');
07294             lex_state = EXPR_BEG;
07295             return tOP_ASGN;
07296         }
07297         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07298         pushback(c);
07299         return '|';
07300 
07301       case '+':
07302         c = nextc();
07303         if (IS_AFTER_OPERATOR()) {
07304             lex_state = EXPR_ARG;
07305             if (c == '@') {
07306                 return tUPLUS;
07307             }
07308             pushback(c);
07309             return '+';
07310         }
07311         if (c == '=') {
07312             set_yylval_id('+');
07313             lex_state = EXPR_BEG;
07314             return tOP_ASGN;
07315         }
07316         if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07317             lex_state = EXPR_BEG;
07318             pushback(c);
07319             if (c != -1 && ISDIGIT(c)) {
07320                 c = '+';
07321                 goto start_num;
07322             }
07323             return tUPLUS;
07324         }
07325         lex_state = EXPR_BEG;
07326         pushback(c);
07327         warn_balanced("+", "unary operator");
07328         return '+';
07329 
07330       case '-':
07331         c = nextc();
07332         if (IS_AFTER_OPERATOR()) {
07333             lex_state = EXPR_ARG;
07334             if (c == '@') {
07335                 return tUMINUS;
07336             }
07337             pushback(c);
07338             return '-';
07339         }
07340         if (c == '=') {
07341             set_yylval_id('-');
07342             lex_state = EXPR_BEG;
07343             return tOP_ASGN;
07344         }
07345         if (c == '>') {
07346             lex_state = EXPR_ENDFN;
07347             return tLAMBDA;
07348         }
07349         if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07350             lex_state = EXPR_BEG;
07351             pushback(c);
07352             if (c != -1 && ISDIGIT(c)) {
07353                 return tUMINUS_NUM;
07354             }
07355             return tUMINUS;
07356         }
07357         lex_state = EXPR_BEG;
07358         pushback(c);
07359         warn_balanced("-", "unary operator");
07360         return '-';
07361 
07362       case '.':
07363         lex_state = EXPR_BEG;
07364         if ((c = nextc()) == '.') {
07365             if ((c = nextc()) == '.') {
07366                 return tDOT3;
07367             }
07368             pushback(c);
07369             return tDOT2;
07370         }
07371         pushback(c);
07372         if (c != -1 && ISDIGIT(c)) {
07373             yyerror("no .<digit> floating literal anymore; put 0 before dot");
07374         }
07375         lex_state = EXPR_DOT;
07376         return '.';
07377 
07378       start_num:
07379       case '0': case '1': case '2': case '3': case '4':
07380       case '5': case '6': case '7': case '8': case '9':
07381         {
07382             int is_float, seen_point, seen_e, nondigit;
07383 
07384             is_float = seen_point = seen_e = nondigit = 0;
07385             lex_state = EXPR_END;
07386             newtok();
07387             if (c == '-' || c == '+') {
07388                 tokadd(c);
07389                 c = nextc();
07390             }
07391             if (c == '0') {
07392 #define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0)
07393                 int start = toklen();
07394                 c = nextc();
07395                 if (c == 'x' || c == 'X') {
07396                     /* hexadecimal */
07397                     c = nextc();
07398                     if (c != -1 && ISXDIGIT(c)) {
07399                         do {
07400                             if (c == '_') {
07401                                 if (nondigit) break;
07402                                 nondigit = c;
07403                                 continue;
07404                             }
07405                             if (!ISXDIGIT(c)) break;
07406                             nondigit = 0;
07407                             tokadd(c);
07408                         } while ((c = nextc()) != -1);
07409                     }
07410                     pushback(c);
07411                     tokfix();
07412                     if (toklen() == start) {
07413                         no_digits();
07414                     }
07415                     else if (nondigit) goto trailing_uc;
07416                     set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE));
07417                     return tINTEGER;
07418                 }
07419                 if (c == 'b' || c == 'B') {
07420                     /* binary */
07421                     c = nextc();
07422                     if (c == '0' || c == '1') {
07423                         do {
07424                             if (c == '_') {
07425                                 if (nondigit) break;
07426                                 nondigit = c;
07427                                 continue;
07428                             }
07429                             if (c != '0' && c != '1') break;
07430                             nondigit = 0;
07431                             tokadd(c);
07432                         } while ((c = nextc()) != -1);
07433                     }
07434                     pushback(c);
07435                     tokfix();
07436                     if (toklen() == start) {
07437                         no_digits();
07438                     }
07439                     else if (nondigit) goto trailing_uc;
07440                     set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE));
07441                     return tINTEGER;
07442                 }
07443                 if (c == 'd' || c == 'D') {
07444                     /* decimal */
07445                     c = nextc();
07446                     if (c != -1 && ISDIGIT(c)) {
07447                         do {
07448                             if (c == '_') {
07449                                 if (nondigit) break;
07450                                 nondigit = c;
07451                                 continue;
07452                             }
07453                             if (!ISDIGIT(c)) break;
07454                             nondigit = 0;
07455                             tokadd(c);
07456                         } while ((c = nextc()) != -1);
07457                     }
07458                     pushback(c);
07459                     tokfix();
07460                     if (toklen() == start) {
07461                         no_digits();
07462                     }
07463                     else if (nondigit) goto trailing_uc;
07464                     set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07465                     return tINTEGER;
07466                 }
07467                 if (c == '_') {
07468                     /* 0_0 */
07469                     goto octal_number;
07470                 }
07471                 if (c == 'o' || c == 'O') {
07472                     /* prefixed octal */
07473                     c = nextc();
07474                     if (c == -1 || c == '_' || !ISDIGIT(c)) {
07475                         no_digits();
07476                     }
07477                 }
07478                 if (c >= '0' && c <= '7') {
07479                     /* octal */
07480                   octal_number:
07481                     do {
07482                         if (c == '_') {
07483                             if (nondigit) break;
07484                             nondigit = c;
07485                             continue;
07486                         }
07487                         if (c < '0' || c > '9') break;
07488                         if (c > '7') goto invalid_octal;
07489                         nondigit = 0;
07490                         tokadd(c);
07491                     } while ((c = nextc()) != -1);
07492                     if (toklen() > start) {
07493                         pushback(c);
07494                         tokfix();
07495                         if (nondigit) goto trailing_uc;
07496                         set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE));
07497                         return tINTEGER;
07498                     }
07499                     if (nondigit) {
07500                         pushback(c);
07501                         goto trailing_uc;
07502                     }
07503                 }
07504                 if (c > '7' && c <= '9') {
07505                   invalid_octal:
07506                     yyerror("Invalid octal digit");
07507                 }
07508                 else if (c == '.' || c == 'e' || c == 'E') {
07509                     tokadd('0');
07510                 }
07511                 else {
07512                     pushback(c);
07513                     set_yylval_literal(INT2FIX(0));
07514                     return tINTEGER;
07515                 }
07516             }
07517 
07518             for (;;) {
07519                 switch (c) {
07520                   case '0': case '1': case '2': case '3': case '4':
07521                   case '5': case '6': case '7': case '8': case '9':
07522                     nondigit = 0;
07523                     tokadd(c);
07524                     break;
07525 
07526                   case '.':
07527                     if (nondigit) goto trailing_uc;
07528                     if (seen_point || seen_e) {
07529                         goto decode_num;
07530                     }
07531                     else {
07532                         int c0 = nextc();
07533                         if (c0 == -1 || !ISDIGIT(c0)) {
07534                             pushback(c0);
07535                             goto decode_num;
07536                         }
07537                         c = c0;
07538                     }
07539                     tokadd('.');
07540                     tokadd(c);
07541                     is_float++;
07542                     seen_point++;
07543                     nondigit = 0;
07544                     break;
07545 
07546                   case 'e':
07547                   case 'E':
07548                     if (nondigit) {
07549                         pushback(c);
07550                         c = nondigit;
07551                         goto decode_num;
07552                     }
07553                     if (seen_e) {
07554                         goto decode_num;
07555                     }
07556                     tokadd(c);
07557                     seen_e++;
07558                     is_float++;
07559                     nondigit = c;
07560                     c = nextc();
07561                     if (c != '-' && c != '+') continue;
07562                     tokadd(c);
07563                     nondigit = c;
07564                     break;
07565 
07566                   case '_':     /* `_' in number just ignored */
07567                     if (nondigit) goto decode_num;
07568                     nondigit = c;
07569                     break;
07570 
07571                   default:
07572                     goto decode_num;
07573                 }
07574                 c = nextc();
07575             }
07576 
07577           decode_num:
07578             pushback(c);
07579             if (nondigit) {
07580                 char tmp[30];
07581               trailing_uc:
07582                 snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit);
07583                 yyerror(tmp);
07584             }
07585             tokfix();
07586             if (is_float) {
07587                 double d = strtod(tok(), 0);
07588                 if (errno == ERANGE) {
07589                     rb_warningS("Float %s out of range", tok());
07590                     errno = 0;
07591                 }
07592                 set_yylval_literal(DBL2NUM(d));
07593                 return tFLOAT;
07594             }
07595             set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07596             return tINTEGER;
07597         }
07598 
07599       case ')':
07600       case ']':
07601         paren_nest--;
07602       case '}':
07603         COND_LEXPOP();
07604         CMDARG_LEXPOP();
07605         if (c == ')')
07606             lex_state = EXPR_ENDFN;
07607         else
07608             lex_state = EXPR_ENDARG;
07609         if (c == '}') {
07610             if (!brace_nest--) c = tSTRING_DEND;
07611         }
07612         return c;
07613 
07614       case ':':
07615         c = nextc();
07616         if (c == ':') {
07617             if (IS_BEG() || IS_lex_state(EXPR_CLASS) || IS_SPCARG(-1)) {
07618                 lex_state = EXPR_BEG;
07619                 return tCOLON3;
07620             }
07621             lex_state = EXPR_DOT;
07622             return tCOLON2;
07623         }
07624         if (IS_END() || ISSPACE(c)) {
07625             pushback(c);
07626             warn_balanced(":", "symbol literal");
07627             lex_state = EXPR_BEG;
07628             return ':';
07629         }
07630         switch (c) {
07631           case '\'':
07632             lex_strterm = NEW_STRTERM(str_ssym, c, 0);
07633             break;
07634           case '"':
07635             lex_strterm = NEW_STRTERM(str_dsym, c, 0);
07636             break;
07637           default:
07638             pushback(c);
07639             break;
07640         }
07641         lex_state = EXPR_FNAME;
07642         return tSYMBEG;
07643 
07644       case '/':
07645         if (IS_lex_state(EXPR_BEG_ANY)) {
07646             lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07647             return tREGEXP_BEG;
07648         }
07649         if ((c = nextc()) == '=') {
07650             set_yylval_id('/');
07651             lex_state = EXPR_BEG;
07652             return tOP_ASGN;
07653         }
07654         pushback(c);
07655         if (IS_SPCARG(c)) {
07656             (void)arg_ambiguous();
07657             lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07658             return tREGEXP_BEG;
07659         }
07660         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07661         warn_balanced("/", "regexp literal");
07662         return '/';
07663 
07664       case '^':
07665         if ((c = nextc()) == '=') {
07666             set_yylval_id('^');
07667             lex_state = EXPR_BEG;
07668             return tOP_ASGN;
07669         }
07670         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07671         pushback(c);
07672         return '^';
07673 
07674       case ';':
07675         lex_state = EXPR_BEG;
07676         command_start = TRUE;
07677         return ';';
07678 
07679       case ',':
07680         lex_state = EXPR_BEG;
07681         return ',';
07682 
07683       case '~':
07684         if (IS_AFTER_OPERATOR()) {
07685             if ((c = nextc()) != '@') {
07686                 pushback(c);
07687             }
07688             lex_state = EXPR_ARG;
07689         }
07690         else {
07691             lex_state = EXPR_BEG;
07692         }
07693         return '~';
07694 
07695       case '(':
07696         if (IS_BEG()) {
07697             c = tLPAREN;
07698         }
07699         else if (IS_SPCARG(-1)) {
07700             c = tLPAREN_ARG;
07701         }
07702         paren_nest++;
07703         COND_PUSH(0);
07704         CMDARG_PUSH(0);
07705         lex_state = EXPR_BEG;
07706         return c;
07707 
07708       case '[':
07709         paren_nest++;
07710         if (IS_AFTER_OPERATOR()) {
07711             lex_state = EXPR_ARG;
07712             if ((c = nextc()) == ']') {
07713                 if ((c = nextc()) == '=') {
07714                     return tASET;
07715                 }
07716                 pushback(c);
07717                 return tAREF;
07718             }
07719             pushback(c);
07720             return '[';
07721         }
07722         else if (IS_BEG()) {
07723             c = tLBRACK;
07724         }
07725         else if (IS_ARG() && space_seen) {
07726             c = tLBRACK;
07727         }
07728         lex_state = EXPR_BEG;
07729         COND_PUSH(0);
07730         CMDARG_PUSH(0);
07731         return c;
07732 
07733       case '{':
07734         ++brace_nest;
07735         if (lpar_beg && lpar_beg == paren_nest) {
07736             lex_state = EXPR_BEG;
07737             lpar_beg = 0;
07738             --paren_nest;
07739             COND_PUSH(0);
07740             CMDARG_PUSH(0);
07741             return tLAMBEG;
07742         }
07743         if (IS_ARG() || IS_lex_state(EXPR_END | EXPR_ENDFN))
07744             c = '{';          /* block (primary) */
07745         else if (IS_lex_state(EXPR_ENDARG))
07746             c = tLBRACE_ARG;  /* block (expr) */
07747         else
07748             c = tLBRACE;      /* hash */
07749         COND_PUSH(0);
07750         CMDARG_PUSH(0);
07751         lex_state = EXPR_BEG;
07752         if (c != tLBRACE) command_start = TRUE;
07753         return c;
07754 
07755       case '\\':
07756         c = nextc();
07757         if (c == '\n') {
07758             space_seen = 1;
07759 #ifdef RIPPER
07760             ripper_dispatch_scan_event(parser, tSP);
07761 #endif
07762             goto retry; /* skip \\n */
07763         }
07764         pushback(c);
07765         return '\\';
07766 
07767       case '%':
07768         if (IS_lex_state(EXPR_BEG_ANY)) {
07769             int term;
07770             int paren;
07771 
07772             c = nextc();
07773           quotation:
07774             if (c == -1 || !ISALNUM(c)) {
07775                 term = c;
07776                 c = 'Q';
07777             }
07778             else {
07779                 term = nextc();
07780                 if (rb_enc_isalnum(term, current_enc) || !parser_isascii()) {
07781                     yyerror("unknown type of %string");
07782                     return 0;
07783                 }
07784             }
07785             if (c == -1 || term == -1) {
07786                 compile_error(PARSER_ARG "unterminated quoted string meets end of file");
07787                 return 0;
07788             }
07789             paren = term;
07790             if (term == '(') term = ')';
07791             else if (term == '[') term = ']';
07792             else if (term == '{') term = '}';
07793             else if (term == '<') term = '>';
07794             else paren = 0;
07795 
07796             switch (c) {
07797               case 'Q':
07798                 lex_strterm = NEW_STRTERM(str_dquote, term, paren);
07799                 return tSTRING_BEG;
07800 
07801               case 'q':
07802                 lex_strterm = NEW_STRTERM(str_squote, term, paren);
07803                 return tSTRING_BEG;
07804 
07805               case 'W':
07806                 lex_strterm = NEW_STRTERM(str_dword, term, paren);
07807                 do {c = nextc();} while (ISSPACE(c));
07808                 pushback(c);
07809                 return tWORDS_BEG;
07810 
07811               case 'w':
07812                 lex_strterm = NEW_STRTERM(str_sword, term, paren);
07813                 do {c = nextc();} while (ISSPACE(c));
07814                 pushback(c);
07815                 return tQWORDS_BEG;
07816 
07817               case 'I':
07818                 lex_strterm = NEW_STRTERM(str_dword, term, paren);
07819                 do {c = nextc();} while (ISSPACE(c));
07820                 pushback(c);
07821                 return tSYMBOLS_BEG;
07822 
07823               case 'i':
07824                 lex_strterm = NEW_STRTERM(str_sword, term, paren);
07825                 do {c = nextc();} while (ISSPACE(c));
07826                 pushback(c);
07827                 return tQSYMBOLS_BEG;
07828 
07829               case 'x':
07830                 lex_strterm = NEW_STRTERM(str_xquote, term, paren);
07831                 return tXSTRING_BEG;
07832 
07833               case 'r':
07834                 lex_strterm = NEW_STRTERM(str_regexp, term, paren);
07835                 return tREGEXP_BEG;
07836 
07837               case 's':
07838                 lex_strterm = NEW_STRTERM(str_ssym, term, paren);
07839                 lex_state = EXPR_FNAME;
07840                 return tSYMBEG;
07841 
07842               default:
07843                 yyerror("unknown type of %string");
07844                 return 0;
07845             }
07846         }
07847         if ((c = nextc()) == '=') {
07848             set_yylval_id('%');
07849             lex_state = EXPR_BEG;
07850             return tOP_ASGN;
07851         }
07852         if (IS_SPCARG(c)) {
07853             goto quotation;
07854         }
07855         lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
07856         pushback(c);
07857         warn_balanced("%%", "string literal");
07858         return '%';
07859 
07860       case '$':
07861         lex_state = EXPR_END;
07862         newtok();
07863         c = nextc();
07864         switch (c) {
07865           case '_':             /* $_: last read line string */
07866             c = nextc();
07867             if (parser_is_identchar()) {
07868                 tokadd('$');
07869                 tokadd('_');
07870                 break;
07871             }
07872             pushback(c);
07873             c = '_';
07874             /* fall through */
07875           case '~':             /* $~: match-data */
07876           case '*':             /* $*: argv */
07877           case '$':             /* $$: pid */
07878           case '?':             /* $?: last status */
07879           case '!':             /* $!: error string */
07880           case '@':             /* $@: error position */
07881           case '/':             /* $/: input record separator */
07882           case '\\':            /* $\: output record separator */
07883           case ';':             /* $;: field separator */
07884           case ',':             /* $,: output field separator */
07885           case '.':             /* $.: last read line number */
07886           case '=':             /* $=: ignorecase */
07887           case ':':             /* $:: load path */
07888           case '<':             /* $<: reading filename */
07889           case '>':             /* $>: default output handle */
07890           case '\"':            /* $": already loaded files */
07891             tokadd('$');
07892             tokadd(c);
07893             tokfix();
07894             set_yylval_name(rb_intern(tok()));
07895             return tGVAR;
07896 
07897           case '-':
07898             tokadd('$');
07899             tokadd(c);
07900             c = nextc();
07901             if (parser_is_identchar()) {
07902                 if (tokadd_mbchar(c) == -1) return 0;
07903             }
07904             else {
07905                 pushback(c);
07906             }
07907           gvar:
07908             tokfix();
07909             set_yylval_name(rb_intern(tok()));
07910             return tGVAR;
07911 
07912           case '&':             /* $&: last match */
07913           case '`':             /* $`: string before last match */
07914           case '\'':            /* $': string after last match */
07915           case '+':             /* $+: string matches last paren. */
07916             if (IS_lex_state_for(last_state, EXPR_FNAME)) {
07917                 tokadd('$');
07918                 tokadd(c);
07919                 goto gvar;
07920             }
07921             set_yylval_node(NEW_BACK_REF(c));
07922             return tBACK_REF;
07923 
07924           case '1': case '2': case '3':
07925           case '4': case '5': case '6':
07926           case '7': case '8': case '9':
07927             tokadd('$');
07928             do {
07929                 tokadd(c);
07930                 c = nextc();
07931             } while (c != -1 && ISDIGIT(c));
07932             pushback(c);
07933             if (IS_lex_state_for(last_state, EXPR_FNAME)) goto gvar;
07934             tokfix();
07935             set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
07936             return tNTH_REF;
07937 
07938           default:
07939             if (!parser_is_identchar()) {
07940                 pushback(c);
07941                 compile_error(PARSER_ARG "`$%c' is not allowed as a global variable name", c);
07942                 return 0;
07943             }
07944           case '0':
07945             tokadd('$');
07946         }
07947         break;
07948 
07949       case '@':
07950         c = nextc();
07951         newtok();
07952         tokadd('@');
07953         if (c == '@') {
07954             tokadd('@');
07955             c = nextc();
07956         }
07957         if (c != -1 && (ISDIGIT(c) || !parser_is_identchar())) {
07958             pushback(c);
07959             if (tokidx == 1) {
07960                 compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
07961             }
07962             else {
07963                 compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
07964             }
07965             return 0;
07966         }
07967         break;
07968 
07969       case '_':
07970         if (was_bol() && whole_match_p("__END__", 7, 0)) {
07971             ruby__end__seen = 1;
07972             parser->eofp = Qtrue;
07973 #ifndef RIPPER
07974             return -1;
07975 #else
07976             lex_goto_eol(parser);
07977             ripper_dispatch_scan_event(parser, k__END__);
07978             return 0;
07979 #endif
07980         }
07981         newtok();
07982         break;
07983 
07984       default:
07985         if (!parser_is_identchar()) {
07986             compile_error(PARSER_ARG  "Invalid char `\\x%02X' in expression", c);
07987             goto retry;
07988         }
07989 
07990         newtok();
07991         break;
07992     }
07993 
07994     mb = ENC_CODERANGE_7BIT;
07995     do {
07996         if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
07997         if (tokadd_mbchar(c) == -1) return 0;
07998         c = nextc();
07999     } while (parser_is_identchar());
08000     switch (tok()[0]) {
08001       case '@': case '$':
08002         pushback(c);
08003         break;
08004       default:
08005         if ((c == '!' || c == '?') && !peek('=')) {
08006             tokadd(c);
08007         }
08008         else {
08009             pushback(c);
08010         }
08011     }
08012     tokfix();
08013 
08014     {
08015         int result = 0;
08016 
08017         last_state = lex_state;
08018         switch (tok()[0]) {
08019           case '$':
08020             lex_state = EXPR_END;
08021             result = tGVAR;
08022             break;
08023           case '@':
08024             lex_state = EXPR_END;
08025             if (tok()[1] == '@')
08026                 result = tCVAR;
08027             else
08028                 result = tIVAR;
08029             break;
08030 
08031           default:
08032             if (toklast() == '!' || toklast() == '?') {
08033                 result = tFID;
08034             }
08035             else {
08036                 if (IS_lex_state(EXPR_FNAME)) {
08037                     if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
08038                         (!peek('=') || (peek_n('>', 1)))) {
08039                         result = tIDENTIFIER;
08040                         tokadd(c);
08041                         tokfix();
08042                     }
08043                     else {
08044                         pushback(c);
08045                     }
08046                 }
08047                 if (result == 0 && ISUPPER(tok()[0])) {
08048                     result = tCONSTANT;
08049                 }
08050                 else {
08051                     result = tIDENTIFIER;
08052                 }
08053             }
08054 
08055             if (IS_LABEL_POSSIBLE()) {
08056                 if (IS_LABEL_SUFFIX(0)) {
08057                     lex_state = EXPR_BEG;
08058                     nextc();
08059                     set_yylval_name(TOK_INTERN(!ENC_SINGLE(mb)));
08060                     return tLABEL;
08061                 }
08062             }
08063             if (mb == ENC_CODERANGE_7BIT && !IS_lex_state(EXPR_DOT)) {
08064                 const struct kwtable *kw;
08065 
08066                 /* See if it is a reserved word.  */
08067                 kw = rb_reserved_word(tok(), toklen());
08068                 if (kw) {
08069                     enum lex_state_e state = lex_state;
08070                     lex_state = kw->state;
08071                     if (state == EXPR_FNAME) {
08072                         set_yylval_name(rb_intern(kw->name));
08073                         return kw->id[0];
08074                     }
08075                     if (lex_state == EXPR_BEG) {
08076                         command_start = TRUE;
08077                     }
08078                     if (kw->id[0] == keyword_do) {
08079                         if (lpar_beg && lpar_beg == paren_nest) {
08080                             lpar_beg = 0;
08081                             --paren_nest;
08082                             return keyword_do_LAMBDA;
08083                         }
08084                         if (COND_P()) return keyword_do_cond;
08085                         if (CMDARG_P() && state != EXPR_CMDARG)
08086                             return keyword_do_block;
08087                         if (state & (EXPR_BEG | EXPR_ENDARG))
08088                             return keyword_do_block;
08089                         return keyword_do;
08090                     }
08091                     if (state & (EXPR_BEG | EXPR_VALUE))
08092                         return kw->id[0];
08093                     else {
08094                         if (kw->id[0] != kw->id[1])
08095                             lex_state = EXPR_BEG;
08096                         return kw->id[1];
08097                     }
08098                 }
08099             }
08100 
08101             if (IS_lex_state(EXPR_BEG_ANY | EXPR_ARG_ANY | EXPR_DOT)) {
08102                 if (cmd_state) {
08103                     lex_state = EXPR_CMDARG;
08104                 }
08105                 else {
08106                     lex_state = EXPR_ARG;
08107                 }
08108             }
08109             else if (lex_state == EXPR_FNAME) {
08110                 lex_state = EXPR_ENDFN;
08111             }
08112             else {
08113                 lex_state = EXPR_END;
08114             }
08115         }
08116         {
08117             ID ident = TOK_INTERN(!ENC_SINGLE(mb));
08118 
08119             set_yylval_name(ident);
08120             if (!IS_lex_state_for(last_state, EXPR_DOT|EXPR_FNAME) &&
08121                 is_local_id(ident) && lvar_defined(ident)) {
08122                 lex_state = EXPR_END;
08123             }
08124         }
08125         return result;
08126     }
08127 }
08128 
08129 #if YYPURE
08130 static int
08131 yylex(void *lval, void *p)
08132 #else
08133 yylex(void *p)
08134 #endif
08135 {
08136     struct parser_params *parser = (struct parser_params*)p;
08137     int t;
08138 
08139 #if YYPURE
08140     parser->parser_yylval = lval;
08141     parser->parser_yylval->val = Qundef;
08142 #endif
08143     t = parser_yylex(parser);
08144 #ifdef RIPPER
08145     if (!NIL_P(parser->delayed)) {
08146         ripper_dispatch_delayed_token(parser, t);
08147         return t;
08148     }
08149     if (t != 0)
08150         ripper_dispatch_scan_event(parser, t);
08151 #endif
08152 
08153     return t;
08154 }
08155 
08156 #ifndef RIPPER
08157 static NODE*
08158 node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
08159 {
08160     NODE *n = (rb_node_newnode)(type, a0, a1, a2);
08161     nd_set_line(n, ruby_sourceline);
08162     return n;
08163 }
08164 
08165 static enum node_type
08166 nodetype(NODE *node)                    /* for debug */
08167 {
08168     return (enum node_type)nd_type(node);
08169 }
08170 
08171 static int
08172 nodeline(NODE *node)
08173 {
08174     return nd_line(node);
08175 }
08176 
08177 static NODE*
08178 newline_node(NODE *node)
08179 {
08180     if (node) {
08181         node = remove_begin(node);
08182         node->flags |= NODE_FL_NEWLINE;
08183     }
08184     return node;
08185 }
08186 
08187 static void
08188 fixpos(NODE *node, NODE *orig)
08189 {
08190     if (!node) return;
08191     if (!orig) return;
08192     if (orig == (NODE*)1) return;
08193     nd_set_line(node, nd_line(orig));
08194 }
08195 
08196 static void
08197 parser_warning(struct parser_params *parser, NODE *node, const char *mesg)
08198 {
08199     rb_compile_warning(ruby_sourcefile, nd_line(node), "%s", mesg);
08200 }
08201 #define parser_warning(node, mesg) parser_warning(parser, (node), (mesg))
08202 
08203 static void
08204 parser_warn(struct parser_params *parser, NODE *node, const char *mesg)
08205 {
08206     rb_compile_warn(ruby_sourcefile, nd_line(node), "%s", mesg);
08207 }
08208 #define parser_warn(node, mesg) parser_warn(parser, (node), (mesg))
08209 
08210 static NODE*
08211 block_append_gen(struct parser_params *parser, NODE *head, NODE *tail)
08212 {
08213     NODE *end, *h = head, *nd;
08214 
08215     if (tail == 0) return head;
08216 
08217     if (h == 0) return tail;
08218     switch (nd_type(h)) {
08219       case NODE_LIT:
08220       case NODE_STR:
08221       case NODE_SELF:
08222       case NODE_TRUE:
08223       case NODE_FALSE:
08224       case NODE_NIL:
08225         parser_warning(h, "unused literal ignored");
08226         return tail;
08227       default:
08228         h = end = NEW_BLOCK(head);
08229         end->nd_end = end;
08230         fixpos(end, head);
08231         head = end;
08232         break;
08233       case NODE_BLOCK:
08234         end = h->nd_end;
08235         break;
08236     }
08237 
08238     nd = end->nd_head;
08239     switch (nd_type(nd)) {
08240       case NODE_RETURN:
08241       case NODE_BREAK:
08242       case NODE_NEXT:
08243       case NODE_REDO:
08244       case NODE_RETRY:
08245         if (RTEST(ruby_verbose)) {
08246             parser_warning(tail, "statement not reached");
08247         }
08248         break;
08249 
08250       default:
08251         break;
08252     }
08253 
08254     if (nd_type(tail) != NODE_BLOCK) {
08255         tail = NEW_BLOCK(tail);
08256         tail->nd_end = tail;
08257     }
08258     end->nd_next = tail;
08259     h->nd_end = tail->nd_end;
08260     return head;
08261 }
08262 
08263 /* append item to the list */
08264 static NODE*
08265 list_append_gen(struct parser_params *parser, NODE *list, NODE *item)
08266 {
08267     NODE *last;
08268 
08269     if (list == 0) return NEW_LIST(item);
08270     if (list->nd_next) {
08271         last = list->nd_next->nd_end;
08272     }
08273     else {
08274         last = list;
08275     }
08276 
08277     list->nd_alen += 1;
08278     last->nd_next = NEW_LIST(item);
08279     list->nd_next->nd_end = last->nd_next;
08280     return list;
08281 }
08282 
08283 /* concat two lists */
08284 static NODE*
08285 list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08286 {
08287     NODE *last;
08288 
08289     if (head->nd_next) {
08290         last = head->nd_next->nd_end;
08291     }
08292     else {
08293         last = head;
08294     }
08295 
08296     head->nd_alen += tail->nd_alen;
08297     last->nd_next = tail;
08298     if (tail->nd_next) {
08299         head->nd_next->nd_end = tail->nd_next->nd_end;
08300     }
08301     else {
08302         head->nd_next->nd_end = tail;
08303     }
08304 
08305     return head;
08306 }
08307 
08308 static int
08309 literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
08310 {
08311     if (NIL_P(tail)) return 1;
08312     if (!rb_enc_compatible(head, tail)) {
08313         compile_error(PARSER_ARG "string literal encodings differ (%s / %s)",
08314                       rb_enc_name(rb_enc_get(head)),
08315                       rb_enc_name(rb_enc_get(tail)));
08316         rb_str_resize(head, 0);
08317         rb_str_resize(tail, 0);
08318         return 0;
08319     }
08320     rb_str_buf_append(head, tail);
08321     return 1;
08322 }
08323 
08324 /* concat two string literals */
08325 static NODE *
08326 literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08327 {
08328     enum node_type htype;
08329     NODE *headlast;
08330     VALUE lit;
08331 
08332     if (!head) return tail;
08333     if (!tail) return head;
08334 
08335     htype = nd_type(head);
08336     if (htype == NODE_EVSTR) {
08337         NODE *node = NEW_DSTR(Qnil);
08338         head = list_append(node, head);
08339         htype = NODE_DSTR;
08340     }
08341     switch (nd_type(tail)) {
08342       case NODE_STR:
08343         if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
08344             nd_type(headlast) == NODE_STR) {
08345             htype = NODE_STR;
08346             lit = headlast->nd_lit;
08347         }
08348         else {
08349             lit = head->nd_lit;
08350         }
08351         if (htype == NODE_STR) {
08352             if (!literal_concat0(parser, lit, tail->nd_lit)) {
08353               error:
08354                 rb_gc_force_recycle((VALUE)head);
08355                 rb_gc_force_recycle((VALUE)tail);
08356                 return 0;
08357             }
08358             rb_gc_force_recycle((VALUE)tail);
08359         }
08360         else {
08361             list_append(head, tail);
08362         }
08363         break;
08364 
08365       case NODE_DSTR:
08366         if (htype == NODE_STR) {
08367             if (!literal_concat0(parser, head->nd_lit, tail->nd_lit))
08368                 goto error;
08369             tail->nd_lit = head->nd_lit;
08370             rb_gc_force_recycle((VALUE)head);
08371             head = tail;
08372         }
08373         else if (NIL_P(tail->nd_lit)) {
08374           append:
08375             head->nd_alen += tail->nd_alen - 1;
08376             head->nd_next->nd_end->nd_next = tail->nd_next;
08377             head->nd_next->nd_end = tail->nd_next->nd_end;
08378             rb_gc_force_recycle((VALUE)tail);
08379         }
08380         else if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
08381                  nd_type(headlast) == NODE_STR) {
08382             lit = headlast->nd_lit;
08383             if (!literal_concat0(parser, lit, tail->nd_lit))
08384                 goto error;
08385             tail->nd_lit = Qnil;
08386             goto append;
08387         }
08388         else {
08389             nd_set_type(tail, NODE_ARRAY);
08390             tail->nd_head = NEW_STR(tail->nd_lit);
08391             list_concat(head, tail);
08392         }
08393         break;
08394 
08395       case NODE_EVSTR:
08396         if (htype == NODE_STR) {
08397             nd_set_type(head, NODE_DSTR);
08398             head->nd_alen = 1;
08399         }
08400         list_append(head, tail);
08401         break;
08402     }
08403     return head;
08404 }
08405 
08406 static NODE *
08407 evstr2dstr_gen(struct parser_params *parser, NODE *node)
08408 {
08409     if (nd_type(node) == NODE_EVSTR) {
08410         node = list_append(NEW_DSTR(Qnil), node);
08411     }
08412     return node;
08413 }
08414 
08415 static NODE *
08416 new_evstr_gen(struct parser_params *parser, NODE *node)
08417 {
08418     NODE *head = node;
08419 
08420     if (node) {
08421         switch (nd_type(node)) {
08422           case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
08423             return node;
08424         }
08425     }
08426     return NEW_EVSTR(head);
08427 }
08428 
08429 static NODE *
08430 call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
08431 {
08432     value_expr(recv);
08433     value_expr(arg1);
08434     return NEW_CALL(recv, id, NEW_LIST(arg1));
08435 }
08436 
08437 static NODE *
08438 call_uni_op_gen(struct parser_params *parser, NODE *recv, ID id)
08439 {
08440     value_expr(recv);
08441     return NEW_CALL(recv, id, 0);
08442 }
08443 
08444 static NODE*
08445 match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08446 {
08447     value_expr(node1);
08448     value_expr(node2);
08449     if (node1) {
08450         switch (nd_type(node1)) {
08451           case NODE_DREGX:
08452           case NODE_DREGX_ONCE:
08453             return NEW_MATCH2(node1, node2);
08454 
08455           case NODE_LIT:
08456             if (RB_TYPE_P(node1->nd_lit, T_REGEXP)) {
08457                 return NEW_MATCH2(node1, node2);
08458             }
08459         }
08460     }
08461 
08462     if (node2) {
08463         switch (nd_type(node2)) {
08464           case NODE_DREGX:
08465           case NODE_DREGX_ONCE:
08466             return NEW_MATCH3(node2, node1);
08467 
08468           case NODE_LIT:
08469             if (RB_TYPE_P(node2->nd_lit, T_REGEXP)) {
08470                 return NEW_MATCH3(node2, node1);
08471             }
08472         }
08473     }
08474 
08475     return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
08476 }
08477 
08478 static NODE*
08479 gettable_gen(struct parser_params *parser, ID id)
08480 {
08481     switch (id) {
08482       case keyword_self:
08483         return NEW_SELF();
08484       case keyword_nil:
08485         return NEW_NIL();
08486       case keyword_true:
08487         return NEW_TRUE();
08488       case keyword_false:
08489         return NEW_FALSE();
08490       case keyword__FILE__:
08491         return NEW_STR(rb_str_dup(ruby_sourcefile_string));
08492       case keyword__LINE__:
08493         return NEW_LIT(INT2FIX(tokline));
08494       case keyword__ENCODING__:
08495         return NEW_LIT(rb_enc_from_encoding(current_enc));
08496     }
08497     switch (id_type(id)) {
08498       case ID_LOCAL:
08499         if (dyna_in_block() && dvar_defined(id)) return NEW_DVAR(id);
08500         if (local_id(id)) return NEW_LVAR(id);
08501         /* method call without arguments */
08502         return NEW_VCALL(id);
08503       case ID_GLOBAL:
08504         return NEW_GVAR(id);
08505       case ID_INSTANCE:
08506         return NEW_IVAR(id);
08507       case ID_CONST:
08508         return NEW_CONST(id);
08509       case ID_CLASS:
08510         return NEW_CVAR(id);
08511     }
08512     compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08513     return 0;
08514 }
08515 #else  /* !RIPPER */
08516 static int
08517 id_is_var_gen(struct parser_params *parser, ID id)
08518 {
08519     if (is_notop_id(id)) {
08520         switch (id & ID_SCOPE_MASK) {
08521           case ID_GLOBAL: case ID_INSTANCE: case ID_CONST: case ID_CLASS:
08522             return 1;
08523           case ID_LOCAL:
08524             if (dyna_in_block() && dvar_defined(id)) return 1;
08525             if (local_id(id)) return 1;
08526             /* method call without arguments */
08527             return 0;
08528         }
08529     }
08530     compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08531     return 0;
08532 }
08533 #endif /* !RIPPER */
08534 
08535 #if PARSER_DEBUG
08536 static const char *
08537 lex_state_name(enum lex_state_e state)
08538 {
08539     static const char names[][12] = {
08540         "EXPR_BEG",    "EXPR_END",    "EXPR_ENDARG", "EXPR_ENDFN",  "EXPR_ARG",
08541         "EXPR_CMDARG", "EXPR_MID",    "EXPR_FNAME",  "EXPR_DOT",    "EXPR_CLASS",
08542         "EXPR_VALUE",
08543     };
08544 
08545     if ((unsigned)state & ~(~0u << EXPR_MAX_STATE))
08546         return names[ffs(state)];
08547     return NULL;
08548 }
08549 #endif
08550 
08551 #ifdef RIPPER
08552 static VALUE
08553 assignable_gen(struct parser_params *parser, VALUE lhs)
08554 #else
08555 static NODE*
08556 assignable_gen(struct parser_params *parser, ID id, NODE *val)
08557 #endif
08558 {
08559 #ifdef RIPPER
08560     ID id = get_id(lhs);
08561 # define assignable_result(x) get_value(lhs)
08562 # define parser_yyerror(parser, x) dispatch1(assign_error, lhs)
08563 #else
08564 # define assignable_result(x) (x)
08565 #endif
08566     if (!id) return assignable_result(0);
08567     switch (id) {
08568       case keyword_self:
08569         yyerror("Can't change the value of self");
08570         goto error;
08571       case keyword_nil:
08572         yyerror("Can't assign to nil");
08573         goto error;
08574       case keyword_true:
08575         yyerror("Can't assign to true");
08576         goto error;
08577       case keyword_false:
08578         yyerror("Can't assign to false");
08579         goto error;
08580       case keyword__FILE__:
08581         yyerror("Can't assign to __FILE__");
08582         goto error;
08583       case keyword__LINE__:
08584         yyerror("Can't assign to __LINE__");
08585         goto error;
08586       case keyword__ENCODING__:
08587         yyerror("Can't assign to __ENCODING__");
08588         goto error;
08589     }
08590     switch (id_type(id)) {
08591       case ID_LOCAL:
08592         if (dyna_in_block()) {
08593             if (dvar_curr(id)) {
08594                 return assignable_result(NEW_DASGN_CURR(id, val));
08595             }
08596             else if (dvar_defined(id)) {
08597                 return assignable_result(NEW_DASGN(id, val));
08598             }
08599             else if (local_id(id)) {
08600                 return assignable_result(NEW_LASGN(id, val));
08601             }
08602             else {
08603                 dyna_var(id);
08604                 return assignable_result(NEW_DASGN_CURR(id, val));
08605             }
08606         }
08607         else {
08608             if (!local_id(id)) {
08609                 local_var(id);
08610             }
08611             return assignable_result(NEW_LASGN(id, val));
08612         }
08613         break;
08614       case ID_GLOBAL:
08615         return assignable_result(NEW_GASGN(id, val));
08616       case ID_INSTANCE:
08617         return assignable_result(NEW_IASGN(id, val));
08618       case ID_CONST:
08619         if (!in_def && !in_single)
08620             return assignable_result(NEW_CDECL(id, val, 0));
08621         yyerror("dynamic constant assignment");
08622         break;
08623       case ID_CLASS:
08624         return assignable_result(NEW_CVASGN(id, val));
08625       default:
08626         compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
08627     }
08628   error:
08629     return assignable_result(0);
08630 #undef assignable_result
08631 #undef parser_yyerror
08632 }
08633 
08634 static int
08635 is_private_local_id(ID name)
08636 {
08637     VALUE s;
08638     if (name == idUScore) return 1;
08639     if (!is_local_id(name)) return 0;
08640     s = rb_id2str(name);
08641     if (!s) return 0;
08642     return RSTRING_PTR(s)[0] == '_';
08643 }
08644 
08645 #define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
08646 
08647 static ID
08648 shadowing_lvar_gen(struct parser_params *parser, ID name)
08649 {
08650     if (is_private_local_id(name)) return name;
08651     if (dyna_in_block()) {
08652         if (dvar_curr(name)) {
08653             yyerror("duplicated argument name");
08654         }
08655         else if (dvar_defined_get(name) || local_id(name)) {
08656             rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
08657             vtable_add(lvtbl->vars, name);
08658             if (lvtbl->used) {
08659                 vtable_add(lvtbl->used, (ID)ruby_sourceline | LVAR_USED);
08660             }
08661         }
08662     }
08663     else {
08664         if (local_id(name)) {
08665             yyerror("duplicated argument name");
08666         }
08667     }
08668     return name;
08669 }
08670 
08671 static void
08672 new_bv_gen(struct parser_params *parser, ID name)
08673 {
08674     if (!name) return;
08675     if (!is_local_id(name)) {
08676         compile_error(PARSER_ARG "invalid local variable - %s",
08677                       rb_id2name(name));
08678         return;
08679     }
08680     shadowing_lvar(name);
08681     dyna_var(name);
08682 }
08683 
08684 #ifndef RIPPER
08685 static NODE *
08686 aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
08687 {
08688     if (recv && nd_type(recv) == NODE_SELF)
08689         recv = (NODE *)1;
08690     return NEW_ATTRASGN(recv, tASET, idx);
08691 }
08692 
08693 static void
08694 block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08695 {
08696     if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
08697         compile_error(PARSER_ARG "both block arg and actual block given");
08698     }
08699 }
08700 
08701 static const char id_type_names[][9] = {
08702     "LOCAL",
08703     "INSTANCE",
08704     "",                         /* INSTANCE2 */
08705     "GLOBAL",
08706     "ATTRSET",
08707     "CONST",
08708     "CLASS",
08709     "JUNK",
08710 };
08711 
08712 ID
08713 rb_id_attrset(ID id)
08714 {
08715     if (!is_notop_id(id)) {
08716         switch (id) {
08717           case tAREF: case tASET:
08718             return tASET;       /* only exception */
08719         }
08720         rb_name_error(id, "cannot make operator ID :%s attrset", rb_id2name(id));
08721     }
08722     else {
08723         int scope = (int)(id & ID_SCOPE_MASK);
08724         switch (scope) {
08725           case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
08726           case ID_CONST: case ID_CLASS: case ID_JUNK:
08727             break;
08728           case ID_ATTRSET:
08729             return id;
08730           default:
08731             rb_name_error(id, "cannot make %s ID %+"PRIsVALUE" attrset",
08732                           id_type_names[scope], ID2SYM(id));
08733 
08734         }
08735     }
08736     id &= ~ID_SCOPE_MASK;
08737     id |= ID_ATTRSET;
08738     return id;
08739 }
08740 
08741 static NODE *
08742 attrset_gen(struct parser_params *parser, NODE *recv, ID id)
08743 {
08744     if (recv && nd_type(recv) == NODE_SELF)
08745         recv = (NODE *)1;
08746     return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
08747 }
08748 
08749 static void
08750 rb_backref_error_gen(struct parser_params *parser, NODE *node)
08751 {
08752     switch (nd_type(node)) {
08753       case NODE_NTH_REF:
08754         compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth);
08755         break;
08756       case NODE_BACK_REF:
08757         compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth);
08758         break;
08759     }
08760 }
08761 
08762 static NODE *
08763 arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08764 {
08765     if (!node2) return node1;
08766     switch (nd_type(node1)) {
08767       case NODE_BLOCK_PASS:
08768         if (node1->nd_head)
08769             node1->nd_head = arg_concat(node1->nd_head, node2);
08770         else
08771             node1->nd_head = NEW_LIST(node2);
08772         return node1;
08773       case NODE_ARGSPUSH:
08774         if (nd_type(node2) != NODE_ARRAY) break;
08775         node1->nd_body = list_concat(NEW_LIST(node1->nd_body), node2);
08776         nd_set_type(node1, NODE_ARGSCAT);
08777         return node1;
08778       case NODE_ARGSCAT:
08779         if (nd_type(node2) != NODE_ARRAY ||
08780             nd_type(node1->nd_body) != NODE_ARRAY) break;
08781         node1->nd_body = list_concat(node1->nd_body, node2);
08782         return node1;
08783     }
08784     return NEW_ARGSCAT(node1, node2);
08785 }
08786 
08787 static NODE *
08788 arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08789 {
08790     if (!node1) return NEW_LIST(node2);
08791     switch (nd_type(node1))  {
08792       case NODE_ARRAY:
08793         return list_append(node1, node2);
08794       case NODE_BLOCK_PASS:
08795         node1->nd_head = arg_append(node1->nd_head, node2);
08796         return node1;
08797       case NODE_ARGSPUSH:
08798         node1->nd_body = list_append(NEW_LIST(node1->nd_body), node2);
08799         nd_set_type(node1, NODE_ARGSCAT);
08800         return node1;
08801     }
08802     return NEW_ARGSPUSH(node1, node2);
08803 }
08804 
08805 static NODE *
08806 splat_array(NODE* node)
08807 {
08808     if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
08809     if (nd_type(node) == NODE_ARRAY) return node;
08810     return 0;
08811 }
08812 
08813 static NODE *
08814 node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
08815 {
08816     if (!lhs) return 0;
08817 
08818     switch (nd_type(lhs)) {
08819       case NODE_GASGN:
08820       case NODE_IASGN:
08821       case NODE_IASGN2:
08822       case NODE_LASGN:
08823       case NODE_DASGN:
08824       case NODE_DASGN_CURR:
08825       case NODE_MASGN:
08826       case NODE_CDECL:
08827       case NODE_CVASGN:
08828         lhs->nd_value = rhs;
08829         break;
08830 
08831       case NODE_ATTRASGN:
08832       case NODE_CALL:
08833         lhs->nd_args = arg_append(lhs->nd_args, rhs);
08834         break;
08835 
08836       default:
08837         /* should not happen */
08838         break;
08839     }
08840 
08841     return lhs;
08842 }
08843 
08844 static int
08845 value_expr_gen(struct parser_params *parser, NODE *node)
08846 {
08847     int cond = 0;
08848 
08849     if (!node) {
08850         rb_warning0("empty expression");
08851     }
08852     while (node) {
08853         switch (nd_type(node)) {
08854           case NODE_DEFN:
08855           case NODE_DEFS:
08856             parser_warning(node, "void value expression");
08857             return FALSE;
08858 
08859           case NODE_RETURN:
08860           case NODE_BREAK:
08861           case NODE_NEXT:
08862           case NODE_REDO:
08863           case NODE_RETRY:
08864             if (!cond) yyerror("void value expression");
08865             /* or "control never reach"? */
08866             return FALSE;
08867 
08868           case NODE_BLOCK:
08869             while (node->nd_next) {
08870                 node = node->nd_next;
08871             }
08872             node = node->nd_head;
08873             break;
08874 
08875           case NODE_BEGIN:
08876             node = node->nd_body;
08877             break;
08878 
08879           case NODE_IF:
08880             if (!node->nd_body) {
08881                 node = node->nd_else;
08882                 break;
08883             }
08884             else if (!node->nd_else) {
08885                 node = node->nd_body;
08886                 break;
08887             }
08888             if (!value_expr(node->nd_body)) return FALSE;
08889             node = node->nd_else;
08890             break;
08891 
08892           case NODE_AND:
08893           case NODE_OR:
08894             cond = 1;
08895             node = node->nd_2nd;
08896             break;
08897 
08898           default:
08899             return TRUE;
08900         }
08901     }
08902 
08903     return TRUE;
08904 }
08905 
08906 static void
08907 void_expr_gen(struct parser_params *parser, NODE *node)
08908 {
08909     const char *useless = 0;
08910 
08911     if (!RTEST(ruby_verbose)) return;
08912 
08913     if (!node) return;
08914     switch (nd_type(node)) {
08915       case NODE_CALL:
08916         switch (node->nd_mid) {
08917           case '+':
08918           case '-':
08919           case '*':
08920           case '/':
08921           case '%':
08922           case tPOW:
08923           case tUPLUS:
08924           case tUMINUS:
08925           case '|':
08926           case '^':
08927           case '&':
08928           case tCMP:
08929           case '>':
08930           case tGEQ:
08931           case '<':
08932           case tLEQ:
08933           case tEQ:
08934           case tNEQ:
08935             useless = rb_id2name(node->nd_mid);
08936             break;
08937         }
08938         break;
08939 
08940       case NODE_LVAR:
08941       case NODE_DVAR:
08942       case NODE_GVAR:
08943       case NODE_IVAR:
08944       case NODE_CVAR:
08945       case NODE_NTH_REF:
08946       case NODE_BACK_REF:
08947         useless = "a variable";
08948         break;
08949       case NODE_CONST:
08950         useless = "a constant";
08951         break;
08952       case NODE_LIT:
08953       case NODE_STR:
08954       case NODE_DSTR:
08955       case NODE_DREGX:
08956       case NODE_DREGX_ONCE:
08957         useless = "a literal";
08958         break;
08959       case NODE_COLON2:
08960       case NODE_COLON3:
08961         useless = "::";
08962         break;
08963       case NODE_DOT2:
08964         useless = "..";
08965         break;
08966       case NODE_DOT3:
08967         useless = "...";
08968         break;
08969       case NODE_SELF:
08970         useless = "self";
08971         break;
08972       case NODE_NIL:
08973         useless = "nil";
08974         break;
08975       case NODE_TRUE:
08976         useless = "true";
08977         break;
08978       case NODE_FALSE:
08979         useless = "false";
08980         break;
08981       case NODE_DEFINED:
08982         useless = "defined?";
08983         break;
08984     }
08985 
08986     if (useless) {
08987         int line = ruby_sourceline;
08988 
08989         ruby_sourceline = nd_line(node);
08990         rb_warnS("possibly useless use of %s in void context", useless);
08991         ruby_sourceline = line;
08992     }
08993 }
08994 
08995 static void
08996 void_stmts_gen(struct parser_params *parser, NODE *node)
08997 {
08998     if (!RTEST(ruby_verbose)) return;
08999     if (!node) return;
09000     if (nd_type(node) != NODE_BLOCK) return;
09001 
09002     for (;;) {
09003         if (!node->nd_next) return;
09004         void_expr0(node->nd_head);
09005         node = node->nd_next;
09006     }
09007 }
09008 
09009 static NODE *
09010 remove_begin(NODE *node)
09011 {
09012     NODE **n = &node, *n1 = node;
09013     while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
09014         *n = n1 = n1->nd_body;
09015     }
09016     return node;
09017 }
09018 
09019 static void
09020 reduce_nodes_gen(struct parser_params *parser, NODE **body)
09021 {
09022     NODE *node = *body;
09023 
09024     if (!node) {
09025         *body = NEW_NIL();
09026         return;
09027     }
09028 #define subnodes(n1, n2) \
09029     ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
09030      (!node->n2) ? (body = &node->n1, 1) : \
09031      (reduce_nodes(&node->n1), body = &node->n2, 1))
09032 
09033     while (node) {
09034         int newline = (int)(node->flags & NODE_FL_NEWLINE);
09035         switch (nd_type(node)) {
09036           end:
09037           case NODE_NIL:
09038             *body = 0;
09039             return;
09040           case NODE_RETURN:
09041             *body = node = node->nd_stts;
09042             if (newline && node) node->flags |= NODE_FL_NEWLINE;
09043             continue;
09044           case NODE_BEGIN:
09045             *body = node = node->nd_body;
09046             if (newline && node) node->flags |= NODE_FL_NEWLINE;
09047             continue;
09048           case NODE_BLOCK:
09049             body = &node->nd_end->nd_head;
09050             break;
09051           case NODE_IF:
09052             if (subnodes(nd_body, nd_else)) break;
09053             return;
09054           case NODE_CASE:
09055             body = &node->nd_body;
09056             break;
09057           case NODE_WHEN:
09058             if (!subnodes(nd_body, nd_next)) goto end;
09059             break;
09060           case NODE_ENSURE:
09061             if (!subnodes(nd_head, nd_resq)) goto end;
09062             break;
09063           case NODE_RESCUE:
09064             if (node->nd_else) {
09065                 body = &node->nd_resq;
09066                 break;
09067             }
09068             if (!subnodes(nd_head, nd_resq)) goto end;
09069             break;
09070           default:
09071             return;
09072         }
09073         node = *body;
09074         if (newline && node) node->flags |= NODE_FL_NEWLINE;
09075     }
09076 
09077 #undef subnodes
09078 }
09079 
09080 static int
09081 is_static_content(NODE *node)
09082 {
09083     if (!node) return 1;
09084     switch (nd_type(node)) {
09085       case NODE_HASH:
09086         if (!(node = node->nd_head)) break;
09087       case NODE_ARRAY:
09088         do {
09089             if (!is_static_content(node->nd_head)) return 0;
09090         } while ((node = node->nd_next) != 0);
09091       case NODE_LIT:
09092       case NODE_STR:
09093       case NODE_NIL:
09094       case NODE_TRUE:
09095       case NODE_FALSE:
09096       case NODE_ZARRAY:
09097         break;
09098       default:
09099         return 0;
09100     }
09101     return 1;
09102 }
09103 
09104 static int
09105 assign_in_cond(struct parser_params *parser, NODE *node)
09106 {
09107     switch (nd_type(node)) {
09108       case NODE_MASGN:
09109         yyerror("multiple assignment in conditional");
09110         return 1;
09111 
09112       case NODE_LASGN:
09113       case NODE_DASGN:
09114       case NODE_DASGN_CURR:
09115       case NODE_GASGN:
09116       case NODE_IASGN:
09117         break;
09118 
09119       default:
09120         return 0;
09121     }
09122 
09123     if (!node->nd_value) return 1;
09124     if (is_static_content(node->nd_value)) {
09125         /* reports always */
09126         parser_warn(node->nd_value, "found = in conditional, should be ==");
09127     }
09128     return 1;
09129 }
09130 
09131 static void
09132 warn_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
09133 {
09134     if (!e_option_supplied(parser)) parser_warn(node, str);
09135 }
09136 
09137 static void
09138 warning_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
09139 {
09140     if (!e_option_supplied(parser)) parser_warning(node, str);
09141 }
09142 
09143 static void
09144 fixup_nodes(NODE **rootnode)
09145 {
09146     NODE *node, *next, *head;
09147 
09148     for (node = *rootnode; node; node = next) {
09149         enum node_type type;
09150         VALUE val;
09151 
09152         next = node->nd_next;
09153         head = node->nd_head;
09154         rb_gc_force_recycle((VALUE)node);
09155         *rootnode = next;
09156         switch (type = nd_type(head)) {
09157           case NODE_DOT2:
09158           case NODE_DOT3:
09159             val = rb_range_new(head->nd_beg->nd_lit, head->nd_end->nd_lit,
09160                                type == NODE_DOT3);
09161             rb_gc_force_recycle((VALUE)head->nd_beg);
09162             rb_gc_force_recycle((VALUE)head->nd_end);
09163             nd_set_type(head, NODE_LIT);
09164             head->nd_lit = val;
09165             break;
09166           default:
09167             break;
09168         }
09169     }
09170 }
09171 
09172 static NODE *cond0(struct parser_params*,NODE*);
09173 
09174 static NODE*
09175 range_op(struct parser_params *parser, NODE *node)
09176 {
09177     enum node_type type;
09178 
09179     if (node == 0) return 0;
09180 
09181     type = nd_type(node);
09182     value_expr(node);
09183     if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
09184         warn_unless_e_option(parser, node, "integer literal in conditional range");
09185         return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."))));
09186     }
09187     return cond0(parser, node);
09188 }
09189 
09190 static int
09191 literal_node(NODE *node)
09192 {
09193     if (!node) return 1;        /* same as NODE_NIL */
09194     switch (nd_type(node)) {
09195       case NODE_LIT:
09196       case NODE_STR:
09197       case NODE_DSTR:
09198       case NODE_EVSTR:
09199       case NODE_DREGX:
09200       case NODE_DREGX_ONCE:
09201       case NODE_DSYM:
09202         return 2;
09203       case NODE_TRUE:
09204       case NODE_FALSE:
09205       case NODE_NIL:
09206         return 1;
09207     }
09208     return 0;
09209 }
09210 
09211 static NODE*
09212 cond0(struct parser_params *parser, NODE *node)
09213 {
09214     if (node == 0) return 0;
09215     assign_in_cond(parser, node);
09216 
09217     switch (nd_type(node)) {
09218       case NODE_DSTR:
09219       case NODE_EVSTR:
09220       case NODE_STR:
09221         rb_warn0("string literal in condition");
09222         break;
09223 
09224       case NODE_DREGX:
09225       case NODE_DREGX_ONCE:
09226         warning_unless_e_option(parser, node, "regex literal in condition");
09227         return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
09228 
09229       case NODE_AND:
09230       case NODE_OR:
09231         node->nd_1st = cond0(parser, node->nd_1st);
09232         node->nd_2nd = cond0(parser, node->nd_2nd);
09233         break;
09234 
09235       case NODE_DOT2:
09236       case NODE_DOT3:
09237         node->nd_beg = range_op(parser, node->nd_beg);
09238         node->nd_end = range_op(parser, node->nd_end);
09239         if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
09240         else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
09241         if (!e_option_supplied(parser)) {
09242             int b = literal_node(node->nd_beg);
09243             int e = literal_node(node->nd_end);
09244             if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
09245                 parser_warn(node, "range literal in condition");
09246             }
09247         }
09248         break;
09249 
09250       case NODE_DSYM:
09251         parser_warning(node, "literal in condition");
09252         break;
09253 
09254       case NODE_LIT:
09255         if (RB_TYPE_P(node->nd_lit, T_REGEXP)) {
09256             warn_unless_e_option(parser, node, "regex literal in condition");
09257             nd_set_type(node, NODE_MATCH);
09258         }
09259         else {
09260             parser_warning(node, "literal in condition");
09261         }
09262       default:
09263         break;
09264     }
09265     return node;
09266 }
09267 
09268 static NODE*
09269 cond_gen(struct parser_params *parser, NODE *node)
09270 {
09271     if (node == 0) return 0;
09272     return cond0(parser, node);
09273 }
09274 
09275 static NODE*
09276 logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
09277 {
09278     value_expr(left);
09279     if (left && (enum node_type)nd_type(left) == type) {
09280         NODE *node = left, *second;
09281         while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
09282             node = second;
09283         }
09284         node->nd_2nd = NEW_NODE(type, second, right, 0);
09285         return left;
09286     }
09287     return NEW_NODE(type, left, right, 0);
09288 }
09289 
09290 static void
09291 no_blockarg(struct parser_params *parser, NODE *node)
09292 {
09293     if (node && nd_type(node) == NODE_BLOCK_PASS) {
09294         compile_error(PARSER_ARG "block argument should not be given");
09295     }
09296 }
09297 
09298 static NODE *
09299 ret_args_gen(struct parser_params *parser, NODE *node)
09300 {
09301     if (node) {
09302         no_blockarg(parser, node);
09303         if (nd_type(node) == NODE_ARRAY) {
09304             if (node->nd_next == 0) {
09305                 node = node->nd_head;
09306             }
09307             else {
09308                 nd_set_type(node, NODE_VALUES);
09309             }
09310         }
09311     }
09312     return node;
09313 }
09314 
09315 static NODE *
09316 new_yield_gen(struct parser_params *parser, NODE *node)
09317 {
09318     if (node) no_blockarg(parser, node);
09319 
09320     return NEW_YIELD(node);
09321 }
09322 
09323 static NODE*
09324 negate_lit(NODE *node)
09325 {
09326     switch (TYPE(node->nd_lit)) {
09327       case T_FIXNUM:
09328         node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
09329         break;
09330       case T_BIGNUM:
09331         node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
09332         break;
09333       case T_FLOAT:
09334 #if USE_FLONUM
09335         if (FLONUM_P(node->nd_lit)) {
09336             node->nd_lit = DBL2NUM(-RFLOAT_VALUE(node->nd_lit));
09337         }
09338         else {
09339             RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
09340         }
09341 #else
09342         RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
09343 #endif
09344         break;
09345       default:
09346         break;
09347     }
09348     return node;
09349 }
09350 
09351 static NODE *
09352 arg_blk_pass(NODE *node1, NODE *node2)
09353 {
09354     if (node2) {
09355         node2->nd_head = node1;
09356         return node2;
09357     }
09358     return node1;
09359 }
09360 
09361 
09362 static NODE*
09363 new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, NODE *tail)
09364 {
09365     int saved_line = ruby_sourceline;
09366     struct rb_args_info *args = tail->nd_ainfo;
09367 
09368     args->pre_args_num   = m ? rb_long2int(m->nd_plen) : 0;
09369     args->pre_init       = m ? m->nd_next : 0;
09370 
09371     args->post_args_num  = p ? rb_long2int(p->nd_plen) : 0;
09372     args->post_init      = p ? p->nd_next : 0;
09373     args->first_post_arg = p ? p->nd_pid : 0;
09374 
09375     args->rest_arg       = r;
09376 
09377     args->opt_args       = o;
09378 
09379     ruby_sourceline = saved_line;
09380 
09381     return tail;
09382 }
09383 
09384 static NODE*
09385 new_args_tail_gen(struct parser_params *parser, NODE *k, ID kr, ID b)
09386 {
09387     int saved_line = ruby_sourceline;
09388     struct rb_args_info *args;
09389     NODE *kw_rest_arg = 0;
09390     NODE *node;
09391 
09392     args = ALLOC(struct rb_args_info);
09393     MEMZERO(args, struct rb_args_info, 1);
09394     node = NEW_NODE(NODE_ARGS, 0, 0, args);
09395 
09396     args->block_arg      = b;
09397     args->kw_args        = k;
09398     if (k && !kr) kr = internal_id();
09399     if (kr) {
09400         arg_var(kr);
09401         kw_rest_arg  = NEW_DVAR(kr);
09402     }
09403     args->kw_rest_arg    = kw_rest_arg;
09404 
09405     ruby_sourceline = saved_line;
09406     return node;
09407 }
09408 
09409 static NODE*
09410 dsym_node_gen(struct parser_params *parser, NODE *node)
09411 {
09412     VALUE lit;
09413 
09414     if (!node) {
09415         return NEW_LIT(ID2SYM(idNULL));
09416     }
09417 
09418     switch (nd_type(node)) {
09419       case NODE_DSTR:
09420         nd_set_type(node, NODE_DSYM);
09421         break;
09422       case NODE_STR:
09423         lit = node->nd_lit;
09424         node->nd_lit = ID2SYM(rb_intern_str(lit));
09425         nd_set_type(node, NODE_LIT);
09426         break;
09427       default:
09428         node = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST(node));
09429         break;
09430     }
09431     return node;
09432 }
09433 #endif /* !RIPPER */
09434 
09435 #ifndef RIPPER
09436 static NODE *
09437 new_op_assign_gen(struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
09438 {
09439     NODE *asgn;
09440 
09441     if (lhs) {
09442         ID vid = lhs->nd_vid;
09443         if (op == tOROP) {
09444             lhs->nd_value = rhs;
09445             asgn = NEW_OP_ASGN_OR(gettable(vid), lhs);
09446             if (is_asgn_or_id(vid)) {
09447                 asgn->nd_aid = vid;
09448             }
09449         }
09450         else if (op == tANDOP) {
09451             lhs->nd_value = rhs;
09452             asgn = NEW_OP_ASGN_AND(gettable(vid), lhs);
09453         }
09454         else {
09455             asgn = lhs;
09456             asgn->nd_value = NEW_CALL(gettable(vid), op, NEW_LIST(rhs));
09457         }
09458     }
09459     else {
09460         asgn = NEW_BEGIN(0);
09461     }
09462     return asgn;
09463 }
09464 
09465 static NODE *
09466 new_attr_op_assign_gen(struct parser_params *parser, NODE *lhs, ID attr, ID op, NODE *rhs)
09467 {
09468     NODE *asgn;
09469 
09470     if (op == tOROP) {
09471         op = 0;
09472     }
09473     else if (op == tANDOP) {
09474         op = 1;
09475     }
09476     asgn = NEW_OP_ASGN2(lhs, attr, op, rhs);
09477     fixpos(asgn, lhs);
09478     return asgn;
09479 }
09480 
09481 static NODE *
09482 new_const_op_assign_gen(struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
09483 {
09484     NODE *asgn;
09485 
09486     if (op == tOROP) {
09487         op = 0;
09488     }
09489     else if (op == tANDOP) {
09490         op = 1;
09491     }
09492     if (lhs) {
09493         asgn = NEW_OP_CDECL(lhs, op, rhs);
09494     }
09495     else {
09496         asgn = NEW_BEGIN(0);
09497     }
09498     fixpos(asgn, lhs);
09499     return asgn;
09500 }
09501 #else
09502 static VALUE
09503 new_op_assign_gen(struct parser_params *parser, VALUE lhs, VALUE op, VALUE rhs)
09504 {
09505     return dispatch3(opassign, lhs, op, rhs);
09506 }
09507 
09508 static VALUE
09509 new_attr_op_assign_gen(struct parser_params *parser, VALUE lhs, VALUE type, VALUE attr, VALUE op, VALUE rhs)
09510 {
09511     VALUE recv = dispatch3(field, lhs, type, attr);
09512     return dispatch3(opassign, recv, op, rhs);
09513 }
09514 #endif
09515 
09516 static void
09517 warn_unused_var(struct parser_params *parser, struct local_vars *local)
09518 {
09519     int i, cnt;
09520     ID *v, *u;
09521 
09522     if (!local->used) return;
09523     v = local->vars->tbl;
09524     u = local->used->tbl;
09525     cnt = local->used->pos;
09526     if (cnt != local->vars->pos) {
09527         rb_bug("local->used->pos != local->vars->pos");
09528     }
09529     for (i = 0; i < cnt; ++i) {
09530         if (!v[i] || (u[i] & LVAR_USED)) continue;
09531         if (is_private_local_id(v[i])) continue;
09532         rb_warn4S(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));
09533     }
09534 }
09535 
09536 static void
09537 local_push_gen(struct parser_params *parser, int inherit_dvars)
09538 {
09539     struct local_vars *local;
09540 
09541     local = ALLOC(struct local_vars);
09542     local->prev = lvtbl;
09543     local->args = vtable_alloc(0);
09544     local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
09545     local->used = !(inherit_dvars &&
09546                     (ifndef_ripper(compile_for_eval || e_option_supplied(parser))+0)) &&
09547         RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
09548     local->cmdargs = cmdarg_stack;
09549     cmdarg_stack = 0;
09550     lvtbl = local;
09551 }
09552 
09553 static void
09554 local_pop_gen(struct parser_params *parser)
09555 {
09556     struct local_vars *local = lvtbl->prev;
09557     if (lvtbl->used) {
09558         warn_unused_var(parser, lvtbl);
09559         vtable_free(lvtbl->used);
09560     }
09561     vtable_free(lvtbl->args);
09562     vtable_free(lvtbl->vars);
09563     cmdarg_stack = lvtbl->cmdargs;
09564     xfree(lvtbl);
09565     lvtbl = local;
09566 }
09567 
09568 #ifndef RIPPER
09569 static ID*
09570 local_tbl_gen(struct parser_params *parser)
09571 {
09572     int cnt_args = vtable_size(lvtbl->args);
09573     int cnt_vars = vtable_size(lvtbl->vars);
09574     int cnt = cnt_args + cnt_vars;
09575     int i, j;
09576     ID *buf;
09577 
09578     if (cnt <= 0) return 0;
09579     buf = ALLOC_N(ID, cnt + 1);
09580     MEMCPY(buf+1, lvtbl->args->tbl, ID, cnt_args);
09581     /* remove IDs duplicated to warn shadowing */
09582     for (i = 0, j = cnt_args+1; i < cnt_vars; ++i) {
09583         ID id = lvtbl->vars->tbl[i];
09584         if (!vtable_included(lvtbl->args, id)) {
09585             buf[j++] = id;
09586         }
09587     }
09588     if (--j < cnt) REALLOC_N(buf, ID, (cnt = j) + 1);
09589     buf[0] = cnt;
09590     return buf;
09591 }
09592 #endif
09593 
09594 static int
09595 arg_var_gen(struct parser_params *parser, ID id)
09596 {
09597     vtable_add(lvtbl->args, id);
09598     return vtable_size(lvtbl->args) - 1;
09599 }
09600 
09601 static int
09602 local_var_gen(struct parser_params *parser, ID id)
09603 {
09604     vtable_add(lvtbl->vars, id);
09605     if (lvtbl->used) {
09606         vtable_add(lvtbl->used, (ID)ruby_sourceline);
09607     }
09608     return vtable_size(lvtbl->vars) - 1;
09609 }
09610 
09611 static int
09612 local_id_gen(struct parser_params *parser, ID id)
09613 {
09614     struct vtable *vars, *args, *used;
09615 
09616     vars = lvtbl->vars;
09617     args = lvtbl->args;
09618     used = lvtbl->used;
09619 
09620     while (vars && POINTER_P(vars->prev)) {
09621         vars = vars->prev;
09622         args = args->prev;
09623         if (used) used = used->prev;
09624     }
09625 
09626     if (vars && vars->prev == DVARS_INHERIT) {
09627         return rb_local_defined(id);
09628     }
09629     else if (vtable_included(args, id)) {
09630         return 1;
09631     }
09632     else {
09633         int i = vtable_included(vars, id);
09634         if (i && used) used->tbl[i-1] |= LVAR_USED;
09635         return i != 0;
09636     }
09637 }
09638 
09639 static const struct vtable *
09640 dyna_push_gen(struct parser_params *parser)
09641 {
09642     lvtbl->args = vtable_alloc(lvtbl->args);
09643     lvtbl->vars = vtable_alloc(lvtbl->vars);
09644     if (lvtbl->used) {
09645         lvtbl->used = vtable_alloc(lvtbl->used);
09646     }
09647     return lvtbl->args;
09648 }
09649 
09650 static void
09651 dyna_pop_1(struct parser_params *parser)
09652 {
09653     struct vtable *tmp;
09654 
09655     if ((tmp = lvtbl->used) != 0) {
09656         warn_unused_var(parser, lvtbl);
09657         lvtbl->used = lvtbl->used->prev;
09658         vtable_free(tmp);
09659     }
09660     tmp = lvtbl->args;
09661     lvtbl->args = lvtbl->args->prev;
09662     vtable_free(tmp);
09663     tmp = lvtbl->vars;
09664     lvtbl->vars = lvtbl->vars->prev;
09665     vtable_free(tmp);
09666 }
09667 
09668 static void
09669 dyna_pop_gen(struct parser_params *parser, const struct vtable *lvargs)
09670 {
09671     while (lvtbl->args != lvargs) {
09672         dyna_pop_1(parser);
09673         if (!lvtbl->args) {
09674             struct local_vars *local = lvtbl->prev;
09675             xfree(lvtbl);
09676             lvtbl = local;
09677         }
09678     }
09679     dyna_pop_1(parser);
09680 }
09681 
09682 static int
09683 dyna_in_block_gen(struct parser_params *parser)
09684 {
09685     return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE;
09686 }
09687 
09688 static int
09689 dvar_defined_gen(struct parser_params *parser, ID id, int get)
09690 {
09691     struct vtable *vars, *args, *used;
09692     int i;
09693 
09694     args = lvtbl->args;
09695     vars = lvtbl->vars;
09696     used = lvtbl->used;
09697 
09698     while (POINTER_P(vars)) {
09699         if (vtable_included(args, id)) {
09700             return 1;
09701         }
09702         if ((i = vtable_included(vars, id)) != 0) {
09703             if (used) used->tbl[i-1] |= LVAR_USED;
09704             return 1;
09705         }
09706         args = args->prev;
09707         vars = vars->prev;
09708         if (get) used = 0;
09709         if (used) used = used->prev;
09710     }
09711 
09712     if (vars == DVARS_INHERIT) {
09713         return rb_dvar_defined(id);
09714     }
09715 
09716     return 0;
09717 }
09718 
09719 static int
09720 dvar_curr_gen(struct parser_params *parser, ID id)
09721 {
09722     return (vtable_included(lvtbl->args, id) ||
09723             vtable_included(lvtbl->vars, id));
09724 }
09725 
09726 #ifndef RIPPER
09727 static void
09728 reg_fragment_setenc_gen(struct parser_params* parser, VALUE str, int options)
09729 {
09730     int c = RE_OPTION_ENCODING_IDX(options);
09731 
09732     if (c) {
09733         int opt, idx;
09734         rb_char_to_option_kcode(c, &opt, &idx);
09735         if (idx != ENCODING_GET(str) &&
09736             rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09737             goto error;
09738         }
09739         ENCODING_SET(str, idx);
09740     }
09741     else if (RE_OPTION_ENCODING_NONE(options)) {
09742         if (!ENCODING_IS_ASCII8BIT(str) &&
09743             rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09744             c = 'n';
09745             goto error;
09746         }
09747         rb_enc_associate(str, rb_ascii8bit_encoding());
09748     }
09749     else if (current_enc == rb_usascii_encoding()) {
09750         if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09751             /* raise in re.c */
09752             rb_enc_associate(str, rb_usascii_encoding());
09753         }
09754         else {
09755             rb_enc_associate(str, rb_ascii8bit_encoding());
09756         }
09757     }
09758     return;
09759 
09760   error:
09761     compile_error(PARSER_ARG
09762         "regexp encoding option '%c' differs from source encoding '%s'",
09763         c, rb_enc_name(rb_enc_get(str)));
09764 }
09765 
09766 static int
09767 reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
09768 {
09769     VALUE err;
09770     reg_fragment_setenc(str, options);
09771     err = rb_reg_check_preprocess(str);
09772     if (err != Qnil) {
09773         err = rb_obj_as_string(err);
09774         compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
09775         RB_GC_GUARD(err);
09776         return 0;
09777     }
09778     return 1;
09779 }
09780 
09781 typedef struct {
09782     struct parser_params* parser;
09783     rb_encoding *enc;
09784     NODE *succ_block;
09785     NODE *fail_block;
09786     int num;
09787 } reg_named_capture_assign_t;
09788 
09789 static int
09790 reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
09791           int back_num, int *back_refs, OnigRegex regex, void *arg0)
09792 {
09793     reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
09794     struct parser_params* parser = arg->parser;
09795     rb_encoding *enc = arg->enc;
09796     long len = name_end - name;
09797     const char *s = (const char *)name;
09798     ID var;
09799 
09800     arg->num++;
09801 
09802     if (arg->succ_block == 0) {
09803         arg->succ_block = NEW_BEGIN(0);
09804         arg->fail_block = NEW_BEGIN(0);
09805     }
09806 
09807     if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
09808         (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) ||
09809         !rb_enc_symname2_p(s, len, enc)) {
09810         return ST_CONTINUE;
09811     }
09812     var = rb_intern3(s, len, enc);
09813     if (dvar_defined(var) || local_id(var)) {
09814         rb_warningS("named capture conflicts a local variable - %s",
09815                     rb_id2name(var));
09816     }
09817     arg->succ_block = block_append(arg->succ_block,
09818         newline_node(node_assign(assignable(var,0),
09819             NEW_CALL(
09820               gettable(rb_intern("$~")),
09821               idAREF,
09822               NEW_LIST(NEW_LIT(ID2SYM(var))))
09823             )));
09824     arg->fail_block = block_append(arg->fail_block,
09825         newline_node(node_assign(assignable(var,0), NEW_LIT(Qnil))));
09826     return ST_CONTINUE;
09827 }
09828 
09829 static NODE *
09830 reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match)
09831 {
09832     reg_named_capture_assign_t arg;
09833 
09834     arg.parser = parser;
09835     arg.enc = rb_enc_get(regexp);
09836     arg.succ_block = 0;
09837     arg.fail_block = 0;
09838     arg.num = 0;
09839     onig_foreach_name(RREGEXP(regexp)->ptr, reg_named_capture_assign_iter, (void*)&arg);
09840 
09841     if (arg.num == 0)
09842         return match;
09843 
09844     return
09845         block_append(
09846             newline_node(match),
09847             NEW_IF(gettable(rb_intern("$~")),
09848                 block_append(
09849                     newline_node(arg.succ_block),
09850                     newline_node(
09851                         NEW_CALL(
09852                           gettable(rb_intern("$~")),
09853                           rb_intern("begin"),
09854                           NEW_LIST(NEW_LIT(INT2FIX(0)))))),
09855                 block_append(
09856                     newline_node(arg.fail_block),
09857                     newline_node(
09858                         NEW_LIT(Qnil)))));
09859 }
09860 
09861 static VALUE
09862 reg_compile_gen(struct parser_params* parser, VALUE str, int options)
09863 {
09864     VALUE re;
09865     VALUE err;
09866 
09867     reg_fragment_setenc(str, options);
09868     err = rb_errinfo();
09869     re = rb_reg_compile(str, options & RE_OPTION_MASK, ruby_sourcefile, ruby_sourceline);
09870     if (NIL_P(re)) {
09871         ID mesg = rb_intern("mesg");
09872         VALUE m = rb_attr_get(rb_errinfo(), mesg);
09873         rb_set_errinfo(err);
09874         if (!NIL_P(err)) {
09875             rb_str_append(rb_str_cat(rb_attr_get(err, mesg), "\n", 1), m);
09876         }
09877         else {
09878             compile_error(PARSER_ARG "%s", RSTRING_PTR(m));
09879         }
09880         return Qnil;
09881     }
09882     return re;
09883 }
09884 
09885 void
09886 rb_gc_mark_parser(void)
09887 {
09888 }
09889 
09890 NODE*
09891 rb_parser_append_print(VALUE vparser, NODE *node)
09892 {
09893     NODE *prelude = 0;
09894     NODE *scope = node;
09895     struct parser_params *parser;
09896 
09897     if (!node) return node;
09898 
09899     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09900 
09901     node = node->nd_body;
09902 
09903     if (nd_type(node) == NODE_PRELUDE) {
09904         prelude = node;
09905         node = node->nd_body;
09906     }
09907 
09908     node = block_append(node,
09909                         NEW_FCALL(rb_intern("print"),
09910                                   NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
09911     if (prelude) {
09912         prelude->nd_body = node;
09913         scope->nd_body = prelude;
09914     }
09915     else {
09916         scope->nd_body = node;
09917     }
09918 
09919     return scope;
09920 }
09921 
09922 NODE *
09923 rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split)
09924 {
09925     NODE *prelude = 0;
09926     NODE *scope = node;
09927     struct parser_params *parser;
09928 
09929     if (!node) return node;
09930 
09931     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09932 
09933     node = node->nd_body;
09934 
09935     if (nd_type(node) == NODE_PRELUDE) {
09936         prelude = node;
09937         node = node->nd_body;
09938     }
09939     if (split) {
09940         node = block_append(NEW_GASGN(rb_intern("$F"),
09941                                       NEW_CALL(NEW_GVAR(rb_intern("$_")),
09942                                                rb_intern("split"), 0)),
09943                             node);
09944     }
09945     if (chop) {
09946         node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
09947                                      rb_intern("chop!"), 0), node);
09948     }
09949 
09950     node = NEW_OPT_N(node);
09951 
09952     if (prelude) {
09953         prelude->nd_body = node;
09954         scope->nd_body = prelude;
09955     }
09956     else {
09957         scope->nd_body = node;
09958     }
09959 
09960     return scope;
09961 }
09962 
09963 static const struct {
09964     ID token;
09965     const char *name;
09966 } op_tbl[] = {
09967     {tDOT2,     ".."},
09968     {tDOT3,     "..."},
09969     {tPOW,      "**"},
09970     {tDSTAR,    "**"},
09971     {tUPLUS,    "+@"},
09972     {tUMINUS,   "-@"},
09973     {tCMP,      "<=>"},
09974     {tGEQ,      ">="},
09975     {tLEQ,      "<="},
09976     {tEQ,       "=="},
09977     {tEQQ,      "==="},
09978     {tNEQ,      "!="},
09979     {tMATCH,    "=~"},
09980     {tNMATCH,   "!~"},
09981     {tAREF,     "[]"},
09982     {tASET,     "[]="},
09983     {tLSHFT,    "<<"},
09984     {tRSHFT,    ">>"},
09985     {tCOLON2,   "::"},
09986 };
09987 
09988 #define op_tbl_count numberof(op_tbl)
09989 
09990 #ifndef ENABLE_SELECTOR_NAMESPACE
09991 #define ENABLE_SELECTOR_NAMESPACE 0
09992 #endif
09993 
09994 static struct symbols {
09995     ID last_id;
09996     st_table *sym_id;
09997     st_table *id_str;
09998 #if ENABLE_SELECTOR_NAMESPACE
09999     st_table *ivar2_id;
10000     st_table *id_ivar2;
10001 #endif
10002     VALUE op_sym[tLAST_OP_ID];
10003 } global_symbols = {tLAST_TOKEN};
10004 
10005 static const struct st_hash_type symhash = {
10006     rb_str_hash_cmp,
10007     rb_str_hash,
10008 };
10009 
10010 #if ENABLE_SELECTOR_NAMESPACE
10011 struct ivar2_key {
10012     ID id;
10013     VALUE klass;
10014 };
10015 
10016 static int
10017 ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
10018 {
10019     if (key1->id == key2->id && key1->klass == key2->klass) {
10020         return 0;
10021     }
10022     return 1;
10023 }
10024 
10025 static int
10026 ivar2_hash(struct ivar2_key *key)
10027 {
10028     return (key->id << 8) ^ (key->klass >> 2);
10029 }
10030 
10031 static const struct st_hash_type ivar2_hash_type = {
10032     ivar2_cmp,
10033     ivar2_hash,
10034 };
10035 #endif
10036 
10037 void
10038 Init_sym(void)
10039 {
10040     global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
10041     global_symbols.id_str = st_init_numtable_with_size(1000);
10042 #if ENABLE_SELECTOR_NAMESPACE
10043     global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000);
10044     global_symbols.id_ivar2 = st_init_numtable_with_size(1000);
10045 #endif
10046 
10047     (void)nodetype;
10048     (void)nodeline;
10049 #if PARSER_DEBUG
10050     (void)lex_state_name(-1);
10051 #endif
10052 
10053     Init_id();
10054 }
10055 
10056 void
10057 rb_gc_mark_symbols(void)
10058 {
10059     rb_mark_tbl(global_symbols.id_str);
10060     rb_gc_mark_locations(global_symbols.op_sym,
10061                          global_symbols.op_sym + numberof(global_symbols.op_sym));
10062 }
10063 #endif /* !RIPPER */
10064 
10065 static ID
10066 internal_id_gen(struct parser_params *parser)
10067 {
10068     ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars);
10069     id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
10070     return ID_INTERNAL | (id << ID_SCOPE_SHIFT);
10071 }
10072 
10073 #ifndef RIPPER
10074 static int
10075 is_special_global_name(const char *m, const char *e, rb_encoding *enc)
10076 {
10077     int mb = 0;
10078 
10079     if (m >= e) return 0;
10080     if (is_global_name_punct(*m)) {
10081         ++m;
10082     }
10083     else if (*m == '-') {
10084         ++m;
10085         if (m < e && is_identchar(m, e, enc)) {
10086             if (!ISASCII(*m)) mb = 1;
10087             m += rb_enc_mbclen(m, e, enc);
10088         }
10089     }
10090     else {
10091         if (!rb_enc_isdigit(*m, enc)) return 0;
10092         do {
10093             if (!ISASCII(*m)) mb = 1;
10094             ++m;
10095         } while (m < e && rb_enc_isdigit(*m, enc));
10096     }
10097     return m == e ? mb + 1 : 0;
10098 }
10099 
10100 int
10101 rb_symname_p(const char *name)
10102 {
10103     return rb_enc_symname_p(name, rb_ascii8bit_encoding());
10104 }
10105 
10106 int
10107 rb_enc_symname_p(const char *name, rb_encoding *enc)
10108 {
10109     return rb_enc_symname2_p(name, strlen(name), enc);
10110 }
10111 
10112 #define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
10113 #define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
10114 
10115 static int
10116 rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_atttset)
10117 {
10118     const char *m = name;
10119     const char *e = m + len;
10120     int type = ID_JUNK;
10121 
10122     if (!m || len <= 0) return -1;
10123     switch (*m) {
10124       case '\0':
10125         return -1;
10126 
10127       case '$':
10128         type = ID_GLOBAL;
10129         if (is_special_global_name(++m, e, enc)) return type;
10130         goto id;
10131 
10132       case '@':
10133         type = ID_INSTANCE;
10134         if (*++m == '@') {
10135             ++m;
10136             type = ID_CLASS;
10137         }
10138         goto id;
10139 
10140       case '<':
10141         switch (*++m) {
10142           case '<': ++m; break;
10143           case '=': if (*++m == '>') ++m; break;
10144           default: break;
10145         }
10146         break;
10147 
10148       case '>':
10149         switch (*++m) {
10150           case '>': case '=': ++m; break;
10151         }
10152         break;
10153 
10154       case '=':
10155         switch (*++m) {
10156           case '~': ++m; break;
10157           case '=': if (*++m == '=') ++m; break;
10158           default: return -1;
10159         }
10160         break;
10161 
10162       case '*':
10163         if (*++m == '*') ++m;
10164         break;
10165 
10166       case '+': case '-':
10167         if (*++m == '@') ++m;
10168         break;
10169 
10170       case '|': case '^': case '&': case '/': case '%': case '~': case '`':
10171         ++m;
10172         break;
10173 
10174       case '[':
10175         if (*++m != ']') return -1;
10176         if (*++m == '=') ++m;
10177         break;
10178 
10179       case '!':
10180         if (len == 1) return ID_JUNK;
10181         switch (*++m) {
10182           case '=': case '~': ++m; break;
10183           default: return -1;
10184         }
10185         break;
10186 
10187       default:
10188         type = rb_enc_isupper(*m, enc) ? ID_CONST : ID_LOCAL;
10189       id:
10190         if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
10191             return -1;
10192         while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
10193         if (m >= e) break;
10194         switch (*m) {
10195           case '!': case '?':
10196             if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
10197             type = ID_JUNK;
10198             ++m;
10199             if (m + 1 < e || *m != '=') break;
10200             /* fall through */
10201           case '=':
10202             if (!(allowed_atttset & (1U << type))) return -1;
10203             type = ID_ATTRSET;
10204             ++m;
10205             break;
10206         }
10207         break;
10208     }
10209     return m == e ? type : -1;
10210 }
10211 
10212 int
10213 rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
10214 {
10215     return rb_enc_symname_type(name, len, enc, IDSET_ATTRSET_FOR_SYNTAX) != -1;
10216 }
10217 
10218 static int
10219 rb_str_symname_type(VALUE name, unsigned int allowed_atttset)
10220 {
10221     const char *ptr = StringValuePtr(name);
10222     long len = RSTRING_LEN(name);
10223     int type = rb_enc_symname_type(ptr, len, rb_enc_get(name), allowed_atttset);
10224     RB_GC_GUARD(name);
10225     return type;
10226 }
10227 
10228 static ID
10229 register_symid(ID id, const char *name, long len, rb_encoding *enc)
10230 {
10231     VALUE str = rb_enc_str_new(name, len, enc);
10232     return register_symid_str(id, str);
10233 }
10234 
10235 static ID
10236 register_symid_str(ID id, VALUE str)
10237 {
10238     OBJ_FREEZE(str);
10239     st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
10240     st_add_direct(global_symbols.id_str, id, (st_data_t)str);
10241     return id;
10242 }
10243 
10244 static int
10245 sym_check_asciionly(VALUE str)
10246 {
10247     if (!rb_enc_asciicompat(rb_enc_get(str))) return FALSE;
10248     switch (rb_enc_str_coderange(str)) {
10249       case ENC_CODERANGE_BROKEN:
10250         rb_raise(rb_eEncodingError, "invalid encoding symbol");
10251       case ENC_CODERANGE_7BIT:
10252         return TRUE;
10253     }
10254     return FALSE;
10255 }
10256 
10257 /*
10258  * _str_ itself will be registered at the global symbol table.  _str_
10259  * can be modified before the registration, since the encoding will be
10260  * set to ASCII-8BIT if it is a special global name.
10261  */
10262 static ID intern_str(VALUE str);
10263 
10264 ID
10265 rb_intern3(const char *name, long len, rb_encoding *enc)
10266 {
10267     VALUE str;
10268     st_data_t data;
10269     struct RString fake_str;
10270     fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
10271     fake_str.basic.klass = rb_cString;
10272     fake_str.as.heap.len = len;
10273     fake_str.as.heap.ptr = (char *)name;
10274     fake_str.as.heap.aux.capa = len;
10275     str = (VALUE)&fake_str;
10276     rb_enc_associate(str, enc);
10277     OBJ_FREEZE(str);
10278 
10279     if (st_lookup(global_symbols.sym_id, str, &data))
10280         return (ID)data;
10281 
10282     str = rb_enc_str_new(name, len, enc); /* make true string */
10283     return intern_str(str);
10284 }
10285 
10286 static ID
10287 intern_str(VALUE str)
10288 {
10289     const char *name, *m, *e;
10290     long len, last;
10291     rb_encoding *enc, *symenc;
10292     unsigned char c;
10293     ID id;
10294     int mb;
10295 
10296     RSTRING_GETMEM(str, name, len);
10297     m = name;
10298     e = m + len;
10299     enc = rb_enc_get(str);
10300     symenc = enc;
10301 
10302     if (!len || (rb_cString && !rb_enc_asciicompat(enc))) {
10303       junk:
10304         id = ID_JUNK;
10305         goto new_id;
10306     }
10307     last = len-1;
10308     id = 0;
10309     switch (*m) {
10310       case '$':
10311         if (len < 2) goto junk;
10312         id |= ID_GLOBAL;
10313         if ((mb = is_special_global_name(++m, e, enc)) != 0) {
10314             if (!--mb) symenc = rb_usascii_encoding();
10315             goto new_id;
10316         }
10317         break;
10318       case '@':
10319         if (m[1] == '@') {
10320             if (len < 3) goto junk;
10321             m++;
10322             id |= ID_CLASS;
10323         }
10324         else {
10325             if (len < 2) goto junk;
10326             id |= ID_INSTANCE;
10327         }
10328         m++;
10329         break;
10330       default:
10331         c = m[0];
10332         if (c != '_' && rb_enc_isascii(c, enc) && rb_enc_ispunct(c, enc)) {
10333             /* operators */
10334             int i;
10335 
10336             if (len == 1) {
10337                 id = c;
10338                 goto id_register;
10339             }
10340             for (i = 0; i < op_tbl_count; i++) {
10341                 if (*op_tbl[i].name == *m &&
10342                     strcmp(op_tbl[i].name, m) == 0) {
10343                     id = op_tbl[i].token;
10344                     goto id_register;
10345                 }
10346             }
10347         }
10348         break;
10349     }
10350     if (name[last] == '=') {
10351         /* attribute assignment */
10352         if (last > 1 && name[last-1] == '=')
10353             goto junk;
10354         id = rb_intern3(name, last, enc);
10355         if (id > tLAST_OP_ID && !is_attrset_id(id)) {
10356             enc = rb_enc_get(rb_id2str(id));
10357             id = rb_id_attrset(id);
10358             goto id_register;
10359         }
10360         id = ID_ATTRSET;
10361     }
10362     else if (id == 0) {
10363         if (rb_enc_isupper(m[0], enc)) {
10364             id = ID_CONST;
10365         }
10366         else {
10367             id = ID_LOCAL;
10368         }
10369     }
10370     if (!rb_enc_isdigit(*m, enc)) {
10371         while (m <= name + last && is_identchar(m, e, enc)) {
10372             if (ISASCII(*m)) {
10373                 m++;
10374             }
10375             else {
10376                 m += rb_enc_mbclen(m, e, enc);
10377             }
10378         }
10379     }
10380     if (id != ID_ATTRSET && m - name < len) id = ID_JUNK;
10381     if (sym_check_asciionly(str)) symenc = rb_usascii_encoding();
10382   new_id:
10383     if (symenc != enc) rb_enc_associate(str, symenc);
10384     if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
10385         if (len > 20) {
10386             rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.20s...)",
10387                      name);
10388         }
10389         else {
10390             rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.*s)",
10391                      (int)len, name);
10392         }
10393     }
10394     id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
10395   id_register:
10396     return register_symid_str(id, str);
10397 }
10398 
10399 ID
10400 rb_intern2(const char *name, long len)
10401 {
10402     return rb_intern3(name, len, rb_usascii_encoding());
10403 }
10404 
10405 #undef rb_intern
10406 ID
10407 rb_intern(const char *name)
10408 {
10409     return rb_intern2(name, strlen(name));
10410 }
10411 
10412 ID
10413 rb_intern_str(VALUE str)
10414 {
10415     st_data_t id;
10416 
10417     if (st_lookup(global_symbols.sym_id, str, &id))
10418         return (ID)id;
10419     return intern_str(rb_str_dup(str));
10420 }
10421 
10422 VALUE
10423 rb_id2str(ID id)
10424 {
10425     st_data_t data;
10426 
10427     if (id < tLAST_TOKEN) {
10428         int i = 0;
10429 
10430         if (id < INT_MAX && rb_ispunct((int)id)) {
10431             VALUE str = global_symbols.op_sym[i = (int)id];
10432             if (!str) {
10433                 char name[2];
10434                 name[0] = (char)id;
10435                 name[1] = 0;
10436                 str = rb_usascii_str_new(name, 1);
10437                 OBJ_FREEZE(str);
10438                 global_symbols.op_sym[i] = str;
10439             }
10440             return str;
10441         }
10442         for (i = 0; i < op_tbl_count; i++) {
10443             if (op_tbl[i].token == id) {
10444                 VALUE str = global_symbols.op_sym[i];
10445                 if (!str) {
10446                     str = rb_usascii_str_new2(op_tbl[i].name);
10447                     OBJ_FREEZE(str);
10448                     global_symbols.op_sym[i] = str;
10449                 }
10450                 return str;
10451             }
10452         }
10453     }
10454 
10455     if (st_lookup(global_symbols.id_str, id, &data)) {
10456         VALUE str = (VALUE)data;
10457         if (RBASIC(str)->klass == 0)
10458             RBASIC(str)->klass = rb_cString;
10459         return str;
10460     }
10461 
10462     if (is_attrset_id(id)) {
10463         ID id_stem = (id & ~ID_SCOPE_MASK);
10464         VALUE str;
10465 
10466         do {
10467             if (!!(str = rb_id2str(id_stem | ID_LOCAL))) break;
10468             if (!!(str = rb_id2str(id_stem | ID_CONST))) break;
10469             if (!!(str = rb_id2str(id_stem | ID_INSTANCE))) break;
10470             if (!!(str = rb_id2str(id_stem | ID_GLOBAL))) break;
10471             if (!!(str = rb_id2str(id_stem | ID_CLASS))) break;
10472             if (!!(str = rb_id2str(id_stem | ID_JUNK))) break;
10473             return 0;
10474         } while (0);
10475         str = rb_str_dup(str);
10476         rb_str_cat(str, "=", 1);
10477         register_symid_str(id, str);
10478         if (st_lookup(global_symbols.id_str, id, &data)) {
10479             VALUE str = (VALUE)data;
10480             if (RBASIC(str)->klass == 0)
10481                 RBASIC(str)->klass = rb_cString;
10482             return str;
10483         }
10484     }
10485     return 0;
10486 }
10487 
10488 const char *
10489 rb_id2name(ID id)
10490 {
10491     VALUE str = rb_id2str(id);
10492 
10493     if (!str) return 0;
10494     return RSTRING_PTR(str);
10495 }
10496 
10497 static int
10498 symbols_i(VALUE sym, ID value, VALUE ary)
10499 {
10500     rb_ary_push(ary, ID2SYM(value));
10501     return ST_CONTINUE;
10502 }
10503 
10504 /*
10505  *  call-seq:
10506  *     Symbol.all_symbols    => array
10507  *
10508  *  Returns an array of all the symbols currently in Ruby's symbol
10509  *  table.
10510  *
10511  *     Symbol.all_symbols.size    #=> 903
10512  *     Symbol.all_symbols[1,20]   #=> [:floor, :ARGV, :Binding, :symlink,
10513  *                                     :chown, :EOFError, :$;, :String,
10514  *                                     :LOCK_SH, :"setuid?", :$<,
10515  *                                     :default_proc, :compact, :extend,
10516  *                                     :Tms, :getwd, :$=, :ThreadGroup,
10517  *                                     :wait2, :$>]
10518  */
10519 
10520 VALUE
10521 rb_sym_all_symbols(void)
10522 {
10523     VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
10524 
10525     st_foreach(global_symbols.sym_id, symbols_i, ary);
10526     return ary;
10527 }
10528 
10529 int
10530 rb_is_const_id(ID id)
10531 {
10532     return is_const_id(id);
10533 }
10534 
10535 int
10536 rb_is_class_id(ID id)
10537 {
10538     return is_class_id(id);
10539 }
10540 
10541 int
10542 rb_is_global_id(ID id)
10543 {
10544     return is_global_id(id);
10545 }
10546 
10547 int
10548 rb_is_instance_id(ID id)
10549 {
10550     return is_instance_id(id);
10551 }
10552 
10553 int
10554 rb_is_attrset_id(ID id)
10555 {
10556     return is_attrset_id(id);
10557 }
10558 
10559 int
10560 rb_is_local_id(ID id)
10561 {
10562     return is_local_id(id);
10563 }
10564 
10565 int
10566 rb_is_junk_id(ID id)
10567 {
10568     return is_junk_id(id);
10569 }
10570 
10582 ID
10583 rb_check_id(volatile VALUE *namep)
10584 {
10585     st_data_t id;
10586     VALUE tmp;
10587     VALUE name = *namep;
10588 
10589     if (SYMBOL_P(name)) {
10590         return SYM2ID(name);
10591     }
10592     else if (!RB_TYPE_P(name, T_STRING)) {
10593         tmp = rb_check_string_type(name);
10594         if (NIL_P(tmp)) {
10595             tmp = rb_inspect(name);
10596             rb_raise(rb_eTypeError, "%s is not a symbol",
10597                      RSTRING_PTR(tmp));
10598         }
10599         name = tmp;
10600         *namep = name;
10601     }
10602 
10603     sym_check_asciionly(name);
10604 
10605     if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id))
10606         return (ID)id;
10607 
10608     if (rb_is_attrset_name(name)) {
10609         struct RString fake_str;
10610         const VALUE localname = (VALUE)&fake_str;
10611         /* make local name by chopping '=' */
10612         fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
10613         fake_str.basic.klass = rb_cString;
10614         fake_str.as.heap.len = RSTRING_LEN(name) - 1;
10615         fake_str.as.heap.ptr = RSTRING_PTR(name);
10616         fake_str.as.heap.aux.capa = fake_str.as.heap.len;
10617         rb_enc_copy(localname, name);
10618         OBJ_FREEZE(localname);
10619 
10620         if (st_lookup(global_symbols.sym_id, (st_data_t)localname, &id)) {
10621             return rb_id_attrset((ID)id);
10622         }
10623         RB_GC_GUARD(name);
10624     }
10625 
10626     return (ID)0;
10627 }
10628 
10629 ID
10630 rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
10631 {
10632     st_data_t id;
10633     struct RString fake_str;
10634     const VALUE name = (VALUE)&fake_str;
10635     fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
10636     fake_str.basic.klass = rb_cString;
10637     fake_str.as.heap.len = len;
10638     fake_str.as.heap.ptr = (char *)ptr;
10639     fake_str.as.heap.aux.capa = len;
10640     rb_enc_associate(name, enc);
10641 
10642     sym_check_asciionly(name);
10643 
10644     if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id))
10645         return (ID)id;
10646 
10647     if (rb_is_attrset_name(name)) {
10648         fake_str.as.heap.len = len - 1;
10649         if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) {
10650             return rb_id_attrset((ID)id);
10651         }
10652     }
10653 
10654     return (ID)0;
10655 }
10656 
10657 int
10658 rb_is_const_name(VALUE name)
10659 {
10660     return rb_str_symname_type(name, 0) == ID_CONST;
10661 }
10662 
10663 int
10664 rb_is_class_name(VALUE name)
10665 {
10666     return rb_str_symname_type(name, 0) == ID_CLASS;
10667 }
10668 
10669 int
10670 rb_is_global_name(VALUE name)
10671 {
10672     return rb_str_symname_type(name, 0) == ID_GLOBAL;
10673 }
10674 
10675 int
10676 rb_is_instance_name(VALUE name)
10677 {
10678     return rb_str_symname_type(name, 0) == ID_INSTANCE;
10679 }
10680 
10681 int
10682 rb_is_attrset_name(VALUE name)
10683 {
10684     return rb_str_symname_type(name, IDSET_ATTRSET_FOR_INTERN) == ID_ATTRSET;
10685 }
10686 
10687 int
10688 rb_is_local_name(VALUE name)
10689 {
10690     return rb_str_symname_type(name, 0) == ID_LOCAL;
10691 }
10692 
10693 int
10694 rb_is_method_name(VALUE name)
10695 {
10696     switch (rb_str_symname_type(name, 0)) {
10697       case ID_LOCAL: case ID_ATTRSET: case ID_JUNK:
10698         return TRUE;
10699     }
10700     return FALSE;
10701 }
10702 
10703 int
10704 rb_is_junk_name(VALUE name)
10705 {
10706     return rb_str_symname_type(name, IDSET_ATTRSET_FOR_SYNTAX) == -1;
10707 }
10708 
10709 #endif /* !RIPPER */
10710 
10711 static void
10712 parser_initialize(struct parser_params *parser)
10713 {
10714     parser->eofp = Qfalse;
10715 
10716     parser->parser_lex_strterm = 0;
10717     parser->parser_cond_stack = 0;
10718     parser->parser_cmdarg_stack = 0;
10719     parser->parser_class_nest = 0;
10720     parser->parser_paren_nest = 0;
10721     parser->parser_lpar_beg = 0;
10722     parser->parser_brace_nest = 0;
10723     parser->parser_in_single = 0;
10724     parser->parser_in_def = 0;
10725     parser->parser_in_defined = 0;
10726     parser->parser_compile_for_eval = 0;
10727     parser->parser_cur_mid = 0;
10728     parser->parser_tokenbuf = NULL;
10729     parser->parser_tokidx = 0;
10730     parser->parser_toksiz = 0;
10731     parser->parser_heredoc_end = 0;
10732     parser->parser_command_start = TRUE;
10733     parser->parser_deferred_nodes = 0;
10734     parser->parser_lex_pbeg = 0;
10735     parser->parser_lex_p = 0;
10736     parser->parser_lex_pend = 0;
10737     parser->parser_lvtbl = 0;
10738     parser->parser_ruby__end__seen = 0;
10739     parser->parser_ruby_sourcefile = 0;
10740     parser->parser_ruby_sourcefile_string = Qnil;
10741 #ifndef RIPPER
10742     parser->is_ripper = 0;
10743     parser->parser_eval_tree_begin = 0;
10744     parser->parser_eval_tree = 0;
10745 #else
10746     parser->is_ripper = 1;
10747     parser->delayed = Qnil;
10748 
10749     parser->result = Qnil;
10750     parser->parsing_thread = Qnil;
10751     parser->toplevel_p = TRUE;
10752 #endif
10753 #ifdef YYMALLOC
10754     parser->heap = NULL;
10755 #endif
10756     parser->enc = rb_utf8_encoding();
10757 }
10758 
10759 #ifdef RIPPER
10760 #define parser_mark ripper_parser_mark
10761 #define parser_free ripper_parser_free
10762 #endif
10763 
10764 static void
10765 parser_mark(void *ptr)
10766 {
10767     struct parser_params *p = (struct parser_params*)ptr;
10768 
10769     rb_gc_mark((VALUE)p->parser_lex_strterm);
10770     rb_gc_mark((VALUE)p->parser_deferred_nodes);
10771     rb_gc_mark(p->parser_lex_input);
10772     rb_gc_mark(p->parser_lex_lastline);
10773     rb_gc_mark(p->parser_lex_nextline);
10774     rb_gc_mark(p->parser_ruby_sourcefile_string);
10775 #ifndef RIPPER
10776     rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
10777     rb_gc_mark((VALUE)p->parser_eval_tree) ;
10778     rb_gc_mark(p->debug_lines);
10779 #else
10780     rb_gc_mark(p->delayed);
10781     rb_gc_mark(p->value);
10782     rb_gc_mark(p->result);
10783     rb_gc_mark(p->parsing_thread);
10784 #endif
10785 #ifdef YYMALLOC
10786     rb_gc_mark((VALUE)p->heap);
10787 #endif
10788 }
10789 
10790 static void
10791 parser_free(void *ptr)
10792 {
10793     struct parser_params *p = (struct parser_params*)ptr;
10794     struct local_vars *local, *prev;
10795 
10796     if (p->parser_tokenbuf) {
10797         xfree(p->parser_tokenbuf);
10798     }
10799     for (local = p->parser_lvtbl; local; local = prev) {
10800         if (local->vars) xfree(local->vars);
10801         prev = local->prev;
10802         xfree(local);
10803     }
10804     xfree(p);
10805 }
10806 
10807 static size_t
10808 parser_memsize(const void *ptr)
10809 {
10810     struct parser_params *p = (struct parser_params*)ptr;
10811     struct local_vars *local;
10812     size_t size = sizeof(*p);
10813 
10814     if (!ptr) return 0;
10815     size += p->parser_toksiz;
10816     for (local = p->parser_lvtbl; local; local = local->prev) {
10817         size += sizeof(*local);
10818         if (local->vars) size += local->vars->capa * sizeof(ID);
10819     }
10820     return size;
10821 }
10822 
10823 static
10824 #ifndef RIPPER
10825 const
10826 #endif
10827 rb_data_type_t parser_data_type = {
10828     "parser",
10829     {
10830         parser_mark,
10831         parser_free,
10832         parser_memsize,
10833     },
10834 };
10835 
10836 #ifndef RIPPER
10837 #undef rb_reserved_word
10838 
10839 const struct kwtable *
10840 rb_reserved_word(const char *str, unsigned int len)
10841 {
10842     return reserved_word(str, len);
10843 }
10844 
10845 static struct parser_params *
10846 parser_new(void)
10847 {
10848     struct parser_params *p;
10849 
10850     p = ALLOC_N(struct parser_params, 1);
10851     MEMZERO(p, struct parser_params, 1);
10852     parser_initialize(p);
10853     return p;
10854 }
10855 
10856 VALUE
10857 rb_parser_new(void)
10858 {
10859     struct parser_params *p = parser_new();
10860 
10861     return TypedData_Wrap_Struct(0, &parser_data_type, p);
10862 }
10863 
10864 /*
10865  *  call-seq:
10866  *    ripper#end_seen?   -> Boolean
10867  *
10868  *  Return true if parsed source ended by +\_\_END\_\_+.
10869  */
10870 VALUE
10871 rb_parser_end_seen_p(VALUE vparser)
10872 {
10873     struct parser_params *parser;
10874 
10875     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10876     return ruby__end__seen ? Qtrue : Qfalse;
10877 }
10878 
10879 /*
10880  *  call-seq:
10881  *    ripper#encoding   -> encoding
10882  *
10883  *  Return encoding of the source.
10884  */
10885 VALUE
10886 rb_parser_encoding(VALUE vparser)
10887 {
10888     struct parser_params *parser;
10889 
10890     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10891     return rb_enc_from_encoding(current_enc);
10892 }
10893 
10894 /*
10895  *  call-seq:
10896  *    ripper.yydebug   -> true or false
10897  *
10898  *  Get yydebug.
10899  */
10900 VALUE
10901 rb_parser_get_yydebug(VALUE self)
10902 {
10903     struct parser_params *parser;
10904 
10905     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10906     return yydebug ? Qtrue : Qfalse;
10907 }
10908 
10909 /*
10910  *  call-seq:
10911  *    ripper.yydebug = flag
10912  *
10913  *  Set yydebug.
10914  */
10915 VALUE
10916 rb_parser_set_yydebug(VALUE self, VALUE flag)
10917 {
10918     struct parser_params *parser;
10919 
10920     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10921     yydebug = RTEST(flag);
10922     return flag;
10923 }
10924 
10925 #ifdef YYMALLOC
10926 #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
10927 #define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
10928 #define ADD2HEAP(n, c, p) ((parser->heap = (n))->u1.node = (p), \
10929                            (n)->u3.cnt = (c), (p))
10930 
10931 void *
10932 rb_parser_malloc(struct parser_params *parser, size_t size)
10933 {
10934     size_t cnt = HEAPCNT(1, size);
10935     NODE *n = NEWHEAP();
10936     void *ptr = xmalloc(size);
10937 
10938     return ADD2HEAP(n, cnt, ptr);
10939 }
10940 
10941 void *
10942 rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size)
10943 {
10944     size_t cnt = HEAPCNT(nelem, size);
10945     NODE *n = NEWHEAP();
10946     void *ptr = xcalloc(nelem, size);
10947 
10948     return ADD2HEAP(n, cnt, ptr);
10949 }
10950 
10951 void *
10952 rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size)
10953 {
10954     NODE *n;
10955     size_t cnt = HEAPCNT(1, size);
10956 
10957     if (ptr && (n = parser->heap) != NULL) {
10958         do {
10959             if (n->u1.node == ptr) {
10960                 n->u1.node = ptr = xrealloc(ptr, size);
10961                 if (n->u3.cnt) n->u3.cnt = cnt;
10962                 return ptr;
10963             }
10964         } while ((n = n->u2.node) != NULL);
10965     }
10966     n = NEWHEAP();
10967     ptr = xrealloc(ptr, size);
10968     return ADD2HEAP(n, cnt, ptr);
10969 }
10970 
10971 void
10972 rb_parser_free(struct parser_params *parser, void *ptr)
10973 {
10974     NODE **prev = &parser->heap, *n;
10975 
10976     while ((n = *prev) != NULL) {
10977         if (n->u1.node == ptr) {
10978             *prev = n->u2.node;
10979             rb_gc_force_recycle((VALUE)n);
10980             break;
10981         }
10982         prev = &n->u2.node;
10983     }
10984     xfree(ptr);
10985 }
10986 #endif
10987 #endif
10988 
10989 #ifdef RIPPER
10990 #ifdef RIPPER_DEBUG
10991 extern int rb_is_pointer_to_heap(VALUE);
10992 
10993 /* :nodoc: */
10994 static VALUE
10995 ripper_validate_object(VALUE self, VALUE x)
10996 {
10997     if (x == Qfalse) return x;
10998     if (x == Qtrue) return x;
10999     if (x == Qnil) return x;
11000     if (x == Qundef)
11001         rb_raise(rb_eArgError, "Qundef given");
11002     if (FIXNUM_P(x)) return x;
11003     if (SYMBOL_P(x)) return x;
11004     if (!rb_is_pointer_to_heap(x))
11005         rb_raise(rb_eArgError, "invalid pointer: %p", x);
11006     switch (TYPE(x)) {
11007       case T_STRING:
11008       case T_OBJECT:
11009       case T_ARRAY:
11010       case T_BIGNUM:
11011       case T_FLOAT:
11012         return x;
11013       case T_NODE:
11014         if (nd_type(x) != NODE_LASGN) {
11015             rb_raise(rb_eArgError, "NODE given: %p", x);
11016         }
11017         return ((NODE *)x)->nd_rval;
11018       default:
11019         rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
11020                  x, rb_obj_classname(x));
11021     }
11022     return x;
11023 }
11024 #endif
11025 
11026 #define validate(x) ((x) = get_value(x))
11027 
11028 static VALUE
11029 ripper_dispatch0(struct parser_params *parser, ID mid)
11030 {
11031     return rb_funcall(parser->value, mid, 0);
11032 }
11033 
11034 static VALUE
11035 ripper_dispatch1(struct parser_params *parser, ID mid, VALUE a)
11036 {
11037     validate(a);
11038     return rb_funcall(parser->value, mid, 1, a);
11039 }
11040 
11041 static VALUE
11042 ripper_dispatch2(struct parser_params *parser, ID mid, VALUE a, VALUE b)
11043 {
11044     validate(a);
11045     validate(b);
11046     return rb_funcall(parser->value, mid, 2, a, b);
11047 }
11048 
11049 static VALUE
11050 ripper_dispatch3(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c)
11051 {
11052     validate(a);
11053     validate(b);
11054     validate(c);
11055     return rb_funcall(parser->value, mid, 3, a, b, c);
11056 }
11057 
11058 static VALUE
11059 ripper_dispatch4(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d)
11060 {
11061     validate(a);
11062     validate(b);
11063     validate(c);
11064     validate(d);
11065     return rb_funcall(parser->value, mid, 4, a, b, c, d);
11066 }
11067 
11068 static VALUE
11069 ripper_dispatch5(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e)
11070 {
11071     validate(a);
11072     validate(b);
11073     validate(c);
11074     validate(d);
11075     validate(e);
11076     return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
11077 }
11078 
11079 static VALUE
11080 ripper_dispatch7(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, VALUE f, VALUE g)
11081 {
11082     validate(a);
11083     validate(b);
11084     validate(c);
11085     validate(d);
11086     validate(e);
11087     validate(f);
11088     validate(g);
11089     return rb_funcall(parser->value, mid, 7, a, b, c, d, e, f, g);
11090 }
11091 
11092 static const struct kw_assoc {
11093     ID id;
11094     const char *name;
11095 } keyword_to_name[] = {
11096     {keyword_class,     "class"},
11097     {keyword_module,    "module"},
11098     {keyword_def,       "def"},
11099     {keyword_undef,     "undef"},
11100     {keyword_begin,     "begin"},
11101     {keyword_rescue,    "rescue"},
11102     {keyword_ensure,    "ensure"},
11103     {keyword_end,       "end"},
11104     {keyword_if,        "if"},
11105     {keyword_unless,    "unless"},
11106     {keyword_then,      "then"},
11107     {keyword_elsif,     "elsif"},
11108     {keyword_else,      "else"},
11109     {keyword_case,      "case"},
11110     {keyword_when,      "when"},
11111     {keyword_while,     "while"},
11112     {keyword_until,     "until"},
11113     {keyword_for,       "for"},
11114     {keyword_break,     "break"},
11115     {keyword_next,      "next"},
11116     {keyword_redo,      "redo"},
11117     {keyword_retry,     "retry"},
11118     {keyword_in,        "in"},
11119     {keyword_do,        "do"},
11120     {keyword_do_cond,   "do"},
11121     {keyword_do_block,  "do"},
11122     {keyword_return,    "return"},
11123     {keyword_yield,     "yield"},
11124     {keyword_super,     "super"},
11125     {keyword_self,      "self"},
11126     {keyword_nil,       "nil"},
11127     {keyword_true,      "true"},
11128     {keyword_false,     "false"},
11129     {keyword_and,       "and"},
11130     {keyword_or,        "or"},
11131     {keyword_not,       "not"},
11132     {modifier_if,       "if"},
11133     {modifier_unless,   "unless"},
11134     {modifier_while,    "while"},
11135     {modifier_until,    "until"},
11136     {modifier_rescue,   "rescue"},
11137     {keyword_alias,     "alias"},
11138     {keyword_defined,   "defined?"},
11139     {keyword_BEGIN,     "BEGIN"},
11140     {keyword_END,       "END"},
11141     {keyword__LINE__,   "__LINE__"},
11142     {keyword__FILE__,   "__FILE__"},
11143     {keyword__ENCODING__, "__ENCODING__"},
11144     {0, NULL}
11145 };
11146 
11147 static const char*
11148 keyword_id_to_str(ID id)
11149 {
11150     const struct kw_assoc *a;
11151 
11152     for (a = keyword_to_name; a->id; a++) {
11153         if (a->id == id)
11154             return a->name;
11155     }
11156     return NULL;
11157 }
11158 
11159 #undef ripper_id2sym
11160 static VALUE
11161 ripper_id2sym(ID id)
11162 {
11163     const char *name;
11164     char buf[8];
11165 
11166     if (id <= 256) {
11167         buf[0] = (char)id;
11168         buf[1] = '\0';
11169         return ID2SYM(rb_intern2(buf, 1));
11170     }
11171     if ((name = keyword_id_to_str(id))) {
11172         return ID2SYM(rb_intern(name));
11173     }
11174     switch (id) {
11175       case tOROP:
11176         name = "||";
11177         break;
11178       case tANDOP:
11179         name = "&&";
11180         break;
11181       default:
11182         name = rb_id2name(id);
11183         if (!name) {
11184             rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
11185         }
11186         return ID2SYM(id);
11187     }
11188     return ID2SYM(rb_intern(name));
11189 }
11190 
11191 static ID
11192 ripper_get_id(VALUE v)
11193 {
11194     NODE *nd;
11195     if (!RB_TYPE_P(v, T_NODE)) return 0;
11196     nd = (NODE *)v;
11197     if (nd_type(nd) != NODE_LASGN) return 0;
11198     return nd->nd_vid;
11199 }
11200 
11201 static VALUE
11202 ripper_get_value(VALUE v)
11203 {
11204     NODE *nd;
11205     if (v == Qundef) return Qnil;
11206     if (!RB_TYPE_P(v, T_NODE)) return v;
11207     nd = (NODE *)v;
11208     if (nd_type(nd) != NODE_LASGN) return Qnil;
11209     return nd->nd_rval;
11210 }
11211 
11212 static void
11213 ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
11214 {
11215     VALUE str;
11216     va_list args;
11217 
11218     va_start(args, fmt);
11219     str = rb_vsprintf(fmt, args);
11220     va_end(args);
11221     rb_funcall(parser->value, rb_intern("compile_error"), 1, str);
11222 }
11223 
11224 static void
11225 ripper_warn0(struct parser_params *parser, const char *fmt)
11226 {
11227     rb_funcall(parser->value, rb_intern("warn"), 1, STR_NEW2(fmt));
11228 }
11229 
11230 static void
11231 ripper_warnI(struct parser_params *parser, const char *fmt, int a)
11232 {
11233     rb_funcall(parser->value, rb_intern("warn"), 2,
11234                STR_NEW2(fmt), INT2NUM(a));
11235 }
11236 
11237 static void
11238 ripper_warnS(struct parser_params *parser, const char *fmt, const char *str)
11239 {
11240     rb_funcall(parser->value, rb_intern("warn"), 2,
11241                STR_NEW2(fmt), STR_NEW2(str));
11242 }
11243 
11244 static void
11245 ripper_warning0(struct parser_params *parser, const char *fmt)
11246 {
11247     rb_funcall(parser->value, rb_intern("warning"), 1, STR_NEW2(fmt));
11248 }
11249 
11250 static void
11251 ripper_warningS(struct parser_params *parser, const char *fmt, const char *str)
11252 {
11253     rb_funcall(parser->value, rb_intern("warning"), 2,
11254                STR_NEW2(fmt), STR_NEW2(str));
11255 }
11256 
11257 static VALUE
11258 ripper_lex_get_generic(struct parser_params *parser, VALUE src)
11259 {
11260     return rb_io_gets(src);
11261 }
11262 
11263 static VALUE
11264 ripper_s_allocate(VALUE klass)
11265 {
11266     struct parser_params *p;
11267     VALUE self;
11268 
11269     p = ALLOC_N(struct parser_params, 1);
11270     MEMZERO(p, struct parser_params, 1);
11271     self = TypedData_Wrap_Struct(klass, &parser_data_type, p);
11272     p->value = self;
11273     return self;
11274 }
11275 
11276 #define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
11277 
11278 /*
11279  *  call-seq:
11280  *    Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
11281  *
11282  *  Create a new Ripper object.
11283  *  _src_ must be a String, an IO, or an Object which has #gets method.
11284  *
11285  *  This method does not starts parsing.
11286  *  See also Ripper#parse and Ripper.parse.
11287  */
11288 static VALUE
11289 ripper_initialize(int argc, VALUE *argv, VALUE self)
11290 {
11291     struct parser_params *parser;
11292     VALUE src, fname, lineno;
11293 
11294     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
11295     rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
11296     if (RB_TYPE_P(src, T_FILE)) {
11297         parser->parser_lex_gets = ripper_lex_get_generic;
11298     }
11299     else {
11300         StringValue(src);
11301         parser->parser_lex_gets = lex_get_str;
11302     }
11303     parser->parser_lex_input = src;
11304     parser->eofp = Qfalse;
11305     if (NIL_P(fname)) {
11306         fname = STR_NEW2("(ripper)");
11307     }
11308     else {
11309         StringValue(fname);
11310     }
11311     parser_initialize(parser);
11312 
11313     parser->parser_ruby_sourcefile_string = fname;
11314     parser->parser_ruby_sourcefile = RSTRING_PTR(fname);
11315     parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
11316 
11317     return Qnil;
11318 }
11319 
11320 struct ripper_args {
11321     struct parser_params *parser;
11322     int argc;
11323     VALUE *argv;
11324 };
11325 
11326 static VALUE
11327 ripper_parse0(VALUE parser_v)
11328 {
11329     struct parser_params *parser;
11330 
11331     TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
11332     parser_prepare(parser);
11333     ripper_yyparse((void*)parser);
11334     return parser->result;
11335 }
11336 
11337 static VALUE
11338 ripper_ensure(VALUE parser_v)
11339 {
11340     struct parser_params *parser;
11341 
11342     TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
11343     parser->parsing_thread = Qnil;
11344     return Qnil;
11345 }
11346 
11347 /*
11348  *  call-seq:
11349  *    ripper#parse
11350  *
11351  *  Start parsing and returns the value of the root action.
11352  */
11353 static VALUE
11354 ripper_parse(VALUE self)
11355 {
11356     struct parser_params *parser;
11357 
11358     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
11359     if (!ripper_initialized_p(parser)) {
11360         rb_raise(rb_eArgError, "method called for uninitialized object");
11361     }
11362     if (!NIL_P(parser->parsing_thread)) {
11363         if (parser->parsing_thread == rb_thread_current())
11364             rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
11365         else
11366             rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
11367     }
11368     parser->parsing_thread = rb_thread_current();
11369     rb_ensure(ripper_parse0, self, ripper_ensure, self);
11370 
11371     return parser->result;
11372 }
11373 
11374 /*
11375  *  call-seq:
11376  *    ripper#column   -> Integer
11377  *
11378  *  Return column number of current parsing line.
11379  *  This number starts from 0.
11380  */
11381 static VALUE
11382 ripper_column(VALUE self)
11383 {
11384     struct parser_params *parser;
11385     long col;
11386 
11387     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
11388     if (!ripper_initialized_p(parser)) {
11389         rb_raise(rb_eArgError, "method called for uninitialized object");
11390     }
11391     if (NIL_P(parser->parsing_thread)) return Qnil;
11392     col = parser->tokp - parser->parser_lex_pbeg;
11393     return LONG2NUM(col);
11394 }
11395 
11396 /*
11397  *  call-seq:
11398  *    ripper#filename   -> String
11399  *
11400  *  Return current parsing filename.
11401  */
11402 static VALUE
11403 ripper_filename(VALUE self)
11404 {
11405     struct parser_params *parser;
11406 
11407     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
11408     if (!ripper_initialized_p(parser)) {
11409         rb_raise(rb_eArgError, "method called for uninitialized object");
11410     }
11411     return parser->parser_ruby_sourcefile_string;
11412 }
11413 
11414 /*
11415  *  call-seq:
11416  *    ripper#lineno   -> Integer
11417  *
11418  *  Return line number of current parsing line.
11419  *  This number starts from 1.
11420  */
11421 static VALUE
11422 ripper_lineno(VALUE self)
11423 {
11424     struct parser_params *parser;
11425 
11426     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
11427     if (!ripper_initialized_p(parser)) {
11428         rb_raise(rb_eArgError, "method called for uninitialized object");
11429     }
11430     if (NIL_P(parser->parsing_thread)) return Qnil;
11431     return INT2NUM(parser->parser_ruby_sourceline);
11432 }
11433 
11434 #ifdef RIPPER_DEBUG
11435 /* :nodoc: */
11436 static VALUE
11437 ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
11438 {
11439     StringValue(msg);
11440     if (obj == Qundef) {
11441         rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
11442     }
11443     return Qnil;
11444 }
11445 
11446 /* :nodoc: */
11447 static VALUE
11448 ripper_value(VALUE self, VALUE obj)
11449 {
11450     return ULONG2NUM(obj);
11451 }
11452 #endif
11453 
11454 
11455 void
11456 Init_ripper(void)
11457 {
11458     parser_data_type.parent = RTYPEDDATA_TYPE(rb_parser_new());
11459 
11460     ripper_init_eventids1();
11461     ripper_init_eventids2();
11462     /* ensure existing in symbol table */
11463     (void)rb_intern("||");
11464     (void)rb_intern("&&");
11465 
11466     InitVM(ripper);
11467 }
11468 
11469 void
11470 InitVM_ripper(void)
11471 {
11472     VALUE Ripper;
11473 
11474     Ripper = rb_define_class("Ripper", rb_cObject);
11475     rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
11476     rb_define_alloc_func(Ripper, ripper_s_allocate);
11477     rb_define_method(Ripper, "initialize", ripper_initialize, -1);
11478     rb_define_method(Ripper, "parse", ripper_parse, 0);
11479     rb_define_method(Ripper, "column", ripper_column, 0);
11480     rb_define_method(Ripper, "filename", ripper_filename, 0);
11481     rb_define_method(Ripper, "lineno", ripper_lineno, 0);
11482     rb_define_method(Ripper, "end_seen?", rb_parser_end_seen_p, 0);
11483     rb_define_method(Ripper, "encoding", rb_parser_encoding, 0);
11484     rb_define_method(Ripper, "yydebug", rb_parser_get_yydebug, 0);
11485     rb_define_method(Ripper, "yydebug=", rb_parser_set_yydebug, 1);
11486 #ifdef RIPPER_DEBUG
11487     rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
11488     rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
11489     rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
11490 #endif
11491 
11492     ripper_init_eventids1_table(Ripper);
11493     ripper_init_eventids2_table(Ripper);
11494 
11495 # if 0
11496     /* Hack to let RDoc document SCRIPT_LINES__ */
11497 
11498     /*
11499      * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
11500      * after the assignment will be added as an Array of lines with the file
11501      * name as the key.
11502      */
11503     rb_define_global_const("SCRIPT_LINES__", Qnil);
11504 #endif
11505 
11506 }
11507 #endif /* RIPPER */
11508