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