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