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