• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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

Generated on Sat Jul 7 2012 15:29:22 for Ruby by  doxygen 1.7.1