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