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