ext/ripper/ripper.y

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7