Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/ripper/ripper.y

Go to the documentation of this file.

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