From: Nobuyoshi Nakada Date: 2007-05-02T10:28:32+09:00 Subject: [ruby-dev:30744] Re: ObjectC style keyword argument なかだです。 At Fri, 27 Apr 2007 01:12:18 +0900, Yukihiro Matsumoto wrote in [ruby-dev:30737]: > メソッド定義は > か、あるいは > > def copy: x from: y; p [x, y] end これってやはりカンマなしですか? Index: parse.y =================================================================== --- parse.y (revision 12239) +++ parse.y (working copy) @@ -538,4 +538,9 @@ static void ripper_compile_error(struct #endif +ID rb_alist_id(VALUE); +#ifndef RIPPER +static void assoc_arg_vars(struct parser_params *, NODE *); +#endif + %} @@ -622,4 +627,5 @@ static void ripper_compile_error(struct %type f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_head f_margs %type assoc_list assocs assoc undef_list backref string_dvar for_var +%type assoc_call assoc_arg assoc_fargs assoc_farg %type block_param opt_block_param block_param_def f_opt %type bv_decls opt_bv_decl bvar @@ -1049,4 +1055,17 @@ stmt : keyword_alias fitem {lex_state = %*/ } + | primary_value '.' assoc_call + { + /*%%%*/ + ID associd = rb_alist_id($3->nd_lit); + $3->nd_next->nd_alen = $3->nd_alen - 1; + $$ = NEW_CALL($1, associd, $3->nd_next); + fixpos($$, $1); + /*% + $$ = dispatch3(call, $1, ripper_id2sym('.'), + ID2SYM(rb_alist_id(rb_ary_shift($3)))); + $$ = method_arg($$, $3); + %*/ + } | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call { @@ -2839,4 +2858,65 @@ primary : literal %*/ } + | keyword_def assoc_fargs + { + /*%%%*/ + $$ = cur_mid; + cur_mid = rb_alist_id($2->nd_tval); + in_def++; + local_push(0); + assoc_arg_vars(parser, $2->nd_var); + $2->nd_var = 0; + /*% + %*/ + lex_state = EXPR_BEG; + } + bodystmt + keyword_end + { + /*%%%*/ + NODE *body = remove_begin($4); + reduce_nodes(&body); + $$ = NEW_DEFN(cur_mid, NEW_ARGS(RARRAY_LEN($2->nd_tval), 0), + body, NOEX_PRIVATE); + fixpos($$, $2); + local_pop(); + in_def--; + cur_mid = $3; + /*% + $$ = dispatch3(def, rb_alist_id(RARRAY_PTR($2)[0]), + RARRAY_PTR($2)[1], $5); + in_def--; + cur_mid = $3; + %*/ + } + | keyword_def singleton dot_or_colon {lex_state = EXPR_FNAME;} + assoc_fargs + { + in_single++; + /*%%%*/ + local_push(0); + assoc_arg_vars(parser, $5->nd_var); + $5->nd_var = 0; + /*% + %*/ + lex_state = EXPR_BEG; + } + bodystmt + keyword_end + { + /*%%%*/ + NODE *body = remove_begin($7); + reduce_nodes(&body); + $$ = NEW_DEFS($2, rb_alist_id($5->nd_tval), + NEW_ARGS(RARRAY_LEN($5->nd_tval), 0), body); + fixpos($$, $2); + local_pop(); + /*% + $$ = dispatch5(defs, $2, $3, + ID2SYM(rb_alist_id(RARRAY_PTR($5)[0])), + RARRAY_PTR($5)[1], $7); + %*/ + in_single--; + } | keyword_break { @@ -4338,4 +4418,69 @@ assoc : arg_value tASSOC arg_value ; +assoc_call : assoc_arg + | assoc_call ',' assoc_arg + { + /*%%%*/ + rb_ary_concat($1->nd_lit, $3->nd_lit); + $$ = list_concat($1, $3->nd_next); + /*% + rb_ary_push(rb_ary_entry($1, 0), rb_ary_entry($3, 0)); + rb_ary_push($1, rb_ary_entry($3, 1)); + %*/ + } + +assoc_arg : tLABEL arg_value + { + /*%%%*/ + $$ = list_append(NEW_LIST(rb_ary_new3(1, ID2SYM($1))), $2); + /*% + $$ = rb_assoc_new(rb_ary_new3(1, $1), $2); + %*/ + } + ; + +assoc_fargs : assoc_farg + { + /*%%%*/ + ID pid = $1->nd_pid, mid = $1->nd_mid; + rb_gc_force_recycle((VALUE)$1); + $$ = NEW_ARGS(rb_ary_new3(1, ID2SYM(pid)), + NEW_LIST((NODE *)mid)); + /* nd_tval, nd_var */ + /*% + $$ = $1; + RARRAY_PTR($$)[0] = rb_ary_new3(1, RARRAY_PTR($1)[0]); + RARRAY_PTR($$)[1] = rb_ary_new3(1, RARRAY_PTR($1)[1]); + %*/ + } + | assoc_fargs opt_comma assoc_farg + { + /*%%%*/ + ID pid = $3->nd_pid, mid = $3->nd_mid; + rb_gc_force_recycle((VALUE)$3); + $$ = $1; + rb_ary_push($$->nd_tval, ID2SYM(pid)); + $$->nd_var = list_append($$->nd_var, (NODE *)mid); + /*% + $$ = $1; + rb_ary_push(RARRAY_PTR($$)[0], RARRAY_PTR($3)[0]); + rb_ary_push(RARRAY_PTR($$)[1], RARRAY_PTR($3)[1]); + %*/ + } + ; +assoc_farg : tLABEL f_norm_arg + { + /*%%%*/ + if (!is_local_id($2)) + yyerror("formal argument must be local variable"); + $$ = NEW_ARGS_AUX($1, $2); + /*% + $$ = dispatch2(assoc_farg, $1, $2); + NEED_ASSOC($$, $1, $2); + %*/ + lex_state = EXPR_FNAME; + } + ; + operation : tIDENTIFIER | tCONSTANT @@ -4374,4 +4519,9 @@ opt_nl : /* none */ ; +opt_comma : /* none */ + | ',' + {lex_state = EXPR_FNAME;} + ; + rparen : opt_nl ')' ; @@ -6804,4 +6954,6 @@ parser_yylex(struct parser_params *parse if ((lex_state == EXPR_BEG && !cmd_state) || lex_state == EXPR_ARG || + lex_state == EXPR_DOT || + lex_state == EXPR_FNAME || lex_state == EXPR_CMDARG) { if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) { @@ -8510,4 +8662,27 @@ rb_id2name(ID id) } +ID +rb_alist_id(VALUE names) +{ + VALUE name = rb_str_cat(rb_ary_join(names, rb_str_new2(":")), ":", 1); + return rb_intern2(RSTRING_PTR(name), RSTRING_LEN(name)); +} + +#ifndef RIPPER +static void +assoc_arg_vars(struct parser_params *parser, NODE *var) +{ + while (var) { + NODE *next = var->nd_next; + ID id = var->nd_pid; + + rb_gc_force_recycle((VALUE)var); + shadowing_lvar(id); + arg_var(id); + var = next; + } +} +#endif + static int symbols_i(VALUE sym, ID value, VALUE ary) -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦