Ruby 1.9.3p327(2012-11-10revision37606)
parse.y
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   parse.y -
00004 
00005   $Author: naruse $
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 static int
05989 parser_parse_string(struct parser_params *parser, NODE *quote)
05990 {
05991     int func = (int)quote->nd_func;
05992     int term = nd_term(quote);
05993     int paren = nd_paren(quote);
05994     int c, space = 0;
05995     rb_encoding *enc = parser->enc;
05996 
05997     if (func == -1) return tSTRING_END;
05998     c = nextc();
05999     if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
06000         do {c = nextc();} while (ISSPACE(c));
06001         space = 1;
06002     }
06003     if (c == term && !quote->nd_nest) {
06004         if (func & STR_FUNC_QWORDS) {
06005             quote->nd_func = -1;
06006             return ' ';
06007         }
06008         if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
06009         set_yylval_num(regx_options());
06010         return tREGEXP_END;
06011     }
06012     if (space) {
06013         pushback(c);
06014         return ' ';
06015     }
06016     newtok();
06017     if ((func & STR_FUNC_EXPAND) && c == '#') {
06018         switch (c = nextc()) {
06019           case '$':
06020           case '@':
06021             pushback(c);
06022             return tSTRING_DVAR;
06023           case '{':
06024             return tSTRING_DBEG;
06025         }
06026         tokadd('#');
06027     }
06028     pushback(c);
06029     if (tokadd_string(func, term, paren, &quote->nd_nest,
06030                       &enc) == -1) {
06031         ruby_sourceline = nd_line(quote);
06032         if (func & STR_FUNC_REGEXP) {
06033             if (parser->eofp)
06034                 compile_error(PARSER_ARG "unterminated regexp meets end of file");
06035             return tREGEXP_END;
06036         }
06037         else {
06038             if (parser->eofp)
06039                 compile_error(PARSER_ARG "unterminated string meets end of file");
06040             return tSTRING_END;
06041         }
06042     }
06043 
06044     tokfix();
06045     set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06046 
06047 #ifdef RIPPER
06048     if (!NIL_P(parser->delayed)) {
06049         ptrdiff_t len = lex_p - parser->tokp;
06050         if (len > 0) {
06051             rb_enc_str_buf_cat(parser->delayed, parser->tokp, len, enc);
06052         }
06053         ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06054         parser->tokp = lex_p;
06055     }
06056 #endif
06057 
06058     return tSTRING_CONTENT;
06059 }
06060 
06061 static int
06062 parser_heredoc_identifier(struct parser_params *parser)
06063 {
06064     int c = nextc(), term, func = 0;
06065     long len;
06066 
06067     if (c == '-') {
06068         c = nextc();
06069         func = STR_FUNC_INDENT;
06070     }
06071     switch (c) {
06072       case '\'':
06073         func |= str_squote; goto quoted;
06074       case '"':
06075         func |= str_dquote; goto quoted;
06076       case '`':
06077         func |= str_xquote;
06078       quoted:
06079         newtok();
06080         tokadd(func);
06081         term = c;
06082         while ((c = nextc()) != -1 && c != term) {
06083             if (tokadd_mbchar(c) == -1) return 0;
06084         }
06085         if (c == -1) {
06086             compile_error(PARSER_ARG "unterminated here document identifier");
06087             return 0;
06088         }
06089         break;
06090 
06091       default:
06092         if (!parser_is_identchar()) {
06093             pushback(c);
06094             if (func & STR_FUNC_INDENT) {
06095                 pushback('-');
06096             }
06097             return 0;
06098         }
06099         newtok();
06100         term = '"';
06101         tokadd(func |= str_dquote);
06102         do {
06103             if (tokadd_mbchar(c) == -1) return 0;
06104         } while ((c = nextc()) != -1 && parser_is_identchar());
06105         pushback(c);
06106         break;
06107     }
06108 
06109     tokfix();
06110 #ifdef RIPPER
06111     ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
06112 #endif
06113     len = lex_p - lex_pbeg;
06114     lex_goto_eol(parser);
06115     lex_strterm = rb_node_newnode(NODE_HEREDOC,
06116                                   STR_NEW(tok(), toklen()),     /* nd_lit */
06117                                   len,                          /* nd_nth */
06118                                   lex_lastline);                /* nd_orig */
06119     nd_set_line(lex_strterm, ruby_sourceline);
06120     ripper_flush(parser);
06121     return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
06122 }
06123 
06124 static void
06125 parser_heredoc_restore(struct parser_params *parser, NODE *here)
06126 {
06127     VALUE line;
06128 
06129     line = here->nd_orig;
06130     lex_lastline = line;
06131     lex_pbeg = RSTRING_PTR(line);
06132     lex_pend = lex_pbeg + RSTRING_LEN(line);
06133     lex_p = lex_pbeg + here->nd_nth;
06134     heredoc_end = ruby_sourceline;
06135     ruby_sourceline = nd_line(here);
06136     dispose_string(here->nd_lit);
06137     rb_gc_force_recycle((VALUE)here);
06138     ripper_flush(parser);
06139 }
06140 
06141 static int
06142 parser_whole_match_p(struct parser_params *parser,
06143     const char *eos, long len, int indent)
06144 {
06145     const char *p = lex_pbeg;
06146     long n;
06147 
06148     if (indent) {
06149         while (*p && ISSPACE(*p)) p++;
06150     }
06151     n = lex_pend - (p + len);
06152     if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE;
06153     return strncmp(eos, p, len) == 0;
06154 }
06155 
06156 #ifdef RIPPER
06157 static void
06158 ripper_dispatch_heredoc_end(struct parser_params *parser)
06159 {
06160     if (!NIL_P(parser->delayed))
06161         ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06162     lex_goto_eol(parser);
06163     ripper_dispatch_ignored_scan_event(parser, tHEREDOC_END);
06164 }
06165 
06166 #define dispatch_heredoc_end() ripper_dispatch_heredoc_end(parser)
06167 #else
06168 #define dispatch_heredoc_end() ((void)0)
06169 #endif
06170 
06171 static int
06172 parser_here_document(struct parser_params *parser, NODE *here)
06173 {
06174     int c, func, indent = 0;
06175     const char *eos, *p, *pend;
06176     long len;
06177     VALUE str = 0;
06178     rb_encoding *enc = parser->enc;
06179 
06180     eos = RSTRING_PTR(here->nd_lit);
06181     len = RSTRING_LEN(here->nd_lit) - 1;
06182     indent = (func = *eos++) & STR_FUNC_INDENT;
06183 
06184     if ((c = nextc()) == -1) {
06185       error:
06186         compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
06187 #ifdef RIPPER
06188         if (NIL_P(parser->delayed)) {
06189             ripper_dispatch_scan_event(parser, tSTRING_CONTENT);
06190         }
06191         else {
06192             if (str ||
06193                 ((len = lex_p - parser->tokp) > 0 &&
06194                  (str = STR_NEW3(parser->tokp, len, enc, func), 1))) {
06195                 rb_str_append(parser->delayed, str);
06196             }
06197             ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06198         }
06199         lex_goto_eol(parser);
06200 #endif
06201       restore:
06202         heredoc_restore(lex_strterm);
06203         lex_strterm = 0;
06204         return 0;
06205     }
06206     if (was_bol() && whole_match_p(eos, len, indent)) {
06207         dispatch_heredoc_end();
06208         heredoc_restore(lex_strterm);
06209         return tSTRING_END;
06210     }
06211 
06212     if (!(func & STR_FUNC_EXPAND)) {
06213         do {
06214             p = RSTRING_PTR(lex_lastline);
06215             pend = lex_pend;
06216             if (pend > p) {
06217                 switch (pend[-1]) {
06218                   case '\n':
06219                     if (--pend == p || pend[-1] != '\r') {
06220                         pend++;
06221                         break;
06222                     }
06223                   case '\r':
06224                     --pend;
06225                 }
06226             }
06227             if (str)
06228                 rb_str_cat(str, p, pend - p);
06229             else
06230                 str = STR_NEW(p, pend - p);
06231             if (pend < lex_pend) rb_str_cat(str, "\n", 1);
06232             lex_goto_eol(parser);
06233             if (nextc() == -1) {
06234                 if (str) dispose_string(str);
06235                 goto error;
06236             }
06237         } while (!whole_match_p(eos, len, indent));
06238     }
06239     else {
06240         /*      int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
06241         newtok();
06242         if (c == '#') {
06243             switch (c = nextc()) {
06244               case '$':
06245               case '@':
06246                 pushback(c);
06247                 return tSTRING_DVAR;
06248               case '{':
06249                 return tSTRING_DBEG;
06250             }
06251             tokadd('#');
06252         }
06253         do {
06254             pushback(c);
06255             if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) {
06256                 if (parser->eofp) goto error;
06257                 goto restore;
06258             }
06259             if (c != '\n') {
06260                 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06261                 return tSTRING_CONTENT;
06262             }
06263             tokadd(nextc());
06264             /*      if (mbp && mb == ENC_CODERANGE_UNKNOWN) mbp = 0;*/
06265             if ((c = nextc()) == -1) goto error;
06266         } while (!whole_match_p(eos, len, indent));
06267         str = STR_NEW3(tok(), toklen(), enc, func);
06268     }
06269     dispatch_heredoc_end();
06270     heredoc_restore(lex_strterm);
06271     lex_strterm = NEW_STRTERM(-1, 0, 0);
06272     set_yylval_str(str);
06273     return tSTRING_CONTENT;
06274 }
06275 
06276 #include "lex.c"
06277 
06278 static void
06279 arg_ambiguous_gen(struct parser_params *parser)
06280 {
06281 #ifndef RIPPER
06282     rb_warning0("ambiguous first argument; put parentheses or even spaces");
06283 #else
06284     dispatch0(arg_ambiguous);
06285 #endif
06286 }
06287 #define arg_ambiguous() (arg_ambiguous_gen(parser), 1)
06288 
06289 static ID
06290 formal_argument_gen(struct parser_params *parser, ID lhs)
06291 {
06292 #ifndef RIPPER
06293     if (!is_local_id(lhs))
06294         yyerror("formal argument must be local variable");
06295 #endif
06296     shadowing_lvar(lhs);
06297     return lhs;
06298 }
06299 
06300 static int
06301 lvar_defined_gen(struct parser_params *parser, ID id)
06302 {
06303     return (dyna_in_block() && dvar_defined_get(id)) || local_id(id);
06304 }
06305 
06306 /* emacsen -*- hack */
06307 static long
06308 parser_encode_length(struct parser_params *parser, const char *name, long len)
06309 {
06310     long nlen;
06311 
06312     if (len > 5 && name[nlen = len - 5] == '-') {
06313         if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0)
06314             return nlen;
06315     }
06316     if (len > 4 && name[nlen = len - 4] == '-') {
06317         if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0)
06318             return nlen;
06319         if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0 &&
06320             !(len == 8 && rb_memcicmp(name, "utf8-mac", len) == 0))
06321             /* exclude UTF8-MAC because the encoding named "UTF8" doesn't exist in Ruby */
06322             return nlen;
06323     }
06324     return len;
06325 }
06326 
06327 static void
06328 parser_set_encode(struct parser_params *parser, const char *name)
06329 {
06330     int idx = rb_enc_find_index(name);
06331     rb_encoding *enc;
06332     VALUE excargs[3];
06333 
06334     if (idx < 0) {
06335         excargs[1] = rb_sprintf("unknown encoding name: %s", name);
06336       error:
06337         excargs[0] = rb_eArgError;
06338         excargs[2] = rb_make_backtrace();
06339         rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));
06340         rb_exc_raise(rb_make_exception(3, excargs));
06341     }
06342     enc = rb_enc_from_index(idx);
06343     if (!rb_enc_asciicompat(enc)) {
06344         excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));
06345         goto error;
06346     }
06347     parser->enc = enc;
06348 #ifndef RIPPER
06349     if (ruby_debug_lines) {
06350         long i, n = RARRAY_LEN(ruby_debug_lines);
06351         const VALUE *p = RARRAY_PTR(ruby_debug_lines);
06352         for (i = 0; i < n; ++i) {
06353             rb_enc_associate_index(*p, idx);
06354         }
06355     }
06356 #endif
06357 }
06358 
06359 static int
06360 comment_at_top(struct parser_params *parser)
06361 {
06362     const char *p = lex_pbeg, *pend = lex_p - 1;
06363     if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0;
06364     while (p < pend) {
06365         if (!ISSPACE(*p)) return 0;
06366         p++;
06367     }
06368     return 1;
06369 }
06370 
06371 #ifndef RIPPER
06372 typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);
06373 typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
06374 
06375 static void
06376 magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
06377 {
06378     if (!comment_at_top(parser)) {
06379         return;
06380     }
06381     parser_set_encode(parser, val);
06382 }
06383 
06384 static void
06385 parser_set_token_info(struct parser_params *parser, const char *name, const char *val)
06386 {
06387     int *p = &parser->parser_token_info_enabled;
06388 
06389     switch (*val) {
06390       case 't': case 'T':
06391         if (strcasecmp(val, "true") == 0) {
06392             *p = TRUE;
06393             return;
06394         }
06395         break;
06396       case 'f': case 'F':
06397         if (strcasecmp(val, "false") == 0) {
06398             *p = FALSE;
06399             return;
06400         }
06401         break;
06402     }
06403     rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);
06404 }
06405 
06406 struct magic_comment {
06407     const char *name;
06408     rb_magic_comment_setter_t func;
06409     rb_magic_comment_length_t length;
06410 };
06411 
06412 static const struct magic_comment magic_comments[] = {
06413     {"coding", magic_comment_encoding, parser_encode_length},
06414     {"encoding", magic_comment_encoding, parser_encode_length},
06415     {"warn_indent", parser_set_token_info},
06416 };
06417 #endif
06418 
06419 static const char *
06420 magic_comment_marker(const char *str, long len)
06421 {
06422     long i = 2;
06423 
06424     while (i < len) {
06425         switch (str[i]) {
06426           case '-':
06427             if (str[i-1] == '*' && str[i-2] == '-') {
06428                 return str + i + 1;
06429             }
06430             i += 2;
06431             break;
06432           case '*':
06433             if (i + 1 >= len) return 0;
06434             if (str[i+1] != '-') {
06435                 i += 4;
06436             }
06437             else if (str[i-1] != '-') {
06438                 i += 2;
06439             }
06440             else {
06441                 return str + i + 2;
06442             }
06443             break;
06444           default:
06445             i += 3;
06446             break;
06447         }
06448     }
06449     return 0;
06450 }
06451 
06452 static int
06453 parser_magic_comment(struct parser_params *parser, const char *str, long len)
06454 {
06455     VALUE name = 0, val = 0;
06456     const char *beg, *end, *vbeg, *vend;
06457 #define str_copy(_s, _p, _n) ((_s) \
06458         ? (void)(rb_str_resize((_s), (_n)), \
06459            MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
06460         : (void)((_s) = STR_NEW((_p), (_n))))
06461 
06462     if (len <= 7) return FALSE;
06463     if (!(beg = magic_comment_marker(str, len))) return FALSE;
06464     if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE;
06465     str = beg;
06466     len = end - beg - 3;
06467 
06468     /* %r"([^\\s\'\":;]+)\\s*:\\s*(\"(?:\\\\.|[^\"])*\"|[^\"\\s;]+)[\\s;]*" */
06469     while (len > 0) {
06470 #ifndef RIPPER
06471         const struct magic_comment *p = magic_comments;
06472 #endif
06473         char *s;
06474         int i;
06475         long n = 0;
06476 
06477         for (; len > 0 && *str; str++, --len) {
06478             switch (*str) {
06479               case '\'': case '"': case ':': case ';':
06480                 continue;
06481             }
06482             if (!ISSPACE(*str)) break;
06483         }
06484         for (beg = str; len > 0; str++, --len) {
06485             switch (*str) {
06486               case '\'': case '"': case ':': case ';':
06487                 break;
06488               default:
06489                 if (ISSPACE(*str)) break;
06490                 continue;
06491             }
06492             break;
06493         }
06494         for (end = str; len > 0 && ISSPACE(*str); str++, --len);
06495         if (!len) break;
06496         if (*str != ':') continue;
06497 
06498         do str++; while (--len > 0 && ISSPACE(*str));
06499         if (!len) break;
06500         if (*str == '"') {
06501             for (vbeg = ++str; --len > 0 && *str != '"'; str++) {
06502                 if (*str == '\\') {
06503                     --len;
06504                     ++str;
06505                 }
06506             }
06507             vend = str;
06508             if (len) {
06509                 --len;
06510                 ++str;
06511             }
06512         }
06513         else {
06514             for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++);
06515             vend = str;
06516         }
06517         while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++;
06518 
06519         n = end - beg;
06520         str_copy(name, beg, n);
06521         s = RSTRING_PTR(name);
06522         for (i = 0; i < n; ++i) {
06523             if (s[i] == '-') s[i] = '_';
06524         }
06525 #ifndef RIPPER
06526         do {
06527             if (STRNCASECMP(p->name, s, n) == 0) {
06528                 n = vend - vbeg;
06529                 if (p->length) {
06530                     n = (*p->length)(parser, vbeg, n);
06531                 }
06532                 str_copy(val, vbeg, n);
06533                 (*p->func)(parser, s, RSTRING_PTR(val));
06534                 break;
06535             }
06536         } while (++p < magic_comments + numberof(magic_comments));
06537 #else
06538         dispatch2(magic_comment, name, val);
06539 #endif
06540     }
06541 
06542     return TRUE;
06543 }
06544 
06545 static void
06546 set_file_encoding(struct parser_params *parser, const char *str, const char *send)
06547 {
06548     int sep = 0;
06549     const char *beg = str;
06550     VALUE s;
06551 
06552     for (;;) {
06553         if (send - str <= 6) return;
06554         switch (str[6]) {
06555           case 'C': case 'c': str += 6; continue;
06556           case 'O': case 'o': str += 5; continue;
06557           case 'D': case 'd': str += 4; continue;
06558           case 'I': case 'i': str += 3; continue;
06559           case 'N': case 'n': str += 2; continue;
06560           case 'G': case 'g': str += 1; continue;
06561           case '=': case ':':
06562             sep = 1;
06563             str += 6;
06564             break;
06565           default:
06566             str += 6;
06567             if (ISSPACE(*str)) break;
06568             continue;
06569         }
06570         if (STRNCASECMP(str-6, "coding", 6) == 0) break;
06571     }
06572     for (;;) {
06573         do {
06574             if (++str >= send) return;
06575         } while (ISSPACE(*str));
06576         if (sep) break;
06577         if (*str != '=' && *str != ':') return;
06578         sep = 1;
06579         str++;
06580     }
06581     beg = str;
06582     while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send);
06583     s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg));
06584     parser_set_encode(parser, RSTRING_PTR(s));
06585     rb_str_resize(s, 0);
06586 }
06587 
06588 static void
06589 parser_prepare(struct parser_params *parser)
06590 {
06591     int c = nextc();
06592     switch (c) {
06593       case '#':
06594         if (peek('!')) parser->has_shebang = 1;
06595         break;
06596       case 0xef:                /* UTF-8 BOM marker */
06597         if (lex_pend - lex_p >= 2 &&
06598             (unsigned char)lex_p[0] == 0xbb &&
06599             (unsigned char)lex_p[1] == 0xbf) {
06600             parser->enc = rb_utf8_encoding();
06601             lex_p += 2;
06602             lex_pbeg = lex_p;
06603             return;
06604         }
06605         break;
06606       case EOF:
06607         return;
06608     }
06609     pushback(c);
06610     parser->enc = rb_enc_get(lex_lastline);
06611 }
06612 
06613 #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
06614 #define IS_END() (lex_state == EXPR_END || lex_state == EXPR_ENDARG || lex_state == EXPR_ENDFN)
06615 #define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS)
06616 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
06617 #define IS_LABEL_POSSIBLE() ((lex_state == EXPR_BEG && !cmd_state) || IS_ARG())
06618 #define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1))
06619 
06620 #ifndef RIPPER
06621 #define ambiguous_operator(op, syn) ( \
06622     rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
06623     rb_warning0("even though it seems like "syn""))
06624 #else
06625 #define ambiguous_operator(op, syn) dispatch2(operator_ambiguous, ripper_intern(op), rb_str_new_cstr(syn))
06626 #endif
06627 #define warn_balanced(op, syn) ((void) \
06628     (last_state != EXPR_CLASS && last_state != EXPR_DOT && \
06629      last_state != EXPR_FNAME && last_state != EXPR_ENDFN && \
06630      last_state != EXPR_ENDARG && \
06631      space_seen && !ISSPACE(c) && \
06632      (ambiguous_operator(op, syn), 0)))
06633 
06634 static int
06635 parser_yylex(struct parser_params *parser)
06636 {
06637     register int c;
06638     int space_seen = 0;
06639     int cmd_state;
06640     enum lex_state_e last_state;
06641     rb_encoding *enc;
06642     int mb;
06643 #ifdef RIPPER
06644     int fallthru = FALSE;
06645 #endif
06646 
06647     if (lex_strterm) {
06648         int token;
06649         if (nd_type(lex_strterm) == NODE_HEREDOC) {
06650             token = here_document(lex_strterm);
06651             if (token == tSTRING_END) {
06652                 lex_strterm = 0;
06653                 lex_state = EXPR_END;
06654             }
06655         }
06656         else {
06657             token = parse_string(lex_strterm);
06658             if (token == tSTRING_END || token == tREGEXP_END) {
06659                 rb_gc_force_recycle((VALUE)lex_strterm);
06660                 lex_strterm = 0;
06661                 lex_state = EXPR_END;
06662             }
06663         }
06664         return token;
06665     }
06666     cmd_state = command_start;
06667     command_start = FALSE;
06668   retry:
06669     last_state = lex_state;
06670     switch (c = nextc()) {
06671       case '\0':                /* NUL */
06672       case '\004':              /* ^D */
06673       case '\032':              /* ^Z */
06674       case -1:                  /* end of script. */
06675         return 0;
06676 
06677         /* white spaces */
06678       case ' ': case '\t': case '\f': case '\r':
06679       case '\13': /* '\v' */
06680         space_seen = 1;
06681 #ifdef RIPPER
06682         while ((c = nextc())) {
06683             switch (c) {
06684               case ' ': case '\t': case '\f': case '\r':
06685               case '\13': /* '\v' */
06686                 break;
06687               default:
06688                 goto outofloop;
06689             }
06690         }
06691       outofloop:
06692         pushback(c);
06693         ripper_dispatch_scan_event(parser, tSP);
06694 #endif
06695         goto retry;
06696 
06697       case '#':         /* it's a comment */
06698         /* no magic_comment in shebang line */
06699         if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
06700             if (comment_at_top(parser)) {
06701                 set_file_encoding(parser, lex_p, lex_pend);
06702             }
06703         }
06704         lex_p = lex_pend;
06705 #ifdef RIPPER
06706         ripper_dispatch_scan_event(parser, tCOMMENT);
06707         fallthru = TRUE;
06708 #endif
06709         /* fall through */
06710       case '\n':
06711         switch (lex_state) {
06712           case EXPR_BEG:
06713           case EXPR_FNAME:
06714           case EXPR_DOT:
06715           case EXPR_CLASS:
06716           case EXPR_VALUE:
06717 #ifdef RIPPER
06718             if (!fallthru) {
06719                 ripper_dispatch_scan_event(parser, tIGNORED_NL);
06720             }
06721             fallthru = FALSE;
06722 #endif
06723             goto retry;
06724           default:
06725             break;
06726         }
06727         while ((c = nextc())) {
06728             switch (c) {
06729               case ' ': case '\t': case '\f': case '\r':
06730               case '\13': /* '\v' */
06731                 space_seen = 1;
06732                 break;
06733               case '.': {
06734                   if ((c = nextc()) != '.') {
06735                       pushback(c);
06736                       pushback('.');
06737                       goto retry;
06738                   }
06739               }
06740               default:
06741                 --ruby_sourceline;
06742                 lex_nextline = lex_lastline;
06743               case -1:          /* EOF no decrement*/
06744                 lex_goto_eol(parser);
06745 #ifdef RIPPER
06746                 if (c != -1) {
06747                     parser->tokp = lex_p;
06748                 }
06749 #endif
06750                 goto normal_newline;
06751             }
06752         }
06753       normal_newline:
06754         command_start = TRUE;
06755         lex_state = EXPR_BEG;
06756         return '\n';
06757 
06758       case '*':
06759         if ((c = nextc()) == '*') {
06760             if ((c = nextc()) == '=') {
06761                 set_yylval_id(tPOW);
06762                 lex_state = EXPR_BEG;
06763                 return tOP_ASGN;
06764             }
06765             pushback(c);
06766             c = tPOW;
06767         }
06768         else {
06769             if (c == '=') {
06770                 set_yylval_id('*');
06771                 lex_state = EXPR_BEG;
06772                 return tOP_ASGN;
06773             }
06774             pushback(c);
06775             if (IS_SPCARG(c)) {
06776                 rb_warning0("`*' interpreted as argument prefix");
06777                 c = tSTAR;
06778             }
06779             else if (IS_BEG()) {
06780                 c = tSTAR;
06781             }
06782             else {
06783                 warn_balanced("*", "argument prefix");
06784                 c = '*';
06785             }
06786         }
06787         switch (lex_state) {
06788           case EXPR_FNAME: case EXPR_DOT:
06789             lex_state = EXPR_ARG; break;
06790           default:
06791             lex_state = EXPR_BEG; break;
06792         }
06793         return c;
06794 
06795       case '!':
06796         c = nextc();
06797         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06798             lex_state = EXPR_ARG;
06799             if (c == '@') {
06800                 return '!';
06801             }
06802         }
06803         else {
06804             lex_state = EXPR_BEG;
06805         }
06806         if (c == '=') {
06807             return tNEQ;
06808         }
06809         if (c == '~') {
06810             return tNMATCH;
06811         }
06812         pushback(c);
06813         return '!';
06814 
06815       case '=':
06816         if (was_bol()) {
06817             /* skip embedded rd document */
06818             if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
06819 #ifdef RIPPER
06820                 int first_p = TRUE;
06821 
06822                 lex_goto_eol(parser);
06823                 ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
06824 #endif
06825                 for (;;) {
06826                     lex_goto_eol(parser);
06827 #ifdef RIPPER
06828                     if (!first_p) {
06829                         ripper_dispatch_scan_event(parser, tEMBDOC);
06830                     }
06831                     first_p = FALSE;
06832 #endif
06833                     c = nextc();
06834                     if (c == -1) {
06835                         compile_error(PARSER_ARG "embedded document meets end of file");
06836                         return 0;
06837                     }
06838                     if (c != '=') continue;
06839                     if (strncmp(lex_p, "end", 3) == 0 &&
06840                         (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
06841                         break;
06842                     }
06843                 }
06844                 lex_goto_eol(parser);
06845 #ifdef RIPPER
06846                 ripper_dispatch_scan_event(parser, tEMBDOC_END);
06847 #endif
06848                 goto retry;
06849             }
06850         }
06851 
06852         switch (lex_state) {
06853           case EXPR_FNAME: case EXPR_DOT:
06854             lex_state = EXPR_ARG; break;
06855           default:
06856             lex_state = EXPR_BEG; break;
06857         }
06858         if ((c = nextc()) == '=') {
06859             if ((c = nextc()) == '=') {
06860                 return tEQQ;
06861             }
06862             pushback(c);
06863             return tEQ;
06864         }
06865         if (c == '~') {
06866             return tMATCH;
06867         }
06868         else if (c == '>') {
06869             return tASSOC;
06870         }
06871         pushback(c);
06872         return '=';
06873 
06874       case '<':
06875         last_state = lex_state;
06876         c = nextc();
06877         if (c == '<' &&
06878             lex_state != EXPR_DOT &&
06879             lex_state != EXPR_CLASS &&
06880             !IS_END() &&
06881             (!IS_ARG() || space_seen)) {
06882             int token = heredoc_identifier();
06883             if (token) return token;
06884         }
06885         switch (lex_state) {
06886           case EXPR_FNAME: case EXPR_DOT:
06887             lex_state = EXPR_ARG; break;
06888           default:
06889             lex_state = EXPR_BEG; break;
06890         }
06891         if (c == '=') {
06892             if ((c = nextc()) == '>') {
06893                 return tCMP;
06894             }
06895             pushback(c);
06896             return tLEQ;
06897         }
06898         if (c == '<') {
06899             if ((c = nextc()) == '=') {
06900                 set_yylval_id(tLSHFT);
06901                 lex_state = EXPR_BEG;
06902                 return tOP_ASGN;
06903             }
06904             pushback(c);
06905             warn_balanced("<<", "here document");
06906             return tLSHFT;
06907         }
06908         pushback(c);
06909         return '<';
06910 
06911       case '>':
06912         switch (lex_state) {
06913           case EXPR_FNAME: case EXPR_DOT:
06914             lex_state = EXPR_ARG; break;
06915           default:
06916             lex_state = EXPR_BEG; break;
06917         }
06918         if ((c = nextc()) == '=') {
06919             return tGEQ;
06920         }
06921         if (c == '>') {
06922             if ((c = nextc()) == '=') {
06923                 set_yylval_id(tRSHFT);
06924                 lex_state = EXPR_BEG;
06925                 return tOP_ASGN;
06926             }
06927             pushback(c);
06928             return tRSHFT;
06929         }
06930         pushback(c);
06931         return '>';
06932 
06933       case '"':
06934         lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
06935         return tSTRING_BEG;
06936 
06937       case '`':
06938         if (lex_state == EXPR_FNAME) {
06939             lex_state = EXPR_ENDFN;
06940             return c;
06941         }
06942         if (lex_state == EXPR_DOT) {
06943             if (cmd_state)
06944                 lex_state = EXPR_CMDARG;
06945             else
06946                 lex_state = EXPR_ARG;
06947             return c;
06948         }
06949         lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
06950         return tXSTRING_BEG;
06951 
06952       case '\'':
06953         lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
06954         return tSTRING_BEG;
06955 
06956       case '?':
06957         if (IS_END()) {
06958             lex_state = EXPR_VALUE;
06959             return '?';
06960         }
06961         c = nextc();
06962         if (c == -1) {
06963             compile_error(PARSER_ARG "incomplete character syntax");
06964             return 0;
06965         }
06966         if (rb_enc_isspace(c, parser->enc)) {
06967             if (!IS_ARG()) {
06968                 int c2 = 0;
06969                 switch (c) {
06970                   case ' ':
06971                     c2 = 's';
06972                     break;
06973                   case '\n':
06974                     c2 = 'n';
06975                     break;
06976                   case '\t':
06977                     c2 = 't';
06978                     break;
06979                   case '\v':
06980                     c2 = 'v';
06981                     break;
06982                   case '\r':
06983                     c2 = 'r';
06984                     break;
06985                   case '\f':
06986                     c2 = 'f';
06987                     break;
06988                 }
06989                 if (c2) {
06990                     rb_warnI("invalid character syntax; use ?\\%c", c2);
06991                 }
06992             }
06993           ternary:
06994             pushback(c);
06995             lex_state = EXPR_VALUE;
06996             return '?';
06997         }
06998         newtok();
06999         enc = parser->enc;
07000         if (!parser_isascii()) {
07001             if (tokadd_mbchar(c) == -1) return 0;
07002         }
07003         else if ((rb_enc_isalnum(c, parser->enc) || c == '_') &&
07004                  lex_p < lex_pend && is_identchar(lex_p, lex_pend, parser->enc)) {
07005             goto ternary;
07006         }
07007         else if (c == '\\') {
07008             if (peek('u')) {
07009                 nextc();
07010                 c = parser_tokadd_utf8(parser, &enc, 0, 0, 0);
07011                 if (0x80 <= c) {
07012                     tokaddmbc(c, enc);
07013                 }
07014                 else {
07015                     tokadd(c);
07016                 }
07017             }
07018             else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) {
07019                 nextc();
07020                 if (tokadd_mbchar(c) == -1) return 0;
07021             }
07022             else {
07023                 c = read_escape(0, &enc);
07024                 tokadd(c);
07025             }
07026         }
07027         else {
07028             tokadd(c);
07029         }
07030         tokfix();
07031         set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0));
07032         lex_state = EXPR_END;
07033         return tCHAR;
07034 
07035       case '&':
07036         if ((c = nextc()) == '&') {
07037             lex_state = EXPR_BEG;
07038             if ((c = nextc()) == '=') {
07039                 set_yylval_id(tANDOP);
07040                 lex_state = EXPR_BEG;
07041                 return tOP_ASGN;
07042             }
07043             pushback(c);
07044             return tANDOP;
07045         }
07046         else if (c == '=') {
07047             set_yylval_id('&');
07048             lex_state = EXPR_BEG;
07049             return tOP_ASGN;
07050         }
07051         pushback(c);
07052         if (IS_SPCARG(c)) {
07053             rb_warning0("`&' interpreted as argument prefix");
07054             c = tAMPER;
07055         }
07056         else if (IS_BEG()) {
07057             c = tAMPER;
07058         }
07059         else {
07060             warn_balanced("&", "argument prefix");
07061             c = '&';
07062         }
07063         switch (lex_state) {
07064           case EXPR_FNAME: case EXPR_DOT:
07065             lex_state = EXPR_ARG; break;
07066           default:
07067             lex_state = EXPR_BEG;
07068         }
07069         return c;
07070 
07071       case '|':
07072         if ((c = nextc()) == '|') {
07073             lex_state = EXPR_BEG;
07074             if ((c = nextc()) == '=') {
07075                 set_yylval_id(tOROP);
07076                 lex_state = EXPR_BEG;
07077                 return tOP_ASGN;
07078             }
07079             pushback(c);
07080             return tOROP;
07081         }
07082         if (c == '=') {
07083             set_yylval_id('|');
07084             lex_state = EXPR_BEG;
07085             return tOP_ASGN;
07086         }
07087         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07088             lex_state = EXPR_ARG;
07089         }
07090         else {
07091             lex_state = EXPR_BEG;
07092         }
07093         pushback(c);
07094         return '|';
07095 
07096       case '+':
07097         c = nextc();
07098         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07099             lex_state = EXPR_ARG;
07100             if (c == '@') {
07101                 return tUPLUS;
07102             }
07103             pushback(c);
07104             return '+';
07105         }
07106         if (c == '=') {
07107             set_yylval_id('+');
07108             lex_state = EXPR_BEG;
07109             return tOP_ASGN;
07110         }
07111         if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07112             lex_state = EXPR_BEG;
07113             pushback(c);
07114             if (c != -1 && ISDIGIT(c)) {
07115                 c = '+';
07116                 goto start_num;
07117             }
07118             return tUPLUS;
07119         }
07120         lex_state = EXPR_BEG;
07121         pushback(c);
07122         warn_balanced("+", "unary operator");
07123         return '+';
07124 
07125       case '-':
07126         c = nextc();
07127         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07128             lex_state = EXPR_ARG;
07129             if (c == '@') {
07130                 return tUMINUS;
07131             }
07132             pushback(c);
07133             return '-';
07134         }
07135         if (c == '=') {
07136             set_yylval_id('-');
07137             lex_state = EXPR_BEG;
07138             return tOP_ASGN;
07139         }
07140         if (c == '>') {
07141             lex_state = EXPR_ARG;
07142             return tLAMBDA;
07143         }
07144         if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07145             lex_state = EXPR_BEG;
07146             pushback(c);
07147             if (c != -1 && ISDIGIT(c)) {
07148                 return tUMINUS_NUM;
07149             }
07150             return tUMINUS;
07151         }
07152         lex_state = EXPR_BEG;
07153         pushback(c);
07154         warn_balanced("-", "unary operator");
07155         return '-';
07156 
07157       case '.':
07158         lex_state = EXPR_BEG;
07159         if ((c = nextc()) == '.') {
07160             if ((c = nextc()) == '.') {
07161                 return tDOT3;
07162             }
07163             pushback(c);
07164             return tDOT2;
07165         }
07166         pushback(c);
07167         if (c != -1 && ISDIGIT(c)) {
07168             yyerror("no .<digit> floating literal anymore; put 0 before dot");
07169         }
07170         lex_state = EXPR_DOT;
07171         return '.';
07172 
07173       start_num:
07174       case '0': case '1': case '2': case '3': case '4':
07175       case '5': case '6': case '7': case '8': case '9':
07176         {
07177             int is_float, seen_point, seen_e, nondigit;
07178 
07179             is_float = seen_point = seen_e = nondigit = 0;
07180             lex_state = EXPR_END;
07181             newtok();
07182             if (c == '-' || c == '+') {
07183                 tokadd(c);
07184                 c = nextc();
07185             }
07186             if (c == '0') {
07187 #define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0)
07188                 int start = toklen();
07189                 c = nextc();
07190                 if (c == 'x' || c == 'X') {
07191                     /* hexadecimal */
07192                     c = nextc();
07193                     if (c != -1 && ISXDIGIT(c)) {
07194                         do {
07195                             if (c == '_') {
07196                                 if (nondigit) break;
07197                                 nondigit = c;
07198                                 continue;
07199                             }
07200                             if (!ISXDIGIT(c)) break;
07201                             nondigit = 0;
07202                             tokadd(c);
07203                         } while ((c = nextc()) != -1);
07204                     }
07205                     pushback(c);
07206                     tokfix();
07207                     if (toklen() == start) {
07208                         no_digits();
07209                     }
07210                     else if (nondigit) goto trailing_uc;
07211                     set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE));
07212                     return tINTEGER;
07213                 }
07214                 if (c == 'b' || c == 'B') {
07215                     /* binary */
07216                     c = nextc();
07217                     if (c == '0' || c == '1') {
07218                         do {
07219                             if (c == '_') {
07220                                 if (nondigit) break;
07221                                 nondigit = c;
07222                                 continue;
07223                             }
07224                             if (c != '0' && c != '1') break;
07225                             nondigit = 0;
07226                             tokadd(c);
07227                         } while ((c = nextc()) != -1);
07228                     }
07229                     pushback(c);
07230                     tokfix();
07231                     if (toklen() == start) {
07232                         no_digits();
07233                     }
07234                     else if (nondigit) goto trailing_uc;
07235                     set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE));
07236                     return tINTEGER;
07237                 }
07238                 if (c == 'd' || c == 'D') {
07239                     /* decimal */
07240                     c = nextc();
07241                     if (c != -1 && ISDIGIT(c)) {
07242                         do {
07243                             if (c == '_') {
07244                                 if (nondigit) break;
07245                                 nondigit = c;
07246                                 continue;
07247                             }
07248                             if (!ISDIGIT(c)) break;
07249                             nondigit = 0;
07250                             tokadd(c);
07251                         } while ((c = nextc()) != -1);
07252                     }
07253                     pushback(c);
07254                     tokfix();
07255                     if (toklen() == start) {
07256                         no_digits();
07257                     }
07258                     else if (nondigit) goto trailing_uc;
07259                     set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07260                     return tINTEGER;
07261                 }
07262                 if (c == '_') {
07263                     /* 0_0 */
07264                     goto octal_number;
07265                 }
07266                 if (c == 'o' || c == 'O') {
07267                     /* prefixed octal */
07268                     c = nextc();
07269                     if (c == -1 || c == '_' || !ISDIGIT(c)) {
07270                         no_digits();
07271                     }
07272                 }
07273                 if (c >= '0' && c <= '7') {
07274                     /* octal */
07275                   octal_number:
07276                     do {
07277                         if (c == '_') {
07278                             if (nondigit) break;
07279                             nondigit = c;
07280                             continue;
07281                         }
07282                         if (c < '0' || c > '9') break;
07283                         if (c > '7') goto invalid_octal;
07284                         nondigit = 0;
07285                         tokadd(c);
07286                     } while ((c = nextc()) != -1);
07287                     if (toklen() > start) {
07288                         pushback(c);
07289                         tokfix();
07290                         if (nondigit) goto trailing_uc;
07291                         set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE));
07292                         return tINTEGER;
07293                     }
07294                     if (nondigit) {
07295                         pushback(c);
07296                         goto trailing_uc;
07297                     }
07298                 }
07299                 if (c > '7' && c <= '9') {
07300                   invalid_octal:
07301                     yyerror("Invalid octal digit");
07302                 }
07303                 else if (c == '.' || c == 'e' || c == 'E') {
07304                     tokadd('0');
07305                 }
07306                 else {
07307                     pushback(c);
07308                     set_yylval_literal(INT2FIX(0));
07309                     return tINTEGER;
07310                 }
07311             }
07312 
07313             for (;;) {
07314                 switch (c) {
07315                   case '0': case '1': case '2': case '3': case '4':
07316                   case '5': case '6': case '7': case '8': case '9':
07317                     nondigit = 0;
07318                     tokadd(c);
07319                     break;
07320 
07321                   case '.':
07322                     if (nondigit) goto trailing_uc;
07323                     if (seen_point || seen_e) {
07324                         goto decode_num;
07325                     }
07326                     else {
07327                         int c0 = nextc();
07328                         if (c0 == -1 || !ISDIGIT(c0)) {
07329                             pushback(c0);
07330                             goto decode_num;
07331                         }
07332                         c = c0;
07333                     }
07334                     tokadd('.');
07335                     tokadd(c);
07336                     is_float++;
07337                     seen_point++;
07338                     nondigit = 0;
07339                     break;
07340 
07341                   case 'e':
07342                   case 'E':
07343                     if (nondigit) {
07344                         pushback(c);
07345                         c = nondigit;
07346                         goto decode_num;
07347                     }
07348                     if (seen_e) {
07349                         goto decode_num;
07350                     }
07351                     tokadd(c);
07352                     seen_e++;
07353                     is_float++;
07354                     nondigit = c;
07355                     c = nextc();
07356                     if (c != '-' && c != '+') continue;
07357                     tokadd(c);
07358                     nondigit = c;
07359                     break;
07360 
07361                   case '_':     /* `_' in number just ignored */
07362                     if (nondigit) goto decode_num;
07363                     nondigit = c;
07364                     break;
07365 
07366                   default:
07367                     goto decode_num;
07368                 }
07369                 c = nextc();
07370             }
07371 
07372           decode_num:
07373             pushback(c);
07374             if (nondigit) {
07375                 char tmp[30];
07376               trailing_uc:
07377                 snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit);
07378                 yyerror(tmp);
07379             }
07380             tokfix();
07381             if (is_float) {
07382                 double d = strtod(tok(), 0);
07383                 if (errno == ERANGE) {
07384                     rb_warningS("Float %s out of range", tok());
07385                     errno = 0;
07386                 }
07387                 set_yylval_literal(DBL2NUM(d));
07388                 return tFLOAT;
07389             }
07390             set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07391             return tINTEGER;
07392         }
07393 
07394       case ')':
07395       case ']':
07396         paren_nest--;
07397       case '}':
07398         COND_LEXPOP();
07399         CMDARG_LEXPOP();
07400         if (c == ')')
07401             lex_state = EXPR_ENDFN;
07402         else
07403             lex_state = EXPR_ENDARG;
07404         return c;
07405 
07406       case ':':
07407         c = nextc();
07408         if (c == ':') {
07409             if (IS_BEG() || lex_state == EXPR_CLASS || IS_SPCARG(-1)) {
07410                 lex_state = EXPR_BEG;
07411                 return tCOLON3;
07412             }
07413             lex_state = EXPR_DOT;
07414             return tCOLON2;
07415         }
07416         if (IS_END() || ISSPACE(c)) {
07417             pushback(c);
07418             warn_balanced(":", "symbol literal");
07419             lex_state = EXPR_BEG;
07420             return ':';
07421         }
07422         switch (c) {
07423           case '\'':
07424             lex_strterm = NEW_STRTERM(str_ssym, c, 0);
07425             break;
07426           case '"':
07427             lex_strterm = NEW_STRTERM(str_dsym, c, 0);
07428             break;
07429           default:
07430             pushback(c);
07431             break;
07432         }
07433         lex_state = EXPR_FNAME;
07434         return tSYMBEG;
07435 
07436       case '/':
07437         if (IS_BEG()) {
07438             lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07439             return tREGEXP_BEG;
07440         }
07441         if ((c = nextc()) == '=') {
07442             set_yylval_id('/');
07443             lex_state = EXPR_BEG;
07444             return tOP_ASGN;
07445         }
07446         pushback(c);
07447         if (IS_SPCARG(c)) {
07448             (void)arg_ambiguous();
07449             lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07450             return tREGEXP_BEG;
07451         }
07452         switch (lex_state) {
07453           case EXPR_FNAME: case EXPR_DOT:
07454             lex_state = EXPR_ARG; break;
07455           default:
07456             lex_state = EXPR_BEG; break;
07457         }
07458         warn_balanced("/", "regexp literal");
07459         return '/';
07460 
07461       case '^':
07462         if ((c = nextc()) == '=') {
07463             set_yylval_id('^');
07464             lex_state = EXPR_BEG;
07465             return tOP_ASGN;
07466         }
07467         switch (lex_state) {
07468           case EXPR_FNAME: case EXPR_DOT:
07469             lex_state = EXPR_ARG; break;
07470           default:
07471             lex_state = EXPR_BEG; break;
07472         }
07473         pushback(c);
07474         return '^';
07475 
07476       case ';':
07477         lex_state = EXPR_BEG;
07478         command_start = TRUE;
07479         return ';';
07480 
07481       case ',':
07482         lex_state = EXPR_BEG;
07483         return ',';
07484 
07485       case '~':
07486         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07487             if ((c = nextc()) != '@') {
07488                 pushback(c);
07489             }
07490             lex_state = EXPR_ARG;
07491         }
07492         else {
07493             lex_state = EXPR_BEG;
07494         }
07495         return '~';
07496 
07497       case '(':
07498         if (IS_BEG()) {
07499             c = tLPAREN;
07500         }
07501         else if (IS_SPCARG(-1)) {
07502             c = tLPAREN_ARG;
07503         }
07504         paren_nest++;
07505         COND_PUSH(0);
07506         CMDARG_PUSH(0);
07507         lex_state = EXPR_BEG;
07508         return c;
07509 
07510       case '[':
07511         paren_nest++;
07512         if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07513             lex_state = EXPR_ARG;
07514             if ((c = nextc()) == ']') {
07515                 if ((c = nextc()) == '=') {
07516                     return tASET;
07517                 }
07518                 pushback(c);
07519                 return tAREF;
07520             }
07521             pushback(c);
07522             return '[';
07523         }
07524         else if (IS_BEG()) {
07525             c = tLBRACK;
07526         }
07527         else if (IS_ARG() && space_seen) {
07528             c = tLBRACK;
07529         }
07530         lex_state = EXPR_BEG;
07531         COND_PUSH(0);
07532         CMDARG_PUSH(0);
07533         return c;
07534 
07535       case '{':
07536         if (lpar_beg && lpar_beg == paren_nest) {
07537             lex_state = EXPR_BEG;
07538             lpar_beg = 0;
07539             --paren_nest;
07540             COND_PUSH(0);
07541             CMDARG_PUSH(0);
07542             return tLAMBEG;
07543         }
07544         if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_ENDFN)
07545             c = '{';          /* block (primary) */
07546         else if (lex_state == EXPR_ENDARG)
07547             c = tLBRACE_ARG;  /* block (expr) */
07548         else
07549             c = tLBRACE;      /* hash */
07550         COND_PUSH(0);
07551         CMDARG_PUSH(0);
07552         lex_state = EXPR_BEG;
07553         if (c != tLBRACE) command_start = TRUE;
07554         return c;
07555 
07556       case '\\':
07557         c = nextc();
07558         if (c == '\n') {
07559             space_seen = 1;
07560 #ifdef RIPPER
07561             ripper_dispatch_scan_event(parser, tSP);
07562 #endif
07563             goto retry; /* skip \\n */
07564         }
07565         pushback(c);
07566         return '\\';
07567 
07568       case '%':
07569         if (IS_BEG()) {
07570             int term;
07571             int paren;
07572 
07573             c = nextc();
07574           quotation:
07575             if (c == -1 || !ISALNUM(c)) {
07576                 term = c;
07577                 c = 'Q';
07578             }
07579             else {
07580                 term = nextc();
07581                 if (rb_enc_isalnum(term, parser->enc) || !parser_isascii()) {
07582                     yyerror("unknown type of %string");
07583                     return 0;
07584                 }
07585             }
07586             if (c == -1 || term == -1) {
07587                 compile_error(PARSER_ARG "unterminated quoted string meets end of file");
07588                 return 0;
07589             }
07590             paren = term;
07591             if (term == '(') term = ')';
07592             else if (term == '[') term = ']';
07593             else if (term == '{') term = '}';
07594             else if (term == '<') term = '>';
07595             else paren = 0;
07596 
07597             switch (c) {
07598               case 'Q':
07599                 lex_strterm = NEW_STRTERM(str_dquote, term, paren);
07600                 return tSTRING_BEG;
07601 
07602               case 'q':
07603                 lex_strterm = NEW_STRTERM(str_squote, term, paren);
07604                 return tSTRING_BEG;
07605 
07606               case 'W':
07607                 lex_strterm = NEW_STRTERM(str_dword, term, paren);
07608                 do {c = nextc();} while (ISSPACE(c));
07609                 pushback(c);
07610                 return tWORDS_BEG;
07611 
07612               case 'w':
07613                 lex_strterm = NEW_STRTERM(str_sword, term, paren);
07614                 do {c = nextc();} while (ISSPACE(c));
07615                 pushback(c);
07616                 return tQWORDS_BEG;
07617 
07618               case 'x':
07619                 lex_strterm = NEW_STRTERM(str_xquote, term, paren);
07620                 return tXSTRING_BEG;
07621 
07622               case 'r':
07623                 lex_strterm = NEW_STRTERM(str_regexp, term, paren);
07624                 return tREGEXP_BEG;
07625 
07626               case 's':
07627                 lex_strterm = NEW_STRTERM(str_ssym, term, paren);
07628                 lex_state = EXPR_FNAME;
07629                 return tSYMBEG;
07630 
07631               default:
07632                 yyerror("unknown type of %string");
07633                 return 0;
07634             }
07635         }
07636         if ((c = nextc()) == '=') {
07637             set_yylval_id('%');
07638             lex_state = EXPR_BEG;
07639             return tOP_ASGN;
07640         }
07641         if (IS_SPCARG(c)) {
07642             goto quotation;
07643         }
07644         switch (lex_state) {
07645           case EXPR_FNAME: case EXPR_DOT:
07646             lex_state = EXPR_ARG; break;
07647           default:
07648             lex_state = EXPR_BEG; break;
07649         }
07650         pushback(c);
07651         warn_balanced("%%", "string literal");
07652         return '%';
07653 
07654       case '$':
07655         lex_state = EXPR_END;
07656         newtok();
07657         c = nextc();
07658         switch (c) {
07659           case '_':             /* $_: last read line string */
07660             c = nextc();
07661             if (parser_is_identchar()) {
07662                 tokadd('$');
07663                 tokadd('_');
07664                 break;
07665             }
07666             pushback(c);
07667             c = '_';
07668             /* fall through */
07669           case '~':             /* $~: match-data */
07670           case '*':             /* $*: argv */
07671           case '$':             /* $$: pid */
07672           case '?':             /* $?: last status */
07673           case '!':             /* $!: error string */
07674           case '@':             /* $@: error position */
07675           case '/':             /* $/: input record separator */
07676           case '\\':            /* $\: output record separator */
07677           case ';':             /* $;: field separator */
07678           case ',':             /* $,: output field separator */
07679           case '.':             /* $.: last read line number */
07680           case '=':             /* $=: ignorecase */
07681           case ':':             /* $:: load path */
07682           case '<':             /* $<: reading filename */
07683           case '>':             /* $>: default output handle */
07684           case '\"':            /* $": already loaded files */
07685             tokadd('$');
07686             tokadd(c);
07687             tokfix();
07688             set_yylval_name(rb_intern(tok()));
07689             return tGVAR;
07690 
07691           case '-':
07692             tokadd('$');
07693             tokadd(c);
07694             c = nextc();
07695             if (parser_is_identchar()) {
07696                 if (tokadd_mbchar(c) == -1) return 0;
07697             }
07698             else {
07699                 pushback(c);
07700             }
07701           gvar:
07702             tokfix();
07703             set_yylval_name(rb_intern(tok()));
07704             return tGVAR;
07705 
07706           case '&':             /* $&: last match */
07707           case '`':             /* $`: string before last match */
07708           case '\'':            /* $': string after last match */
07709           case '+':             /* $+: string matches last paren. */
07710             if (last_state == EXPR_FNAME) {
07711                 tokadd('$');
07712                 tokadd(c);
07713                 goto gvar;
07714             }
07715             set_yylval_node(NEW_BACK_REF(c));
07716             return tBACK_REF;
07717 
07718           case '1': case '2': case '3':
07719           case '4': case '5': case '6':
07720           case '7': case '8': case '9':
07721             tokadd('$');
07722             do {
07723                 tokadd(c);
07724                 c = nextc();
07725             } while (c != -1 && ISDIGIT(c));
07726             pushback(c);
07727             if (last_state == EXPR_FNAME) goto gvar;
07728             tokfix();
07729             set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
07730             return tNTH_REF;
07731 
07732           default:
07733             if (!parser_is_identchar()) {
07734                 pushback(c);
07735                 return '$';
07736             }
07737           case '0':
07738             tokadd('$');
07739         }
07740         break;
07741 
07742       case '@':
07743         c = nextc();
07744         newtok();
07745         tokadd('@');
07746         if (c == '@') {
07747             tokadd('@');
07748             c = nextc();
07749         }
07750         if (c != -1 && ISDIGIT(c)) {
07751             if (tokidx == 1) {
07752                 compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
07753             }
07754             else {
07755                 compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
07756             }
07757             return 0;
07758         }
07759         if (!parser_is_identchar()) {
07760             pushback(c);
07761             return '@';
07762         }
07763         break;
07764 
07765       case '_':
07766         if (was_bol() && whole_match_p("__END__", 7, 0)) {
07767             ruby__end__seen = 1;
07768             parser->eofp = Qtrue;
07769 #ifndef RIPPER
07770             return -1;
07771 #else
07772             lex_goto_eol(parser);
07773             ripper_dispatch_scan_event(parser, k__END__);
07774             return 0;
07775 #endif
07776         }
07777         newtok();
07778         break;
07779 
07780       default:
07781         if (!parser_is_identchar()) {
07782             rb_compile_error(PARSER_ARG  "Invalid char `\\x%02X' in expression", c);
07783             goto retry;
07784         }
07785 
07786         newtok();
07787         break;
07788     }
07789 
07790     mb = ENC_CODERANGE_7BIT;
07791     do {
07792         if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
07793         if (tokadd_mbchar(c) == -1) return 0;
07794         c = nextc();
07795     } while (parser_is_identchar());
07796     switch (tok()[0]) {
07797       case '@': case '$':
07798         pushback(c);
07799         break;
07800       default:
07801         if ((c == '!' || c == '?') && !peek('=')) {
07802             tokadd(c);
07803         }
07804         else {
07805             pushback(c);
07806         }
07807     }
07808     tokfix();
07809 
07810     {
07811         int result = 0;
07812 
07813         last_state = lex_state;
07814         switch (tok()[0]) {
07815           case '$':
07816             lex_state = EXPR_END;
07817             result = tGVAR;
07818             break;
07819           case '@':
07820             lex_state = EXPR_END;
07821             if (tok()[1] == '@')
07822                 result = tCVAR;
07823             else
07824                 result = tIVAR;
07825             break;
07826 
07827           default:
07828             if (toklast() == '!' || toklast() == '?') {
07829                 result = tFID;
07830             }
07831             else {
07832                 if (lex_state == EXPR_FNAME) {
07833                     if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
07834                         (!peek('=') || (peek_n('>', 1)))) {
07835                         result = tIDENTIFIER;
07836                         tokadd(c);
07837                         tokfix();
07838                     }
07839                     else {
07840                         pushback(c);
07841                     }
07842                 }
07843                 if (result == 0 && ISUPPER(tok()[0])) {
07844                     result = tCONSTANT;
07845                 }
07846                 else {
07847                     result = tIDENTIFIER;
07848                 }
07849             }
07850 
07851             if (IS_LABEL_POSSIBLE()) {
07852                 if (IS_LABEL_SUFFIX(0)) {
07853                     lex_state = EXPR_BEG;
07854                     nextc();
07855                     set_yylval_name(TOK_INTERN(!ENC_SINGLE(mb)));
07856                     return tLABEL;
07857                 }
07858             }
07859             if (mb == ENC_CODERANGE_7BIT && lex_state != EXPR_DOT) {
07860                 const struct kwtable *kw;
07861 
07862                 /* See if it is a reserved word.  */
07863                 kw = rb_reserved_word(tok(), toklen());
07864                 if (kw) {
07865                     enum lex_state_e state = lex_state;
07866                     lex_state = kw->state;
07867                     if (state == EXPR_FNAME) {
07868                         set_yylval_name(rb_intern(kw->name));
07869                         return kw->id[0];
07870                     }
07871                     if (kw->id[0] == keyword_do) {
07872                         command_start = TRUE;
07873                         if (lpar_beg && lpar_beg == paren_nest) {
07874                             lpar_beg = 0;
07875                             --paren_nest;
07876                             return keyword_do_LAMBDA;
07877                         }
07878                         if (COND_P()) return keyword_do_cond;
07879                         if (CMDARG_P() && state != EXPR_CMDARG)
07880                             return keyword_do_block;
07881                         if (state == EXPR_ENDARG || state == EXPR_BEG)
07882                             return keyword_do_block;
07883                         return keyword_do;
07884                     }
07885                     if (state == EXPR_BEG || state == EXPR_VALUE)
07886                         return kw->id[0];
07887                     else {
07888                         if (kw->id[0] != kw->id[1])
07889                             lex_state = EXPR_BEG;
07890                         return kw->id[1];
07891                     }
07892                 }
07893             }
07894 
07895             if (IS_BEG() ||
07896                 lex_state == EXPR_DOT ||
07897                 IS_ARG()) {
07898                 if (cmd_state) {
07899                     lex_state = EXPR_CMDARG;
07900                 }
07901                 else {
07902                     lex_state = EXPR_ARG;
07903                 }
07904             }
07905             else if (lex_state == EXPR_FNAME) {
07906                 lex_state = EXPR_ENDFN;
07907             }
07908             else {
07909                 lex_state = EXPR_END;
07910             }
07911         }
07912         {
07913             ID ident = TOK_INTERN(!ENC_SINGLE(mb));
07914 
07915             set_yylval_name(ident);
07916             if (last_state != EXPR_DOT && is_local_id(ident) && lvar_defined(ident)) {
07917                 lex_state = EXPR_END;
07918             }
07919         }
07920         return result;
07921     }
07922 }
07923 
07924 #if YYPURE
07925 static int
07926 yylex(void *lval, void *p)
07927 #else
07928 yylex(void *p)
07929 #endif
07930 {
07931     struct parser_params *parser = (struct parser_params*)p;
07932     int t;
07933 
07934 #if YYPURE
07935     parser->parser_yylval = lval;
07936     parser->parser_yylval->val = Qundef;
07937 #endif
07938     t = parser_yylex(parser);
07939 #ifdef RIPPER
07940     if (!NIL_P(parser->delayed)) {
07941         ripper_dispatch_delayed_token(parser, t);
07942         return t;
07943     }
07944     if (t != 0)
07945         ripper_dispatch_scan_event(parser, t);
07946 #endif
07947 
07948     return t;
07949 }
07950 
07951 #ifndef RIPPER
07952 static NODE*
07953 node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
07954 {
07955     NODE *n = (rb_node_newnode)(type, a0, a1, a2);
07956     nd_set_line(n, ruby_sourceline);
07957     return n;
07958 }
07959 
07960 enum node_type
07961 nodetype(NODE *node)                    /* for debug */
07962 {
07963     return (enum node_type)nd_type(node);
07964 }
07965 
07966 int
07967 nodeline(NODE *node)
07968 {
07969     return nd_line(node);
07970 }
07971 
07972 static NODE*
07973 newline_node(NODE *node)
07974 {
07975     if (node) {
07976         node = remove_begin(node);
07977         node->flags |= NODE_FL_NEWLINE;
07978     }
07979     return node;
07980 }
07981 
07982 static void
07983 fixpos(NODE *node, NODE *orig)
07984 {
07985     if (!node) return;
07986     if (!orig) return;
07987     if (orig == (NODE*)1) return;
07988     nd_set_line(node, nd_line(orig));
07989 }
07990 
07991 static void
07992 parser_warning(struct parser_params *parser, NODE *node, const char *mesg)
07993 {
07994     rb_compile_warning(ruby_sourcefile, nd_line(node), "%s", mesg);
07995 }
07996 #define parser_warning(node, mesg) parser_warning(parser, (node), (mesg))
07997 
07998 static void
07999 parser_warn(struct parser_params *parser, NODE *node, const char *mesg)
08000 {
08001     rb_compile_warn(ruby_sourcefile, nd_line(node), "%s", mesg);
08002 }
08003 #define parser_warn(node, mesg) parser_warn(parser, (node), (mesg))
08004 
08005 static NODE*
08006 block_append_gen(struct parser_params *parser, NODE *head, NODE *tail)
08007 {
08008     NODE *end, *h = head, *nd;
08009 
08010     if (tail == 0) return head;
08011 
08012     if (h == 0) return tail;
08013     switch (nd_type(h)) {
08014       case NODE_LIT:
08015       case NODE_STR:
08016       case NODE_SELF:
08017       case NODE_TRUE:
08018       case NODE_FALSE:
08019       case NODE_NIL:
08020         parser_warning(h, "unused literal ignored");
08021         return tail;
08022       default:
08023         h = end = NEW_BLOCK(head);
08024         end->nd_end = end;
08025         fixpos(end, head);
08026         head = end;
08027         break;
08028       case NODE_BLOCK:
08029         end = h->nd_end;
08030         break;
08031     }
08032 
08033     nd = end->nd_head;
08034     switch (nd_type(nd)) {
08035       case NODE_RETURN:
08036       case NODE_BREAK:
08037       case NODE_NEXT:
08038       case NODE_REDO:
08039       case NODE_RETRY:
08040         if (RTEST(ruby_verbose)) {
08041             parser_warning(nd, "statement not reached");
08042         }
08043         break;
08044 
08045       default:
08046         break;
08047     }
08048 
08049     if (nd_type(tail) != NODE_BLOCK) {
08050         tail = NEW_BLOCK(tail);
08051         tail->nd_end = tail;
08052     }
08053     end->nd_next = tail;
08054     h->nd_end = tail->nd_end;
08055     return head;
08056 }
08057 
08058 /* append item to the list */
08059 static NODE*
08060 list_append_gen(struct parser_params *parser, NODE *list, NODE *item)
08061 {
08062     NODE *last;
08063 
08064     if (list == 0) return NEW_LIST(item);
08065     if (list->nd_next) {
08066         last = list->nd_next->nd_end;
08067     }
08068     else {
08069         last = list;
08070     }
08071 
08072     list->nd_alen += 1;
08073     last->nd_next = NEW_LIST(item);
08074     list->nd_next->nd_end = last->nd_next;
08075     return list;
08076 }
08077 
08078 /* concat two lists */
08079 static NODE*
08080 list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08081 {
08082     NODE *last;
08083 
08084     if (head->nd_next) {
08085         last = head->nd_next->nd_end;
08086     }
08087     else {
08088         last = head;
08089     }
08090 
08091     head->nd_alen += tail->nd_alen;
08092     last->nd_next = tail;
08093     if (tail->nd_next) {
08094         head->nd_next->nd_end = tail->nd_next->nd_end;
08095     }
08096     else {
08097         head->nd_next->nd_end = tail;
08098     }
08099 
08100     return head;
08101 }
08102 
08103 static int
08104 literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
08105 {
08106     if (NIL_P(tail)) return 1;
08107     if (!rb_enc_compatible(head, tail)) {
08108         compile_error(PARSER_ARG "string literal encodings differ (%s / %s)",
08109                       rb_enc_name(rb_enc_get(head)),
08110                       rb_enc_name(rb_enc_get(tail)));
08111         rb_str_resize(head, 0);
08112         rb_str_resize(tail, 0);
08113         return 0;
08114     }
08115     rb_str_buf_append(head, tail);
08116     return 1;
08117 }
08118 
08119 /* concat two string literals */
08120 static NODE *
08121 literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08122 {
08123     enum node_type htype;
08124 
08125     if (!head) return tail;
08126     if (!tail) return head;
08127 
08128     htype = nd_type(head);
08129     if (htype == NODE_EVSTR) {
08130         NODE *node = NEW_DSTR(Qnil);
08131         head = list_append(node, head);
08132     }
08133     switch (nd_type(tail)) {
08134       case NODE_STR:
08135         if (htype == NODE_STR) {
08136             if (!literal_concat0(parser, head->nd_lit, tail->nd_lit)) {
08137               error:
08138                 rb_gc_force_recycle((VALUE)head);
08139                 rb_gc_force_recycle((VALUE)tail);
08140                 return 0;
08141             }
08142             rb_gc_force_recycle((VALUE)tail);
08143         }
08144         else {
08145             list_append(head, tail);
08146         }
08147         break;
08148 
08149       case NODE_DSTR:
08150         if (htype == NODE_STR) {
08151             if (!literal_concat0(parser, head->nd_lit, tail->nd_lit))
08152                 goto error;
08153             tail->nd_lit = head->nd_lit;
08154             rb_gc_force_recycle((VALUE)head);
08155             head = tail;
08156         }
08157         else if (NIL_P(tail->nd_lit)) {
08158             head->nd_alen += tail->nd_alen - 1;
08159             head->nd_next->nd_end->nd_next = tail->nd_next;
08160             head->nd_next->nd_end = tail->nd_next->nd_end;
08161             rb_gc_force_recycle((VALUE)tail);
08162         }
08163         else {
08164             nd_set_type(tail, NODE_ARRAY);
08165             tail->nd_head = NEW_STR(tail->nd_lit);
08166             list_concat(head, tail);
08167         }
08168         break;
08169 
08170       case NODE_EVSTR:
08171         if (htype == NODE_STR) {
08172             nd_set_type(head, NODE_DSTR);
08173             head->nd_alen = 1;
08174         }
08175         list_append(head, tail);
08176         break;
08177     }
08178     return head;
08179 }
08180 
08181 static NODE *
08182 evstr2dstr_gen(struct parser_params *parser, NODE *node)
08183 {
08184     if (nd_type(node) == NODE_EVSTR) {
08185         node = list_append(NEW_DSTR(Qnil), node);
08186     }
08187     return node;
08188 }
08189 
08190 static NODE *
08191 new_evstr_gen(struct parser_params *parser, NODE *node)
08192 {
08193     NODE *head = node;
08194 
08195     if (node) {
08196         switch (nd_type(node)) {
08197           case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
08198             return node;
08199         }
08200     }
08201     return NEW_EVSTR(head);
08202 }
08203 
08204 static NODE *
08205 call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
08206 {
08207     value_expr(recv);
08208     value_expr(arg1);
08209     return NEW_CALL(recv, id, NEW_LIST(arg1));
08210 }
08211 
08212 static NODE *
08213 call_uni_op_gen(struct parser_params *parser, NODE *recv, ID id)
08214 {
08215     value_expr(recv);
08216     return NEW_CALL(recv, id, 0);
08217 }
08218 
08219 static NODE*
08220 match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08221 {
08222     value_expr(node1);
08223     value_expr(node2);
08224     if (node1) {
08225         switch (nd_type(node1)) {
08226           case NODE_DREGX:
08227           case NODE_DREGX_ONCE:
08228             return NEW_MATCH2(node1, node2);
08229 
08230           case NODE_LIT:
08231             if (TYPE(node1->nd_lit) == T_REGEXP) {
08232                 return NEW_MATCH2(node1, node2);
08233             }
08234         }
08235     }
08236 
08237     if (node2) {
08238         switch (nd_type(node2)) {
08239           case NODE_DREGX:
08240           case NODE_DREGX_ONCE:
08241             return NEW_MATCH3(node2, node1);
08242 
08243           case NODE_LIT:
08244             if (TYPE(node2->nd_lit) == T_REGEXP) {
08245                 return NEW_MATCH3(node2, node1);
08246             }
08247         }
08248     }
08249 
08250     return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
08251 }
08252 
08253 static NODE*
08254 gettable_gen(struct parser_params *parser, ID id)
08255 {
08256     if (id == keyword_self) {
08257         return NEW_SELF();
08258     }
08259     else if (id == keyword_nil) {
08260         return NEW_NIL();
08261     }
08262     else if (id == keyword_true) {
08263         return NEW_TRUE();
08264     }
08265     else if (id == keyword_false) {
08266         return NEW_FALSE();
08267     }
08268     else if (id == keyword__FILE__) {
08269         return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile),
08270                                                     rb_filesystem_encoding()));
08271     }
08272     else if (id == keyword__LINE__) {
08273         return NEW_LIT(INT2FIX(ruby_sourceline));
08274     }
08275     else if (id == keyword__ENCODING__) {
08276         return NEW_LIT(rb_enc_from_encoding(parser->enc));
08277     }
08278     else if (is_local_id(id)) {
08279         if (dyna_in_block() && dvar_defined(id)) return NEW_DVAR(id);
08280         if (local_id(id)) return NEW_LVAR(id);
08281         /* method call without arguments */
08282         return NEW_VCALL(id);
08283     }
08284     else if (is_global_id(id)) {
08285         return NEW_GVAR(id);
08286     }
08287     else if (is_instance_id(id)) {
08288         return NEW_IVAR(id);
08289     }
08290     else if (is_const_id(id)) {
08291         return NEW_CONST(id);
08292     }
08293     else if (is_class_id(id)) {
08294         return NEW_CVAR(id);
08295     }
08296     compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08297     return 0;
08298 }
08299 #else  /* !RIPPER */
08300 static int
08301 id_is_var_gen(struct parser_params *parser, ID id)
08302 {
08303     if (is_notop_id(id)) {
08304         switch (id & ID_SCOPE_MASK) {
08305           case ID_GLOBAL: case ID_INSTANCE: case ID_CONST: case ID_CLASS:
08306             return 1;
08307           case ID_LOCAL:
08308             if (dyna_in_block() && dvar_defined(id)) return 1;
08309             if (local_id(id)) return 1;
08310             /* method call without arguments */
08311             return 0;
08312         }
08313     }
08314     compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08315     return 0;
08316 }
08317 #endif /* !RIPPER */
08318 
08319 #ifdef RIPPER
08320 static VALUE
08321 assignable_gen(struct parser_params *parser, VALUE lhs)
08322 #else
08323 static NODE*
08324 assignable_gen(struct parser_params *parser, ID id, NODE *val)
08325 #endif
08326 {
08327 #ifdef RIPPER
08328     ID id = get_id(lhs);
08329 # define assignable_result(x) get_value(lhs)
08330 # define parser_yyerror(parser, x) dispatch1(assign_error, lhs)
08331 #else
08332 # define assignable_result(x) (x)
08333 #endif
08334     if (!id) return assignable_result(0);
08335     if (id == keyword_self) {
08336         yyerror("Can't change the value of self");
08337     }
08338     else if (id == keyword_nil) {
08339         yyerror("Can't assign to nil");
08340     }
08341     else if (id == keyword_true) {
08342         yyerror("Can't assign to true");
08343     }
08344     else if (id == keyword_false) {
08345         yyerror("Can't assign to false");
08346     }
08347     else if (id == keyword__FILE__) {
08348         yyerror("Can't assign to __FILE__");
08349     }
08350     else if (id == keyword__LINE__) {
08351         yyerror("Can't assign to __LINE__");
08352     }
08353     else if (id == keyword__ENCODING__) {
08354         yyerror("Can't assign to __ENCODING__");
08355     }
08356     else if (is_local_id(id)) {
08357         if (dyna_in_block()) {
08358             if (dvar_curr(id)) {
08359                 return assignable_result(NEW_DASGN_CURR(id, val));
08360             }
08361             else if (dvar_defined(id)) {
08362                 return assignable_result(NEW_DASGN(id, val));
08363             }
08364             else if (local_id(id)) {
08365                 return assignable_result(NEW_LASGN(id, val));
08366             }
08367             else {
08368                 dyna_var(id);
08369                 return assignable_result(NEW_DASGN_CURR(id, val));
08370             }
08371         }
08372         else {
08373             if (!local_id(id)) {
08374                 local_var(id);
08375             }
08376             return assignable_result(NEW_LASGN(id, val));
08377         }
08378     }
08379     else if (is_global_id(id)) {
08380         return assignable_result(NEW_GASGN(id, val));
08381     }
08382     else if (is_instance_id(id)) {
08383         return assignable_result(NEW_IASGN(id, val));
08384     }
08385     else if (is_const_id(id)) {
08386         if (!in_def && !in_single)
08387             return assignable_result(NEW_CDECL(id, val, 0));
08388         yyerror("dynamic constant assignment");
08389     }
08390     else if (is_class_id(id)) {
08391         return assignable_result(NEW_CVASGN(id, val));
08392     }
08393     else {
08394         compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
08395     }
08396     return assignable_result(0);
08397 #undef assignable_result
08398 #undef parser_yyerror
08399 }
08400 
08401 #define LVAR_USED ((int)1 << (sizeof(int) * CHAR_BIT - 1))
08402 
08403 static ID
08404 shadowing_lvar_gen(struct parser_params *parser, ID name)
08405 {
08406     if (idUScore == name) return name;
08407     if (dyna_in_block()) {
08408         if (dvar_curr(name)) {
08409             yyerror("duplicated argument name");
08410         }
08411         else if (dvar_defined_get(name) || local_id(name)) {
08412             rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
08413             vtable_add(lvtbl->vars, name);
08414             if (lvtbl->used) {
08415                 vtable_add(lvtbl->used, (ID)ruby_sourceline | LVAR_USED);
08416             }
08417         }
08418     }
08419     else {
08420         if (local_id(name)) {
08421             yyerror("duplicated argument name");
08422         }
08423     }
08424     return name;
08425 }
08426 
08427 static void
08428 new_bv_gen(struct parser_params *parser, ID name)
08429 {
08430     if (!name) return;
08431     if (!is_local_id(name)) {
08432         compile_error(PARSER_ARG "invalid local variable - %s",
08433                       rb_id2name(name));
08434         return;
08435     }
08436     shadowing_lvar(name);
08437     dyna_var(name);
08438 }
08439 
08440 #ifndef RIPPER
08441 static NODE *
08442 aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
08443 {
08444     if (recv && nd_type(recv) == NODE_SELF)
08445         recv = (NODE *)1;
08446     return NEW_ATTRASGN(recv, tASET, idx);
08447 }
08448 
08449 static void
08450 block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08451 {
08452     if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
08453         compile_error(PARSER_ARG "both block arg and actual block given");
08454     }
08455 }
08456 
08457 ID
08458 rb_id_attrset(ID id)
08459 {
08460     id &= ~ID_SCOPE_MASK;
08461     id |= ID_ATTRSET;
08462     return id;
08463 }
08464 
08465 static NODE *
08466 attrset_gen(struct parser_params *parser, NODE *recv, ID id)
08467 {
08468     if (recv && nd_type(recv) == NODE_SELF)
08469         recv = (NODE *)1;
08470     return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
08471 }
08472 
08473 static void
08474 rb_backref_error_gen(struct parser_params *parser, NODE *node)
08475 {
08476     switch (nd_type(node)) {
08477       case NODE_NTH_REF:
08478         compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth);
08479         break;
08480       case NODE_BACK_REF:
08481         compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth);
08482         break;
08483     }
08484 }
08485 
08486 static NODE *
08487 arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08488 {
08489     if (!node2) return node1;
08490     switch (nd_type(node1)) {
08491       case NODE_BLOCK_PASS:
08492         if (node1->nd_head)
08493             node1->nd_head = arg_concat(node1->nd_head, node2);
08494         else
08495             node1->nd_head = NEW_LIST(node2);
08496         return node1;
08497       case NODE_ARGSPUSH:
08498         if (nd_type(node2) != NODE_ARRAY) break;
08499         node1->nd_body = list_concat(NEW_LIST(node1->nd_body), node2);
08500         nd_set_type(node1, NODE_ARGSCAT);
08501         return node1;
08502       case NODE_ARGSCAT:
08503         if (nd_type(node2) != NODE_ARRAY ||
08504             nd_type(node1->nd_body) != NODE_ARRAY) break;
08505         node1->nd_body = list_concat(node1->nd_body, node2);
08506         return node1;
08507     }
08508     return NEW_ARGSCAT(node1, node2);
08509 }
08510 
08511 static NODE *
08512 arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08513 {
08514     if (!node1) return NEW_LIST(node2);
08515     switch (nd_type(node1))  {
08516       case NODE_ARRAY:
08517         return list_append(node1, node2);
08518       case NODE_BLOCK_PASS:
08519         node1->nd_head = arg_append(node1->nd_head, node2);
08520         return node1;
08521       case NODE_ARGSPUSH:
08522         node1->nd_body = list_append(NEW_LIST(node1->nd_body), node2);
08523         nd_set_type(node1, NODE_ARGSCAT);
08524         return node1;
08525     }
08526     return NEW_ARGSPUSH(node1, node2);
08527 }
08528 
08529 static NODE *
08530 splat_array(NODE* node)
08531 {
08532     if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
08533     if (nd_type(node) == NODE_ARRAY) return node;
08534     return 0;
08535 }
08536 
08537 static NODE *
08538 node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
08539 {
08540     if (!lhs) return 0;
08541 
08542     switch (nd_type(lhs)) {
08543       case NODE_GASGN:
08544       case NODE_IASGN:
08545       case NODE_IASGN2:
08546       case NODE_LASGN:
08547       case NODE_DASGN:
08548       case NODE_DASGN_CURR:
08549       case NODE_MASGN:
08550       case NODE_CDECL:
08551       case NODE_CVASGN:
08552         lhs->nd_value = rhs;
08553         break;
08554 
08555       case NODE_ATTRASGN:
08556       case NODE_CALL:
08557         lhs->nd_args = arg_append(lhs->nd_args, rhs);
08558         break;
08559 
08560       default:
08561         /* should not happen */
08562         break;
08563     }
08564 
08565     return lhs;
08566 }
08567 
08568 static int
08569 value_expr_gen(struct parser_params *parser, NODE *node)
08570 {
08571     int cond = 0;
08572 
08573     if (!node) {
08574         rb_warning0("empty expression");
08575     }
08576     while (node) {
08577         switch (nd_type(node)) {
08578           case NODE_DEFN:
08579           case NODE_DEFS:
08580             parser_warning(node, "void value expression");
08581             return FALSE;
08582 
08583           case NODE_RETURN:
08584           case NODE_BREAK:
08585           case NODE_NEXT:
08586           case NODE_REDO:
08587           case NODE_RETRY:
08588             if (!cond) yyerror("void value expression");
08589             /* or "control never reach"? */
08590             return FALSE;
08591 
08592           case NODE_BLOCK:
08593             while (node->nd_next) {
08594                 node = node->nd_next;
08595             }
08596             node = node->nd_head;
08597             break;
08598 
08599           case NODE_BEGIN:
08600             node = node->nd_body;
08601             break;
08602 
08603           case NODE_IF:
08604             if (!node->nd_body) {
08605                 node = node->nd_else;
08606                 break;
08607             }
08608             else if (!node->nd_else) {
08609                 node = node->nd_body;
08610                 break;
08611             }
08612             if (!value_expr(node->nd_body)) return FALSE;
08613             node = node->nd_else;
08614             break;
08615 
08616           case NODE_AND:
08617           case NODE_OR:
08618             cond = 1;
08619             node = node->nd_2nd;
08620             break;
08621 
08622           default:
08623             return TRUE;
08624         }
08625     }
08626 
08627     return TRUE;
08628 }
08629 
08630 static void
08631 void_expr_gen(struct parser_params *parser, NODE *node)
08632 {
08633     const char *useless = 0;
08634 
08635     if (!RTEST(ruby_verbose)) return;
08636 
08637     if (!node) return;
08638     switch (nd_type(node)) {
08639       case NODE_CALL:
08640         switch (node->nd_mid) {
08641           case '+':
08642           case '-':
08643           case '*':
08644           case '/':
08645           case '%':
08646           case tPOW:
08647           case tUPLUS:
08648           case tUMINUS:
08649           case '|':
08650           case '^':
08651           case '&':
08652           case tCMP:
08653           case '>':
08654           case tGEQ:
08655           case '<':
08656           case tLEQ:
08657           case tEQ:
08658           case tNEQ:
08659             useless = rb_id2name(node->nd_mid);
08660             break;
08661         }
08662         break;
08663 
08664       case NODE_LVAR:
08665       case NODE_DVAR:
08666       case NODE_GVAR:
08667       case NODE_IVAR:
08668       case NODE_CVAR:
08669       case NODE_NTH_REF:
08670       case NODE_BACK_REF:
08671         useless = "a variable";
08672         break;
08673       case NODE_CONST:
08674         useless = "a constant";
08675         break;
08676       case NODE_LIT:
08677       case NODE_STR:
08678       case NODE_DSTR:
08679       case NODE_DREGX:
08680       case NODE_DREGX_ONCE:
08681         useless = "a literal";
08682         break;
08683       case NODE_COLON2:
08684       case NODE_COLON3:
08685         useless = "::";
08686         break;
08687       case NODE_DOT2:
08688         useless = "..";
08689         break;
08690       case NODE_DOT3:
08691         useless = "...";
08692         break;
08693       case NODE_SELF:
08694         useless = "self";
08695         break;
08696       case NODE_NIL:
08697         useless = "nil";
08698         break;
08699       case NODE_TRUE:
08700         useless = "true";
08701         break;
08702       case NODE_FALSE:
08703         useless = "false";
08704         break;
08705       case NODE_DEFINED:
08706         useless = "defined?";
08707         break;
08708     }
08709 
08710     if (useless) {
08711         int line = ruby_sourceline;
08712 
08713         ruby_sourceline = nd_line(node);
08714         rb_warnS("possibly useless use of %s in void context", useless);
08715         ruby_sourceline = line;
08716     }
08717 }
08718 
08719 static void
08720 void_stmts_gen(struct parser_params *parser, NODE *node)
08721 {
08722     if (!RTEST(ruby_verbose)) return;
08723     if (!node) return;
08724     if (nd_type(node) != NODE_BLOCK) return;
08725 
08726     for (;;) {
08727         if (!node->nd_next) return;
08728         void_expr0(node->nd_head);
08729         node = node->nd_next;
08730     }
08731 }
08732 
08733 static NODE *
08734 remove_begin(NODE *node)
08735 {
08736     NODE **n = &node, *n1 = node;
08737     while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
08738         *n = n1 = n1->nd_body;
08739     }
08740     return node;
08741 }
08742 
08743 static void
08744 reduce_nodes_gen(struct parser_params *parser, NODE **body)
08745 {
08746     NODE *node = *body;
08747 
08748     if (!node) {
08749         *body = NEW_NIL();
08750         return;
08751     }
08752 #define subnodes(n1, n2) \
08753     ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
08754      (!node->n2) ? (body = &node->n1, 1) : \
08755      (reduce_nodes(&node->n1), body = &node->n2, 1))
08756 
08757     while (node) {
08758         int newline = (int)(node->flags & NODE_FL_NEWLINE);
08759         switch (nd_type(node)) {
08760           end:
08761           case NODE_NIL:
08762             *body = 0;
08763             return;
08764           case NODE_RETURN:
08765             *body = node = node->nd_stts;
08766             if (newline && node) node->flags |= NODE_FL_NEWLINE;
08767             continue;
08768           case NODE_BEGIN:
08769             *body = node = node->nd_body;
08770             if (newline && node) node->flags |= NODE_FL_NEWLINE;
08771             continue;
08772           case NODE_BLOCK:
08773             body = &node->nd_end->nd_head;
08774             break;
08775           case NODE_IF:
08776             if (subnodes(nd_body, nd_else)) break;
08777             return;
08778           case NODE_CASE:
08779             body = &node->nd_body;
08780             break;
08781           case NODE_WHEN:
08782             if (!subnodes(nd_body, nd_next)) goto end;
08783             break;
08784           case NODE_ENSURE:
08785             if (!subnodes(nd_head, nd_resq)) goto end;
08786             break;
08787           case NODE_RESCUE:
08788             if (node->nd_else) {
08789                 body = &node->nd_resq;
08790                 break;
08791             }
08792             if (!subnodes(nd_head, nd_resq)) goto end;
08793             break;
08794           default:
08795             return;
08796         }
08797         node = *body;
08798         if (newline && node) node->flags |= NODE_FL_NEWLINE;
08799     }
08800 
08801 #undef subnodes
08802 }
08803 
08804 static int
08805 assign_in_cond(struct parser_params *parser, NODE *node)
08806 {
08807     switch (nd_type(node)) {
08808       case NODE_MASGN:
08809         yyerror("multiple assignment in conditional");
08810         return 1;
08811 
08812       case NODE_LASGN:
08813       case NODE_DASGN:
08814       case NODE_DASGN_CURR:
08815       case NODE_GASGN:
08816       case NODE_IASGN:
08817         break;
08818 
08819       default:
08820         return 0;
08821     }
08822 
08823     if (!node->nd_value) return 1;
08824     switch (nd_type(node->nd_value)) {
08825       case NODE_LIT:
08826       case NODE_STR:
08827       case NODE_NIL:
08828       case NODE_TRUE:
08829       case NODE_FALSE:
08830         /* reports always */
08831         parser_warn(node->nd_value, "found = in conditional, should be ==");
08832         return 1;
08833 
08834       case NODE_DSTR:
08835       case NODE_XSTR:
08836       case NODE_DXSTR:
08837       case NODE_EVSTR:
08838       case NODE_DREGX:
08839       default:
08840         break;
08841     }
08842     return 1;
08843 }
08844 
08845 static void
08846 warn_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08847 {
08848     if (!e_option_supplied(parser)) parser_warn(node, str);
08849 }
08850 
08851 static void
08852 warning_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08853 {
08854     if (!e_option_supplied(parser)) parser_warning(node, str);
08855 }
08856 
08857 static void
08858 fixup_nodes(NODE **rootnode)
08859 {
08860     NODE *node, *next, *head;
08861 
08862     for (node = *rootnode; node; node = next) {
08863         enum node_type type;
08864         VALUE val;
08865 
08866         next = node->nd_next;
08867         head = node->nd_head;
08868         rb_gc_force_recycle((VALUE)node);
08869         *rootnode = next;
08870         switch (type = nd_type(head)) {
08871           case NODE_DOT2:
08872           case NODE_DOT3:
08873             val = rb_range_new(head->nd_beg->nd_lit, head->nd_end->nd_lit,
08874                                type == NODE_DOT3);
08875             rb_gc_force_recycle((VALUE)head->nd_beg);
08876             rb_gc_force_recycle((VALUE)head->nd_end);
08877             nd_set_type(head, NODE_LIT);
08878             head->nd_lit = val;
08879             break;
08880           default:
08881             break;
08882         }
08883     }
08884 }
08885 
08886 static NODE *cond0(struct parser_params*,NODE*);
08887 
08888 static NODE*
08889 range_op(struct parser_params *parser, NODE *node)
08890 {
08891     enum node_type type;
08892 
08893     if (node == 0) return 0;
08894 
08895     type = nd_type(node);
08896     value_expr(node);
08897     if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
08898         warn_unless_e_option(parser, node, "integer literal in conditional range");
08899         return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."))));
08900     }
08901     return cond0(parser, node);
08902 }
08903 
08904 static int
08905 literal_node(NODE *node)
08906 {
08907     if (!node) return 1;        /* same as NODE_NIL */
08908     switch (nd_type(node)) {
08909       case NODE_LIT:
08910       case NODE_STR:
08911       case NODE_DSTR:
08912       case NODE_EVSTR:
08913       case NODE_DREGX:
08914       case NODE_DREGX_ONCE:
08915       case NODE_DSYM:
08916         return 2;
08917       case NODE_TRUE:
08918       case NODE_FALSE:
08919       case NODE_NIL:
08920         return 1;
08921     }
08922     return 0;
08923 }
08924 
08925 static NODE*
08926 cond0(struct parser_params *parser, NODE *node)
08927 {
08928     if (node == 0) return 0;
08929     assign_in_cond(parser, node);
08930 
08931     switch (nd_type(node)) {
08932       case NODE_DSTR:
08933       case NODE_EVSTR:
08934       case NODE_STR:
08935         rb_warn0("string literal in condition");
08936         break;
08937 
08938       case NODE_DREGX:
08939       case NODE_DREGX_ONCE:
08940         warning_unless_e_option(parser, node, "regex literal in condition");
08941         return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
08942 
08943       case NODE_AND:
08944       case NODE_OR:
08945         node->nd_1st = cond0(parser, node->nd_1st);
08946         node->nd_2nd = cond0(parser, node->nd_2nd);
08947         break;
08948 
08949       case NODE_DOT2:
08950       case NODE_DOT3:
08951         node->nd_beg = range_op(parser, node->nd_beg);
08952         node->nd_end = range_op(parser, node->nd_end);
08953         if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
08954         else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
08955         if (!e_option_supplied(parser)) {
08956             int b = literal_node(node->nd_beg);
08957             int e = literal_node(node->nd_end);
08958             if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
08959                 parser_warn(node, "range literal in condition");
08960             }
08961         }
08962         break;
08963 
08964       case NODE_DSYM:
08965         parser_warning(node, "literal in condition");
08966         break;
08967 
08968       case NODE_LIT:
08969         if (TYPE(node->nd_lit) == T_REGEXP) {
08970             warn_unless_e_option(parser, node, "regex literal in condition");
08971             nd_set_type(node, NODE_MATCH);
08972         }
08973         else {
08974             parser_warning(node, "literal in condition");
08975         }
08976       default:
08977         break;
08978     }
08979     return node;
08980 }
08981 
08982 static NODE*
08983 cond_gen(struct parser_params *parser, NODE *node)
08984 {
08985     if (node == 0) return 0;
08986     return cond0(parser, node);
08987 }
08988 
08989 static NODE*
08990 logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
08991 {
08992     value_expr(left);
08993     if (left && (enum node_type)nd_type(left) == type) {
08994         NODE *node = left, *second;
08995         while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
08996             node = second;
08997         }
08998         node->nd_2nd = NEW_NODE(type, second, right, 0);
08999         return left;
09000     }
09001     return NEW_NODE(type, left, right, 0);
09002 }
09003 
09004 static void
09005 no_blockarg(struct parser_params *parser, NODE *node)
09006 {
09007     if (node && nd_type(node) == NODE_BLOCK_PASS) {
09008         compile_error(PARSER_ARG "block argument should not be given");
09009     }
09010 }
09011 
09012 static NODE *
09013 ret_args_gen(struct parser_params *parser, NODE *node)
09014 {
09015     if (node) {
09016         no_blockarg(parser, node);
09017         if (nd_type(node) == NODE_ARRAY) {
09018             if (node->nd_next == 0) {
09019                 node = node->nd_head;
09020             }
09021             else {
09022                 nd_set_type(node, NODE_VALUES);
09023             }
09024         }
09025     }
09026     return node;
09027 }
09028 
09029 static NODE *
09030 new_yield_gen(struct parser_params *parser, NODE *node)
09031 {
09032     long state = Qtrue;
09033 
09034     if (node) {
09035         no_blockarg(parser, node);
09036         if (node && nd_type(node) == NODE_SPLAT) {
09037             state = Qtrue;
09038         }
09039     }
09040     else {
09041         state = Qfalse;
09042     }
09043     return NEW_YIELD(node, state);
09044 }
09045 
09046 static NODE*
09047 negate_lit(NODE *node)
09048 {
09049     switch (TYPE(node->nd_lit)) {
09050       case T_FIXNUM:
09051         node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
09052         break;
09053       case T_BIGNUM:
09054         node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
09055         break;
09056       case T_FLOAT:
09057         RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
09058         break;
09059       default:
09060         break;
09061     }
09062     return node;
09063 }
09064 
09065 static NODE *
09066 arg_blk_pass(NODE *node1, NODE *node2)
09067 {
09068     if (node2) {
09069         node2->nd_head = node1;
09070         return node2;
09071     }
09072     return node1;
09073 }
09074 
09075 static NODE*
09076 new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
09077 {
09078     int saved_line = ruby_sourceline;
09079     NODE *node;
09080     NODE *i1, *i2 = 0;
09081 
09082     node = NEW_ARGS(m ? m->nd_plen : 0, o);
09083     i1 = m ? m->nd_next : 0;
09084     node->nd_next = NEW_ARGS_AUX(r, b);
09085 
09086     if (p) {
09087         i2 = p->nd_next;
09088         node->nd_next->nd_next = NEW_ARGS_AUX(p->nd_pid, p->nd_plen);
09089     }
09090     else if (i1) {
09091         node->nd_next->nd_next = NEW_ARGS_AUX(0, 0);
09092     }
09093     if (i1 || i2) {
09094         node->nd_next->nd_next->nd_next = NEW_NODE(NODE_AND, i1, i2, 0);
09095     }
09096     ruby_sourceline = saved_line;
09097     return node;
09098 }
09099 #endif /* !RIPPER */
09100 
09101 static void
09102 warn_unused_var(struct parser_params *parser, struct local_vars *local)
09103 {
09104     int i, cnt;
09105     ID *v, *u;
09106 
09107     if (!local->used) return;
09108     v = local->vars->tbl;
09109     u = local->used->tbl;
09110     cnt = local->used->pos;
09111     if (cnt != local->vars->pos) {
09112         rb_bug("local->used->pos != local->vars->pos");
09113     }
09114     for (i = 0; i < cnt; ++i) {
09115         if (!v[i] || (u[i] & LVAR_USED)) continue;
09116         if (idUScore == v[i]) continue;
09117         rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));
09118     }
09119 }
09120 
09121 static void
09122 local_push_gen(struct parser_params *parser, int inherit_dvars)
09123 {
09124     struct local_vars *local;
09125 
09126     local = ALLOC(struct local_vars);
09127     local->prev = lvtbl;
09128     local->args = vtable_alloc(0);
09129     local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
09130     local->used = !inherit_dvars && RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
09131     lvtbl = local;
09132 }
09133 
09134 static void
09135 local_pop_gen(struct parser_params *parser)
09136 {
09137     struct local_vars *local = lvtbl->prev;
09138     if (lvtbl->used) {
09139         warn_unused_var(parser, lvtbl);
09140         vtable_free(lvtbl->used);
09141     }
09142     vtable_free(lvtbl->args);
09143     vtable_free(lvtbl->vars);
09144     xfree(lvtbl);
09145     lvtbl = local;
09146 }
09147 
09148 #ifndef RIPPER
09149 static ID*
09150 vtable_tblcpy(ID *buf, const struct vtable *src)
09151 {
09152     int i, cnt = vtable_size(src);
09153 
09154     if (cnt > 0) {
09155         buf[0] = cnt;
09156         for (i = 0; i < cnt; i++) {
09157             buf[i] = src->tbl[i];
09158         }
09159         return buf;
09160     }
09161     return 0;
09162 }
09163 
09164 static ID*
09165 local_tbl_gen(struct parser_params *parser)
09166 {
09167     int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars);
09168     ID *buf;
09169 
09170     if (cnt <= 0) return 0;
09171     buf = ALLOC_N(ID, cnt + 1);
09172     vtable_tblcpy(buf+1, lvtbl->args);
09173     vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars);
09174     buf[0] = cnt;
09175     return buf;
09176 }
09177 #endif
09178 
09179 static int
09180 arg_var_gen(struct parser_params *parser, ID id)
09181 {
09182     vtable_add(lvtbl->args, id);
09183     return vtable_size(lvtbl->args) - 1;
09184 }
09185 
09186 static int
09187 local_var_gen(struct parser_params *parser, ID id)
09188 {
09189     vtable_add(lvtbl->vars, id);
09190     if (lvtbl->used) {
09191         vtable_add(lvtbl->used, (ID)ruby_sourceline);
09192     }
09193     return vtable_size(lvtbl->vars) - 1;
09194 }
09195 
09196 static int
09197 local_id_gen(struct parser_params *parser, ID id)
09198 {
09199     struct vtable *vars, *args, *used;
09200 
09201     vars = lvtbl->vars;
09202     args = lvtbl->args;
09203     used = lvtbl->used;
09204 
09205     while (vars && POINTER_P(vars->prev)) {
09206         vars = vars->prev;
09207         args = args->prev;
09208         if (used) used = used->prev;
09209     }
09210 
09211     if (vars && vars->prev == DVARS_INHERIT) {
09212         return rb_local_defined(id);
09213     }
09214     else if (vtable_included(args, id)) {
09215         return 1;
09216     }
09217     else {
09218         int i = vtable_included(vars, id);
09219         if (i && used) used->tbl[i-1] |= LVAR_USED;
09220         return i != 0;
09221     }
09222 }
09223 
09224 static const struct vtable *
09225 dyna_push_gen(struct parser_params *parser)
09226 {
09227     lvtbl->args = vtable_alloc(lvtbl->args);
09228     lvtbl->vars = vtable_alloc(lvtbl->vars);
09229     if (lvtbl->used) {
09230         lvtbl->used = vtable_alloc(lvtbl->used);
09231     }
09232     return lvtbl->args;
09233 }
09234 
09235 static void
09236 dyna_pop_1(struct parser_params *parser)
09237 {
09238     struct vtable *tmp;
09239 
09240     if ((tmp = lvtbl->used) != 0) {
09241         warn_unused_var(parser, lvtbl);
09242         lvtbl->used = lvtbl->used->prev;
09243         vtable_free(tmp);
09244     }
09245     tmp = lvtbl->args;
09246     lvtbl->args = lvtbl->args->prev;
09247     vtable_free(tmp);
09248     tmp = lvtbl->vars;
09249     lvtbl->vars = lvtbl->vars->prev;
09250     vtable_free(tmp);
09251 }
09252 
09253 static void
09254 dyna_pop_gen(struct parser_params *parser, const struct vtable *lvargs)
09255 {
09256     while (lvtbl->args != lvargs) {
09257         dyna_pop_1(parser);
09258         if (!lvtbl->args) {
09259             struct local_vars *local = lvtbl->prev;
09260             xfree(lvtbl);
09261             lvtbl = local;
09262         }
09263     }
09264     dyna_pop_1(parser);
09265 }
09266 
09267 static int
09268 dyna_in_block_gen(struct parser_params *parser)
09269 {
09270     return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE;
09271 }
09272 
09273 static int
09274 dvar_defined_gen(struct parser_params *parser, ID id, int get)
09275 {
09276     struct vtable *vars, *args, *used;
09277     int i;
09278 
09279     args = lvtbl->args;
09280     vars = lvtbl->vars;
09281     used = lvtbl->used;
09282 
09283     while (POINTER_P(vars)) {
09284         if (vtable_included(args, id)) {
09285             return 1;
09286         }
09287         if ((i = vtable_included(vars, id)) != 0) {
09288             if (used) used->tbl[i-1] |= LVAR_USED;
09289             return 1;
09290         }
09291         args = args->prev;
09292         vars = vars->prev;
09293         if (get) used = 0;
09294         if (used) used = used->prev;
09295     }
09296 
09297     if (vars == DVARS_INHERIT) {
09298         return rb_dvar_defined(id);
09299     }
09300 
09301     return 0;
09302 }
09303 
09304 static int
09305 dvar_curr_gen(struct parser_params *parser, ID id)
09306 {
09307     return (vtable_included(lvtbl->args, id) ||
09308             vtable_included(lvtbl->vars, id));
09309 }
09310 
09311 #ifndef RIPPER
09312 static void
09313 reg_fragment_setenc_gen(struct parser_params* parser, VALUE str, int options)
09314 {
09315     int c = RE_OPTION_ENCODING_IDX(options);
09316 
09317     if (c) {
09318         int opt, idx;
09319         rb_char_to_option_kcode(c, &opt, &idx);
09320         if (idx != ENCODING_GET(str) &&
09321             rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09322             goto error;
09323         }
09324         ENCODING_SET(str, idx);
09325     }
09326     else if (RE_OPTION_ENCODING_NONE(options)) {
09327         if (!ENCODING_IS_ASCII8BIT(str) &&
09328             rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09329             c = 'n';
09330             goto error;
09331         }
09332         rb_enc_associate(str, rb_ascii8bit_encoding());
09333     }
09334     else if (parser->enc == rb_usascii_encoding()) {
09335         if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09336             /* raise in re.c */
09337             rb_enc_associate(str, rb_usascii_encoding());
09338         }
09339         else {
09340             rb_enc_associate(str, rb_ascii8bit_encoding());
09341         }
09342     }
09343     return;
09344 
09345   error:
09346     compile_error(PARSER_ARG
09347         "regexp encoding option '%c' differs from source encoding '%s'",
09348         c, rb_enc_name(rb_enc_get(str)));
09349 }
09350 
09351 static int
09352 reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
09353 {
09354     VALUE err;
09355     reg_fragment_setenc(str, options);
09356     err = rb_reg_check_preprocess(str);
09357     if (err != Qnil) {
09358         err = rb_obj_as_string(err);
09359         compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
09360         RB_GC_GUARD(err);
09361         return 0;
09362     }
09363     return 1;
09364 }
09365 
09366 typedef struct {
09367     struct parser_params* parser;
09368     rb_encoding *enc;
09369     NODE *succ_block;
09370     NODE *fail_block;
09371     int num;
09372 } reg_named_capture_assign_t;
09373 
09374 static int
09375 reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
09376           int back_num, int *back_refs, OnigRegex regex, void *arg0)
09377 {
09378     reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
09379     struct parser_params* parser = arg->parser;
09380     rb_encoding *enc = arg->enc;
09381     long len = name_end - name;
09382     const char *s = (const char *)name;
09383     ID var;
09384 
09385     arg->num++;
09386 
09387     if (arg->succ_block == 0) {
09388         arg->succ_block = NEW_BEGIN(0);
09389         arg->fail_block = NEW_BEGIN(0);
09390     }
09391 
09392     if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
09393         (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) ||
09394         !rb_enc_symname2_p(s, len, enc)) {
09395         return ST_CONTINUE;
09396     }
09397     var = rb_intern3(s, len, enc);
09398     if (dvar_defined(var) || local_id(var)) {
09399         rb_warningS("named capture conflicts a local variable - %s",
09400                     rb_id2name(var));
09401     }
09402     arg->succ_block = block_append(arg->succ_block,
09403         newline_node(node_assign(assignable(var,0),
09404             NEW_CALL(
09405               gettable(rb_intern("$~")),
09406               idAREF,
09407               NEW_LIST(NEW_LIT(ID2SYM(var))))
09408             )));
09409     arg->fail_block = block_append(arg->fail_block,
09410         newline_node(node_assign(assignable(var,0), NEW_LIT(Qnil))));
09411     return ST_CONTINUE;
09412 }
09413 
09414 static NODE *
09415 reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match)
09416 {
09417     reg_named_capture_assign_t arg;
09418 
09419     arg.parser = parser;
09420     arg.enc = rb_enc_get(regexp);
09421     arg.succ_block = 0;
09422     arg.fail_block = 0;
09423     arg.num = 0;
09424     onig_foreach_name(RREGEXP(regexp)->ptr, reg_named_capture_assign_iter, (void*)&arg);
09425 
09426     if (arg.num == 0)
09427         return match;
09428 
09429     return
09430         block_append(
09431             newline_node(match),
09432             NEW_IF(gettable(rb_intern("$~")),
09433                 block_append(
09434                     newline_node(arg.succ_block),
09435                     newline_node(
09436                         NEW_CALL(
09437                           gettable(rb_intern("$~")),
09438                           rb_intern("begin"),
09439                           NEW_LIST(NEW_LIT(INT2FIX(0)))))),
09440                 block_append(
09441                     newline_node(arg.fail_block),
09442                     newline_node(
09443                         NEW_LIT(Qnil)))));
09444 }
09445 
09446 static VALUE
09447 reg_compile_gen(struct parser_params* parser, VALUE str, int options)
09448 {
09449     VALUE re;
09450     VALUE err;
09451 
09452     reg_fragment_setenc(str, options);
09453     err = rb_errinfo();
09454     re = rb_reg_compile(str, options & RE_OPTION_MASK, ruby_sourcefile, ruby_sourceline);
09455     if (NIL_P(re)) {
09456         ID mesg = rb_intern("mesg");
09457         VALUE m = rb_attr_get(rb_errinfo(), mesg);
09458         rb_set_errinfo(err);
09459         if (!NIL_P(err)) {
09460             rb_str_append(rb_str_cat(rb_attr_get(err, mesg), "\n", 1), m);
09461         }
09462         else {
09463             compile_error(PARSER_ARG "%s", RSTRING_PTR(m));
09464         }
09465         return Qnil;
09466     }
09467     return re;
09468 }
09469 
09470 void
09471 rb_gc_mark_parser(void)
09472 {
09473 }
09474 
09475 NODE*
09476 rb_parser_append_print(VALUE vparser, NODE *node)
09477 {
09478     NODE *prelude = 0;
09479     NODE *scope = node;
09480     struct parser_params *parser;
09481 
09482     if (!node) return node;
09483 
09484     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09485 
09486     node = node->nd_body;
09487 
09488     if (nd_type(node) == NODE_PRELUDE) {
09489         prelude = node;
09490         node = node->nd_body;
09491     }
09492 
09493     node = block_append(node,
09494                         NEW_FCALL(rb_intern("print"),
09495                                   NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
09496     if (prelude) {
09497         prelude->nd_body = node;
09498         scope->nd_body = prelude;
09499     }
09500     else {
09501         scope->nd_body = node;
09502     }
09503 
09504     return scope;
09505 }
09506 
09507 NODE *
09508 rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split)
09509 {
09510     NODE *prelude = 0;
09511     NODE *scope = node;
09512     struct parser_params *parser;
09513 
09514     if (!node) return node;
09515 
09516     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09517 
09518     node = node->nd_body;
09519 
09520     if (nd_type(node) == NODE_PRELUDE) {
09521         prelude = node;
09522         node = node->nd_body;
09523     }
09524     if (split) {
09525         node = block_append(NEW_GASGN(rb_intern("$F"),
09526                                       NEW_CALL(NEW_GVAR(rb_intern("$_")),
09527                                                rb_intern("split"), 0)),
09528                             node);
09529     }
09530     if (chop) {
09531         node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
09532                                      rb_intern("chop!"), 0), node);
09533     }
09534 
09535     node = NEW_OPT_N(node);
09536 
09537     if (prelude) {
09538         prelude->nd_body = node;
09539         scope->nd_body = prelude;
09540     }
09541     else {
09542         scope->nd_body = node;
09543     }
09544 
09545     return scope;
09546 }
09547 
09548 static const struct {
09549     ID token;
09550     const char *name;
09551 } op_tbl[] = {
09552     {tDOT2,     ".."},
09553     {tDOT3,     "..."},
09554     {'+',       "+(binary)"},
09555     {'-',       "-(binary)"},
09556     {tPOW,      "**"},
09557     {tUPLUS,    "+@"},
09558     {tUMINUS,   "-@"},
09559     {tCMP,      "<=>"},
09560     {tGEQ,      ">="},
09561     {tLEQ,      "<="},
09562     {tEQ,       "=="},
09563     {tEQQ,      "==="},
09564     {tNEQ,      "!="},
09565     {tMATCH,    "=~"},
09566     {tNMATCH,   "!~"},
09567     {tAREF,     "[]"},
09568     {tASET,     "[]="},
09569     {tLSHFT,    "<<"},
09570     {tRSHFT,    ">>"},
09571     {tCOLON2,   "::"},
09572 };
09573 
09574 #define op_tbl_count numberof(op_tbl)
09575 
09576 #ifndef ENABLE_SELECTOR_NAMESPACE
09577 #define ENABLE_SELECTOR_NAMESPACE 0
09578 #endif
09579 
09580 static struct symbols {
09581     ID last_id;
09582     st_table *sym_id;
09583     st_table *id_str;
09584 #if ENABLE_SELECTOR_NAMESPACE
09585     st_table *ivar2_id;
09586     st_table *id_ivar2;
09587 #endif
09588     VALUE op_sym[tLAST_TOKEN];
09589 } global_symbols = {tLAST_ID};
09590 
09591 static const struct st_hash_type symhash = {
09592     rb_str_hash_cmp,
09593     rb_str_hash,
09594 };
09595 
09596 #if ENABLE_SELECTOR_NAMESPACE
09597 struct ivar2_key {
09598     ID id;
09599     VALUE klass;
09600 };
09601 
09602 static int
09603 ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
09604 {
09605     if (key1->id == key2->id && key1->klass == key2->klass) {
09606         return 0;
09607     }
09608     return 1;
09609 }
09610 
09611 static int
09612 ivar2_hash(struct ivar2_key *key)
09613 {
09614     return (key->id << 8) ^ (key->klass >> 2);
09615 }
09616 
09617 static const struct st_hash_type ivar2_hash_type = {
09618     ivar2_cmp,
09619     ivar2_hash,
09620 };
09621 #endif
09622 
09623 void
09624 Init_sym(void)
09625 {
09626     global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
09627     global_symbols.id_str = st_init_numtable_with_size(1000);
09628 #if ENABLE_SELECTOR_NAMESPACE
09629     global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000);
09630     global_symbols.id_ivar2 = st_init_numtable_with_size(1000);
09631 #endif
09632 
09633     Init_id();
09634 }
09635 
09636 void
09637 rb_gc_mark_symbols(void)
09638 {
09639     rb_mark_tbl(global_symbols.id_str);
09640     rb_gc_mark_locations(global_symbols.op_sym,
09641                          global_symbols.op_sym + tLAST_TOKEN);
09642 }
09643 #endif /* !RIPPER */
09644 
09645 static ID
09646 internal_id_gen(struct parser_params *parser)
09647 {
09648     ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars);
09649     id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
09650     return ID_INTERNAL | (id << ID_SCOPE_SHIFT);
09651 }
09652 
09653 #ifndef RIPPER
09654 static int
09655 is_special_global_name(const char *m, const char *e, rb_encoding *enc)
09656 {
09657     int mb = 0;
09658 
09659     if (m >= e) return 0;
09660     switch (*m) {
09661       case '~': case '*': case '$': case '?': case '!': case '@':
09662       case '/': case '\\': case ';': case ',': case '.': case '=':
09663       case ':': case '<': case '>': case '\"':
09664       case '&': case '`': case '\'': case '+':
09665       case '0':
09666         ++m;
09667         break;
09668       case '-':
09669         ++m;
09670         if (m < e && is_identchar(m, e, enc)) {
09671             if (!ISASCII(*m)) mb = 1;
09672             m += rb_enc_mbclen(m, e, enc);
09673         }
09674         break;
09675       default:
09676         if (!rb_enc_isdigit(*m, enc)) return 0;
09677         do {
09678             if (!ISASCII(*m)) mb = 1;
09679             ++m;
09680         } while (m < e && rb_enc_isdigit(*m, enc));
09681     }
09682     return m == e ? mb + 1 : 0;
09683 }
09684 
09685 int
09686 rb_symname_p(const char *name)
09687 {
09688     return rb_enc_symname_p(name, rb_ascii8bit_encoding());
09689 }
09690 
09691 int
09692 rb_enc_symname_p(const char *name, rb_encoding *enc)
09693 {
09694     return rb_enc_symname2_p(name, strlen(name), enc);
09695 }
09696 
09697 int
09698 rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
09699 {
09700     const char *m = name;
09701     const char *e = m + len;
09702     int localid = FALSE;
09703 
09704     if (!m || len <= 0) return FALSE;
09705     switch (*m) {
09706       case '\0':
09707         return FALSE;
09708 
09709       case '$':
09710         if (is_special_global_name(++m, e, enc)) return TRUE;
09711         goto id;
09712 
09713       case '@':
09714         if (*++m == '@') ++m;
09715         goto id;
09716 
09717       case '<':
09718         switch (*++m) {
09719           case '<': ++m; break;
09720           case '=': if (*++m == '>') ++m; break;
09721           default: break;
09722         }
09723         break;
09724 
09725       case '>':
09726         switch (*++m) {
09727           case '>': case '=': ++m; break;
09728         }
09729         break;
09730 
09731       case '=':
09732         switch (*++m) {
09733           case '~': ++m; break;
09734           case '=': if (*++m == '=') ++m; break;
09735           default: return FALSE;
09736         }
09737         break;
09738 
09739       case '*':
09740         if (*++m == '*') ++m;
09741         break;
09742 
09743       case '+': case '-':
09744         if (*++m == '@') ++m;
09745         break;
09746 
09747       case '|': case '^': case '&': case '/': case '%': case '~': case '`':
09748         ++m;
09749         break;
09750 
09751       case '[':
09752         if (*++m != ']') return FALSE;
09753         if (*++m == '=') ++m;
09754         break;
09755 
09756       case '!':
09757         if (len == 1) return TRUE;
09758         switch (*++m) {
09759           case '=': case '~': ++m; break;
09760           default: return FALSE;
09761         }
09762         break;
09763 
09764       default:
09765         localid = !rb_enc_isupper(*m, enc);
09766       id:
09767         if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
09768             return FALSE;
09769         while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
09770         if (localid) {
09771             switch (*m) {
09772               case '!': case '?': case '=': ++m;
09773             }
09774         }
09775         break;
09776     }
09777     return m == e;
09778 }
09779 
09780 static ID
09781 register_symid(ID id, const char *name, long len, rb_encoding *enc)
09782 {
09783     VALUE str = rb_enc_str_new(name, len, enc);
09784     OBJ_FREEZE(str);
09785     st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
09786     st_add_direct(global_symbols.id_str, id, (st_data_t)str);
09787     return id;
09788 }
09789 
09790 ID
09791 rb_intern3(const char *name, long len, rb_encoding *enc)
09792 {
09793     const char *m = name;
09794     const char *e = m + len;
09795     unsigned char c;
09796     VALUE str;
09797     ID id;
09798     long last;
09799     int mb;
09800     st_data_t data;
09801     struct RString fake_str;
09802     fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
09803     fake_str.basic.klass = rb_cString;
09804     fake_str.as.heap.len = len;
09805     fake_str.as.heap.ptr = (char *)name;
09806     fake_str.as.heap.aux.capa = len;
09807     str = (VALUE)&fake_str;
09808     rb_enc_associate(str, enc);
09809     OBJ_FREEZE(str);
09810 
09811     if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
09812         rb_raise(rb_eEncodingError, "invalid encoding symbol");
09813     }
09814 
09815     if (st_lookup(global_symbols.sym_id, str, &data))
09816         return (ID)data;
09817 
09818     if (rb_cString && !rb_enc_asciicompat(enc)) {
09819         id = ID_JUNK;
09820         goto new_id;
09821     }
09822     last = len-1;
09823     id = 0;
09824     switch (*m) {
09825       case '$':
09826         id |= ID_GLOBAL;
09827         if ((mb = is_special_global_name(++m, e, enc)) != 0) {
09828             if (!--mb) enc = rb_ascii8bit_encoding();
09829             goto new_id;
09830         }
09831         break;
09832       case '@':
09833         if (m[1] == '@') {
09834             m++;
09835             id |= ID_CLASS;
09836         }
09837         else {
09838             id |= ID_INSTANCE;
09839         }
09840         m++;
09841         break;
09842       default:
09843         c = m[0];
09844         if (c != '_' && rb_enc_isascii(c, enc) && rb_enc_ispunct(c, enc)) {
09845             /* operators */
09846             int i;
09847 
09848             if (len == 1) {
09849                 id = c;
09850                 goto id_register;
09851             }
09852             for (i = 0; i < op_tbl_count; i++) {
09853                 if (*op_tbl[i].name == *m &&
09854                     strcmp(op_tbl[i].name, m) == 0) {
09855                     id = op_tbl[i].token;
09856                     goto id_register;
09857                 }
09858             }
09859         }
09860 
09861         if (m[last] == '=') {
09862             /* attribute assignment */
09863             id = rb_intern3(name, last, enc);
09864             if (id > tLAST_TOKEN && !is_attrset_id(id)) {
09865                 enc = rb_enc_get(rb_id2str(id));
09866                 id = rb_id_attrset(id);
09867                 goto id_register;
09868             }
09869             id = ID_ATTRSET;
09870         }
09871         else if (rb_enc_isupper(m[0], enc)) {
09872             id = ID_CONST;
09873         }
09874         else {
09875             id = ID_LOCAL;
09876         }
09877         break;
09878     }
09879     mb = 0;
09880     if (!rb_enc_isdigit(*m, enc)) {
09881         while (m <= name + last && is_identchar(m, e, enc)) {
09882             if (ISASCII(*m)) {
09883                 m++;
09884             }
09885             else {
09886                 mb = 1;
09887                 m += rb_enc_mbclen(m, e, enc);
09888             }
09889         }
09890     }
09891     if (m - name < len) id = ID_JUNK;
09892     if (enc != rb_usascii_encoding()) {
09893         /*
09894          * this clause makes sense only when called from other than
09895          * rb_intern_str() taking care of code-range.
09896          */
09897         if (!mb) {
09898             for (; m <= name + len; ++m) {
09899                 if (!ISASCII(*m)) goto mbstr;
09900             }
09901             enc = rb_usascii_encoding();
09902         }
09903       mbstr:;
09904     }
09905   new_id:
09906     if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
09907         if (len > 20) {
09908             rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.20s...)",
09909                      name);
09910         }
09911         else {
09912             rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.*s)",
09913                      (int)len, name);
09914         }
09915     }
09916     id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
09917   id_register:
09918     return register_symid(id, name, len, enc);
09919 }
09920 
09921 ID
09922 rb_intern2(const char *name, long len)
09923 {
09924     return rb_intern3(name, len, rb_usascii_encoding());
09925 }
09926 
09927 #undef rb_intern
09928 ID
09929 rb_intern(const char *name)
09930 {
09931     return rb_intern2(name, strlen(name));
09932 }
09933 
09934 ID
09935 rb_intern_str(VALUE str)
09936 {
09937     rb_encoding *enc;
09938     ID id;
09939 
09940     if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
09941         enc = rb_usascii_encoding();
09942     }
09943     else {
09944         enc = rb_enc_get(str);
09945     }
09946     id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
09947     RB_GC_GUARD(str);
09948     return id;
09949 }
09950 
09951 VALUE
09952 rb_id2str(ID id)
09953 {
09954     st_data_t data;
09955 
09956     if (id < tLAST_TOKEN) {
09957         int i = 0;
09958 
09959         if (id < INT_MAX && rb_ispunct((int)id)) {
09960             VALUE str = global_symbols.op_sym[i = (int)id];
09961             if (!str) {
09962                 char name[2];
09963                 name[0] = (char)id;
09964                 name[1] = 0;
09965                 str = rb_usascii_str_new(name, 1);
09966                 OBJ_FREEZE(str);
09967                 global_symbols.op_sym[i] = str;
09968             }
09969             return str;
09970         }
09971         for (i = 0; i < op_tbl_count; i++) {
09972             if (op_tbl[i].token == id) {
09973                 VALUE str = global_symbols.op_sym[i];
09974                 if (!str) {
09975                     str = rb_usascii_str_new2(op_tbl[i].name);
09976                     OBJ_FREEZE(str);
09977                     global_symbols.op_sym[i] = str;
09978                 }
09979                 return str;
09980             }
09981         }
09982     }
09983 
09984     if (st_lookup(global_symbols.id_str, id, &data)) {
09985         VALUE str = (VALUE)data;
09986         if (RBASIC(str)->klass == 0)
09987             RBASIC(str)->klass = rb_cString;
09988         return str;
09989     }
09990 
09991     if (is_attrset_id(id)) {
09992         ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
09993         VALUE str;
09994 
09995         while (!(str = rb_id2str(id2))) {
09996             if (!is_local_id(id2)) return 0;
09997             id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
09998         }
09999         str = rb_str_dup(str);
10000         rb_str_cat(str, "=", 1);
10001         rb_intern_str(str);
10002         if (st_lookup(global_symbols.id_str, id, &data)) {
10003             VALUE str = (VALUE)data;
10004             if (RBASIC(str)->klass == 0)
10005                 RBASIC(str)->klass = rb_cString;
10006             return str;
10007         }
10008     }
10009     return 0;
10010 }
10011 
10012 const char *
10013 rb_id2name(ID id)
10014 {
10015     VALUE str = rb_id2str(id);
10016 
10017     if (!str) return 0;
10018     return RSTRING_PTR(str);
10019 }
10020 
10021 static int
10022 symbols_i(VALUE sym, ID value, VALUE ary)
10023 {
10024     rb_ary_push(ary, ID2SYM(value));
10025     return ST_CONTINUE;
10026 }
10027 
10028 /*
10029  *  call-seq:
10030  *     Symbol.all_symbols    => array
10031  *
10032  *  Returns an array of all the symbols currently in Ruby's symbol
10033  *  table.
10034  *
10035  *     Symbol.all_symbols.size    #=> 903
10036  *     Symbol.all_symbols[1,20]   #=> [:floor, :ARGV, :Binding, :symlink,
10037  *                                     :chown, :EOFError, :$;, :String,
10038  *                                     :LOCK_SH, :"setuid?", :$<,
10039  *                                     :default_proc, :compact, :extend,
10040  *                                     :Tms, :getwd, :$=, :ThreadGroup,
10041  *                                     :wait2, :$>]
10042  */
10043 
10044 VALUE
10045 rb_sym_all_symbols(void)
10046 {
10047     VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
10048 
10049     st_foreach(global_symbols.sym_id, symbols_i, ary);
10050     return ary;
10051 }
10052 
10053 int
10054 rb_is_const_id(ID id)
10055 {
10056     return is_const_id(id);
10057 }
10058 
10059 int
10060 rb_is_class_id(ID id)
10061 {
10062     return is_class_id(id);
10063 }
10064 
10065 int
10066 rb_is_instance_id(ID id)
10067 {
10068     return is_instance_id(id);
10069 }
10070 
10071 int
10072 rb_is_local_id(ID id)
10073 {
10074     return is_local_id(id);
10075 }
10076 
10077 int
10078 rb_is_junk_id(ID id)
10079 {
10080     return is_junk_id(id);
10081 }
10082 
10083 #endif /* !RIPPER */
10084 
10085 static void
10086 parser_initialize(struct parser_params *parser)
10087 {
10088     parser->eofp = Qfalse;
10089 
10090     parser->parser_lex_strterm = 0;
10091     parser->parser_cond_stack = 0;
10092     parser->parser_cmdarg_stack = 0;
10093     parser->parser_class_nest = 0;
10094     parser->parser_paren_nest = 0;
10095     parser->parser_lpar_beg = 0;
10096     parser->parser_in_single = 0;
10097     parser->parser_in_def = 0;
10098     parser->parser_in_defined = 0;
10099     parser->parser_compile_for_eval = 0;
10100     parser->parser_cur_mid = 0;
10101     parser->parser_tokenbuf = NULL;
10102     parser->parser_tokidx = 0;
10103     parser->parser_toksiz = 0;
10104     parser->parser_heredoc_end = 0;
10105     parser->parser_command_start = TRUE;
10106     parser->parser_deferred_nodes = 0;
10107     parser->parser_lex_pbeg = 0;
10108     parser->parser_lex_p = 0;
10109     parser->parser_lex_pend = 0;
10110     parser->parser_lvtbl = 0;
10111     parser->parser_ruby__end__seen = 0;
10112     parser->parser_ruby_sourcefile = 0;
10113 #ifndef RIPPER
10114     parser->is_ripper = 0;
10115     parser->parser_eval_tree_begin = 0;
10116     parser->parser_eval_tree = 0;
10117 #else
10118     parser->is_ripper = 1;
10119     parser->parser_ruby_sourcefile_string = Qnil;
10120     parser->delayed = Qnil;
10121 
10122     parser->result = Qnil;
10123     parser->parsing_thread = Qnil;
10124     parser->toplevel_p = TRUE;
10125 #endif
10126 #ifdef YYMALLOC
10127     parser->heap = NULL;
10128 #endif
10129     parser->enc = rb_usascii_encoding();
10130 }
10131 
10132 #ifdef RIPPER
10133 #define parser_mark ripper_parser_mark
10134 #define parser_free ripper_parser_free
10135 #endif
10136 
10137 static void
10138 parser_mark(void *ptr)
10139 {
10140     struct parser_params *p = (struct parser_params*)ptr;
10141 
10142     rb_gc_mark((VALUE)p->parser_lex_strterm);
10143     rb_gc_mark((VALUE)p->parser_deferred_nodes);
10144     rb_gc_mark(p->parser_lex_input);
10145     rb_gc_mark(p->parser_lex_lastline);
10146     rb_gc_mark(p->parser_lex_nextline);
10147 #ifndef RIPPER
10148     rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
10149     rb_gc_mark((VALUE)p->parser_eval_tree) ;
10150     rb_gc_mark(p->debug_lines);
10151 #else
10152     rb_gc_mark(p->parser_ruby_sourcefile_string);
10153     rb_gc_mark(p->delayed);
10154     rb_gc_mark(p->value);
10155     rb_gc_mark(p->result);
10156     rb_gc_mark(p->parsing_thread);
10157 #endif
10158 #ifdef YYMALLOC
10159     rb_gc_mark((VALUE)p->heap);
10160 #endif
10161 }
10162 
10163 static void
10164 parser_free(void *ptr)
10165 {
10166     struct parser_params *p = (struct parser_params*)ptr;
10167     struct local_vars *local, *prev;
10168 
10169     if (p->parser_tokenbuf) {
10170         xfree(p->parser_tokenbuf);
10171     }
10172     for (local = p->parser_lvtbl; local; local = prev) {
10173         if (local->vars) xfree(local->vars);
10174         prev = local->prev;
10175         xfree(local);
10176     }
10177 #ifndef RIPPER
10178     xfree(p->parser_ruby_sourcefile);
10179 #endif
10180     xfree(p);
10181 }
10182 
10183 static size_t
10184 parser_memsize(const void *ptr)
10185 {
10186     struct parser_params *p = (struct parser_params*)ptr;
10187     struct local_vars *local;
10188     size_t size = sizeof(*p);
10189 
10190     if (!ptr) return 0;
10191     size += p->parser_toksiz;
10192     for (local = p->parser_lvtbl; local; local = local->prev) {
10193         size += sizeof(*local);
10194         if (local->vars) size += local->vars->capa * sizeof(ID);
10195     }
10196 #ifndef RIPPER
10197     if (p->parser_ruby_sourcefile) {
10198         size += strlen(p->parser_ruby_sourcefile) + 1;
10199     }
10200 #endif
10201     return size;
10202 }
10203 
10204 static
10205 #ifndef RIPPER
10206 const
10207 #endif
10208 rb_data_type_t parser_data_type = {
10209     "parser",
10210     {
10211         parser_mark,
10212         parser_free,
10213         parser_memsize,
10214     },
10215 };
10216 
10217 #ifndef RIPPER
10218 #undef rb_reserved_word
10219 
10220 const struct kwtable *
10221 rb_reserved_word(const char *str, unsigned int len)
10222 {
10223     return reserved_word(str, len);
10224 }
10225 
10226 static struct parser_params *
10227 parser_new(void)
10228 {
10229     struct parser_params *p;
10230 
10231     p = ALLOC_N(struct parser_params, 1);
10232     MEMZERO(p, struct parser_params, 1);
10233     parser_initialize(p);
10234     return p;
10235 }
10236 
10237 VALUE
10238 rb_parser_new(void)
10239 {
10240     struct parser_params *p = parser_new();
10241 
10242     return TypedData_Wrap_Struct(0, &parser_data_type, p);
10243 }
10244 
10245 /*
10246  *  call-seq:
10247  *    ripper#end_seen?   -> Boolean
10248  *
10249  *  Return true if parsed source ended by +\_\_END\_\_+.
10250  */
10251 VALUE
10252 rb_parser_end_seen_p(VALUE vparser)
10253 {
10254     struct parser_params *parser;
10255 
10256     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10257     return ruby__end__seen ? Qtrue : Qfalse;
10258 }
10259 
10260 /*
10261  *  call-seq:
10262  *    ripper#encoding   -> encoding
10263  *
10264  *  Return encoding of the source.
10265  */
10266 VALUE
10267 rb_parser_encoding(VALUE vparser)
10268 {
10269     struct parser_params *parser;
10270 
10271     TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10272     return rb_enc_from_encoding(parser->enc);
10273 }
10274 
10275 /*
10276  *  call-seq:
10277  *    ripper.yydebug   -> true or false
10278  *
10279  *  Get yydebug.
10280  */
10281 VALUE
10282 rb_parser_get_yydebug(VALUE self)
10283 {
10284     struct parser_params *parser;
10285 
10286     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10287     return yydebug ? Qtrue : Qfalse;
10288 }
10289 
10290 /*
10291  *  call-seq:
10292  *    ripper.yydebug = flag
10293  *
10294  *  Set yydebug.
10295  */
10296 VALUE
10297 rb_parser_set_yydebug(VALUE self, VALUE flag)
10298 {
10299     struct parser_params *parser;
10300 
10301     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10302     yydebug = RTEST(flag);
10303     return flag;
10304 }
10305 
10306 #ifdef YYMALLOC
10307 #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
10308 #define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
10309 #define ADD2HEAP(n, c, p) ((parser->heap = (n))->u1.node = (p), \
10310                            (n)->u3.cnt = (c), (p))
10311 
10312 void *
10313 rb_parser_malloc(struct parser_params *parser, size_t size)
10314 {
10315     size_t cnt = HEAPCNT(1, size);
10316     NODE *n = NEWHEAP();
10317     void *ptr = xmalloc(size);
10318 
10319     return ADD2HEAP(n, cnt, ptr);
10320 }
10321 
10322 void *
10323 rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size)
10324 {
10325     size_t cnt = HEAPCNT(nelem, size);
10326     NODE *n = NEWHEAP();
10327     void *ptr = xcalloc(nelem, size);
10328 
10329     return ADD2HEAP(n, cnt, ptr);
10330 }
10331 
10332 void *
10333 rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size)
10334 {
10335     NODE *n;
10336     size_t cnt = HEAPCNT(1, size);
10337 
10338     if (ptr && (n = parser->heap) != NULL) {
10339         do {
10340             if (n->u1.node == ptr) {
10341                 n->u1.node = ptr = xrealloc(ptr, size);
10342                 if (n->u3.cnt) n->u3.cnt = cnt;
10343                 return ptr;
10344             }
10345         } while ((n = n->u2.node) != NULL);
10346     }
10347     n = NEWHEAP();
10348     ptr = xrealloc(ptr, size);
10349     return ADD2HEAP(n, cnt, ptr);
10350 }
10351 
10352 void
10353 rb_parser_free(struct parser_params *parser, void *ptr)
10354 {
10355     NODE **prev = &parser->heap, *n;
10356 
10357     while ((n = *prev) != NULL) {
10358         if (n->u1.node == ptr) {
10359             *prev = n->u2.node;
10360             rb_gc_force_recycle((VALUE)n);
10361             break;
10362         }
10363         prev = &n->u2.node;
10364     }
10365     xfree(ptr);
10366 }
10367 #endif
10368 #endif
10369 
10370 #ifdef RIPPER
10371 #ifdef RIPPER_DEBUG
10372 extern int rb_is_pointer_to_heap(VALUE);
10373 
10374 /* :nodoc: */
10375 static VALUE
10376 ripper_validate_object(VALUE self, VALUE x)
10377 {
10378     if (x == Qfalse) return x;
10379     if (x == Qtrue) return x;
10380     if (x == Qnil) return x;
10381     if (x == Qundef)
10382         rb_raise(rb_eArgError, "Qundef given");
10383     if (FIXNUM_P(x)) return x;
10384     if (SYMBOL_P(x)) return x;
10385     if (!rb_is_pointer_to_heap(x))
10386         rb_raise(rb_eArgError, "invalid pointer: %p", x);
10387     switch (TYPE(x)) {
10388       case T_STRING:
10389       case T_OBJECT:
10390       case T_ARRAY:
10391       case T_BIGNUM:
10392       case T_FLOAT:
10393         return x;
10394       case T_NODE:
10395         if (nd_type(x) != NODE_LASGN) {
10396             rb_raise(rb_eArgError, "NODE given: %p", x);
10397         }
10398         return ((NODE *)x)->nd_rval;
10399       default:
10400         rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
10401                  x, rb_obj_classname(x));
10402     }
10403     return x;
10404 }
10405 #endif
10406 
10407 #define validate(x) ((x) = get_value(x))
10408 
10409 static VALUE
10410 ripper_dispatch0(struct parser_params *parser, ID mid)
10411 {
10412     return rb_funcall(parser->value, mid, 0);
10413 }
10414 
10415 static VALUE
10416 ripper_dispatch1(struct parser_params *parser, ID mid, VALUE a)
10417 {
10418     validate(a);
10419     return rb_funcall(parser->value, mid, 1, a);
10420 }
10421 
10422 static VALUE
10423 ripper_dispatch2(struct parser_params *parser, ID mid, VALUE a, VALUE b)
10424 {
10425     validate(a);
10426     validate(b);
10427     return rb_funcall(parser->value, mid, 2, a, b);
10428 }
10429 
10430 static VALUE
10431 ripper_dispatch3(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c)
10432 {
10433     validate(a);
10434     validate(b);
10435     validate(c);
10436     return rb_funcall(parser->value, mid, 3, a, b, c);
10437 }
10438 
10439 static VALUE
10440 ripper_dispatch4(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d)
10441 {
10442     validate(a);
10443     validate(b);
10444     validate(c);
10445     validate(d);
10446     return rb_funcall(parser->value, mid, 4, a, b, c, d);
10447 }
10448 
10449 static VALUE
10450 ripper_dispatch5(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e)
10451 {
10452     validate(a);
10453     validate(b);
10454     validate(c);
10455     validate(d);
10456     validate(e);
10457     return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
10458 }
10459 
10460 static const struct kw_assoc {
10461     ID id;
10462     const char *name;
10463 } keyword_to_name[] = {
10464     {keyword_class,     "class"},
10465     {keyword_module,    "module"},
10466     {keyword_def,       "def"},
10467     {keyword_undef,     "undef"},
10468     {keyword_begin,     "begin"},
10469     {keyword_rescue,    "rescue"},
10470     {keyword_ensure,    "ensure"},
10471     {keyword_end,       "end"},
10472     {keyword_if,        "if"},
10473     {keyword_unless,    "unless"},
10474     {keyword_then,      "then"},
10475     {keyword_elsif,     "elsif"},
10476     {keyword_else,      "else"},
10477     {keyword_case,      "case"},
10478     {keyword_when,      "when"},
10479     {keyword_while,     "while"},
10480     {keyword_until,     "until"},
10481     {keyword_for,       "for"},
10482     {keyword_break,     "break"},
10483     {keyword_next,      "next"},
10484     {keyword_redo,      "redo"},
10485     {keyword_retry,     "retry"},
10486     {keyword_in,        "in"},
10487     {keyword_do,        "do"},
10488     {keyword_do_cond,   "do"},
10489     {keyword_do_block,  "do"},
10490     {keyword_return,    "return"},
10491     {keyword_yield,     "yield"},
10492     {keyword_super,     "super"},
10493     {keyword_self,      "self"},
10494     {keyword_nil,       "nil"},
10495     {keyword_true,      "true"},
10496     {keyword_false,     "false"},
10497     {keyword_and,       "and"},
10498     {keyword_or,        "or"},
10499     {keyword_not,       "not"},
10500     {modifier_if,       "if"},
10501     {modifier_unless,   "unless"},
10502     {modifier_while,    "while"},
10503     {modifier_until,    "until"},
10504     {modifier_rescue,   "rescue"},
10505     {keyword_alias,     "alias"},
10506     {keyword_defined,   "defined?"},
10507     {keyword_BEGIN,     "BEGIN"},
10508     {keyword_END,       "END"},
10509     {keyword__LINE__,   "__LINE__"},
10510     {keyword__FILE__,   "__FILE__"},
10511     {keyword__ENCODING__, "__ENCODING__"},
10512     {0, NULL}
10513 };
10514 
10515 static const char*
10516 keyword_id_to_str(ID id)
10517 {
10518     const struct kw_assoc *a;
10519 
10520     for (a = keyword_to_name; a->id; a++) {
10521         if (a->id == id)
10522             return a->name;
10523     }
10524     return NULL;
10525 }
10526 
10527 #undef ripper_id2sym
10528 static VALUE
10529 ripper_id2sym(ID id)
10530 {
10531     const char *name;
10532     char buf[8];
10533 
10534     if (id <= 256) {
10535         buf[0] = (char)id;
10536         buf[1] = '\0';
10537         return ID2SYM(rb_intern2(buf, 1));
10538     }
10539     if ((name = keyword_id_to_str(id))) {
10540         return ID2SYM(rb_intern(name));
10541     }
10542     switch (id) {
10543       case tOROP:
10544         name = "||";
10545         break;
10546       case tANDOP:
10547         name = "&&";
10548         break;
10549       default:
10550         name = rb_id2name(id);
10551         if (!name) {
10552             rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
10553         }
10554         return ID2SYM(id);
10555     }
10556     return ID2SYM(rb_intern(name));
10557 }
10558 
10559 static ID
10560 ripper_get_id(VALUE v)
10561 {
10562     NODE *nd;
10563     if (!RB_TYPE_P(v, T_NODE)) return 0;
10564     nd = (NODE *)v;
10565     if (nd_type(nd) != NODE_LASGN) return 0;
10566     return nd->nd_vid;
10567 }
10568 
10569 static VALUE
10570 ripper_get_value(VALUE v)
10571 {
10572     NODE *nd;
10573     if (v == Qundef) return Qnil;
10574     if (!RB_TYPE_P(v, T_NODE)) return v;
10575     nd = (NODE *)v;
10576     if (nd_type(nd) != NODE_LASGN) return Qnil;
10577     return nd->nd_rval;
10578 }
10579 
10580 static void
10581 ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
10582 {
10583     VALUE str;
10584     va_list args;
10585 
10586     va_start(args, fmt);
10587     str = rb_vsprintf(fmt, args);
10588     va_end(args);
10589     rb_funcall(parser->value, rb_intern("compile_error"), 1, str);
10590 }
10591 
10592 static void
10593 ripper_warn0(struct parser_params *parser, const char *fmt)
10594 {
10595     rb_funcall(parser->value, rb_intern("warn"), 1, STR_NEW2(fmt));
10596 }
10597 
10598 static void
10599 ripper_warnI(struct parser_params *parser, const char *fmt, int a)
10600 {
10601     rb_funcall(parser->value, rb_intern("warn"), 2,
10602                STR_NEW2(fmt), INT2NUM(a));
10603 }
10604 
10605 #if 0
10606 static void
10607 ripper_warnS(struct parser_params *parser, const char *fmt, const char *str)
10608 {
10609     rb_funcall(parser->value, rb_intern("warn"), 2,
10610                STR_NEW2(fmt), STR_NEW2(str));
10611 }
10612 #endif
10613 
10614 static void
10615 ripper_warning0(struct parser_params *parser, const char *fmt)
10616 {
10617     rb_funcall(parser->value, rb_intern("warning"), 1, STR_NEW2(fmt));
10618 }
10619 
10620 static void
10621 ripper_warningS(struct parser_params *parser, const char *fmt, const char *str)
10622 {
10623     rb_funcall(parser->value, rb_intern("warning"), 2,
10624                STR_NEW2(fmt), STR_NEW2(str));
10625 }
10626 
10627 static VALUE
10628 ripper_lex_get_generic(struct parser_params *parser, VALUE src)
10629 {
10630     return rb_funcall(src, ripper_id_gets, 0);
10631 }
10632 
10633 static VALUE
10634 ripper_s_allocate(VALUE klass)
10635 {
10636     struct parser_params *p;
10637     VALUE self;
10638 
10639     p = ALLOC_N(struct parser_params, 1);
10640     MEMZERO(p, struct parser_params, 1);
10641     self = TypedData_Wrap_Struct(klass, &parser_data_type, p);
10642     p->value = self;
10643     return self;
10644 }
10645 
10646 #define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
10647 
10648 /*
10649  *  call-seq:
10650  *    Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
10651  *
10652  *  Create a new Ripper object.
10653  *  _src_ must be a String, an IO, or an Object which has #gets method.
10654  *
10655  *  This method does not starts parsing.
10656  *  See also Ripper#parse and Ripper.parse.
10657  */
10658 static VALUE
10659 ripper_initialize(int argc, VALUE *argv, VALUE self)
10660 {
10661     struct parser_params *parser;
10662     VALUE src, fname, lineno;
10663 
10664     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10665     rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
10666     if (rb_obj_respond_to(src, ripper_id_gets, 0)) {
10667         parser->parser_lex_gets = ripper_lex_get_generic;
10668     }
10669     else {
10670         StringValue(src);
10671         parser->parser_lex_gets = lex_get_str;
10672     }
10673     parser->parser_lex_input = src;
10674     parser->eofp = Qfalse;
10675     if (NIL_P(fname)) {
10676         fname = STR_NEW2("(ripper)");
10677     }
10678     else {
10679         StringValue(fname);
10680     }
10681     parser_initialize(parser);
10682 
10683     parser->parser_ruby_sourcefile_string = fname;
10684     parser->parser_ruby_sourcefile = RSTRING_PTR(fname);
10685     parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
10686 
10687     return Qnil;
10688 }
10689 
10690 struct ripper_args {
10691     struct parser_params *parser;
10692     int argc;
10693     VALUE *argv;
10694 };
10695 
10696 static VALUE
10697 ripper_parse0(VALUE parser_v)
10698 {
10699     struct parser_params *parser;
10700 
10701     TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10702     parser_prepare(parser);
10703     ripper_yyparse((void*)parser);
10704     return parser->result;
10705 }
10706 
10707 static VALUE
10708 ripper_ensure(VALUE parser_v)
10709 {
10710     struct parser_params *parser;
10711 
10712     TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10713     parser->parsing_thread = Qnil;
10714     return Qnil;
10715 }
10716 
10717 /*
10718  *  call-seq:
10719  *    ripper#parse
10720  *
10721  *  Start parsing and returns the value of the root action.
10722  */
10723 static VALUE
10724 ripper_parse(VALUE self)
10725 {
10726     struct parser_params *parser;
10727 
10728     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10729     if (!ripper_initialized_p(parser)) {
10730         rb_raise(rb_eArgError, "method called for uninitialized object");
10731     }
10732     if (!NIL_P(parser->parsing_thread)) {
10733         if (parser->parsing_thread == rb_thread_current())
10734             rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
10735         else
10736             rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
10737     }
10738     parser->parsing_thread = rb_thread_current();
10739     rb_ensure(ripper_parse0, self, ripper_ensure, self);
10740 
10741     return parser->result;
10742 }
10743 
10744 /*
10745  *  call-seq:
10746  *    ripper#column   -> Integer
10747  *
10748  *  Return column number of current parsing line.
10749  *  This number starts from 0.
10750  */
10751 static VALUE
10752 ripper_column(VALUE self)
10753 {
10754     struct parser_params *parser;
10755     long col;
10756 
10757     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10758     if (!ripper_initialized_p(parser)) {
10759         rb_raise(rb_eArgError, "method called for uninitialized object");
10760     }
10761     if (NIL_P(parser->parsing_thread)) return Qnil;
10762     col = parser->tokp - parser->parser_lex_pbeg;
10763     return LONG2NUM(col);
10764 }
10765 
10766 /*
10767  *  call-seq:
10768  *    ripper#filename   -> String
10769  *
10770  *  Return current parsing filename.
10771  */
10772 static VALUE
10773 ripper_filename(VALUE self)
10774 {
10775     struct parser_params *parser;
10776 
10777     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10778     if (!ripper_initialized_p(parser)) {
10779         rb_raise(rb_eArgError, "method called for uninitialized object");
10780     }
10781     return parser->parser_ruby_sourcefile_string;
10782 }
10783 
10784 /*
10785  *  call-seq:
10786  *    ripper#lineno   -> Integer
10787  *
10788  *  Return line number of current parsing line.
10789  *  This number starts from 1.
10790  */
10791 static VALUE
10792 ripper_lineno(VALUE self)
10793 {
10794     struct parser_params *parser;
10795 
10796     TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10797     if (!ripper_initialized_p(parser)) {
10798         rb_raise(rb_eArgError, "method called for uninitialized object");
10799     }
10800     if (NIL_P(parser->parsing_thread)) return Qnil;
10801     return INT2NUM(parser->parser_ruby_sourceline);
10802 }
10803 
10804 #ifdef RIPPER_DEBUG
10805 /* :nodoc: */
10806 static VALUE
10807 ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
10808 {
10809     StringValue(msg);
10810     if (obj == Qundef) {
10811         rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
10812     }
10813     return Qnil;
10814 }
10815 
10816 /* :nodoc: */
10817 static VALUE
10818 ripper_value(VALUE self, VALUE obj)
10819 {
10820     return ULONG2NUM(obj);
10821 }
10822 #endif
10823 
10824 
10825 void
10826 InitVM_ripper(void)
10827 {
10828     parser_data_type.parent = RTYPEDDATA_TYPE(rb_parser_new());
10829 }
10830 
10831 void
10832 Init_ripper(void)
10833 {
10834     VALUE Ripper;
10835 
10836     InitVM(ripper);
10837     Ripper = rb_define_class("Ripper", rb_cObject);
10838     rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
10839     rb_define_alloc_func(Ripper, ripper_s_allocate);
10840     rb_define_method(Ripper, "initialize", ripper_initialize, -1);
10841     rb_define_method(Ripper, "parse", ripper_parse, 0);
10842     rb_define_method(Ripper, "column", ripper_column, 0);
10843     rb_define_method(Ripper, "filename", ripper_filename, 0);
10844     rb_define_method(Ripper, "lineno", ripper_lineno, 0);
10845     rb_define_method(Ripper, "end_seen?", rb_parser_end_seen_p, 0);
10846     rb_define_method(Ripper, "encoding", rb_parser_encoding, 0);
10847     rb_define_method(Ripper, "yydebug", rb_parser_get_yydebug, 0);
10848     rb_define_method(Ripper, "yydebug=", rb_parser_set_yydebug, 1);
10849 #ifdef RIPPER_DEBUG
10850     rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
10851     rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
10852     rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
10853 #endif
10854 
10855     ripper_id_gets = rb_intern("gets");
10856     ripper_init_eventids1(Ripper);
10857     ripper_init_eventids2(Ripper);
10858     /* ensure existing in symbol table */
10859     (void)rb_intern("||");
10860     (void)rb_intern("&&");
10861 
10862 # if 0
10863     /* Hack to let RDoc document SCRIPT_LINES__ */
10864 
10865     /*
10866      * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
10867      * after the assignment will be added as an Array of lines with the file
10868      * name as the key.
10869      */
10870     rb_define_global_const("SCRIPT_LINES__", Qnil);
10871 #endif
10872 
10873 }
10874 #endif /* RIPPER */
10875