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