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