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