parse.y

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

Generated on Wed Aug 10 09:17:11 2011 for Ruby by  doxygen 1.4.7