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