diff --git a/parse.y b/parse.y index e325c5c..5ca6b5f 100644 --- a/parse.y +++ b/parse.y @@ -26,6 +26,16 @@ #include #include +#ifdef RIPPER +typedef struct RIPPER_YYSTYPE { + VALUE val; + NODE *node; + ID id; + int num; +} RIPPER_YYSTYPE; +#define YYSTYPE RIPPER_YYSTYPE +#endif + #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) #define YYMALLOC(size) rb_parser_malloc(parser, size) @@ -105,7 +115,6 @@ struct local_vars { #define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl)) #define POINTER_P(val) ((VALUE)(val) & ~(VALUE)3) -#ifndef RIPPER static int vtable_size(const struct vtable *tbl) { @@ -181,7 +190,6 @@ typedef struct token_info { int nonspc; struct token_info *next; } token_info; -#endif /* Structure of Lexer Buffer: @@ -374,8 +382,11 @@ static NODE *call_uni_op_gen(struct parser_params*,NODE*,ID); static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,ID); #define new_args(f,o,r,p,b) new_args_gen(parser, f,o,r,p,b) + +#endif /* !RIPPER */ static void shadowing_lvar_gen(struct parser_params*,ID); #define shadowing_lvar(name) shadowing_lvar_gen(parser, name) +#ifndef RIPPER static NODE *negate_lit(NODE*); static NODE *ret_args_gen(struct parser_params*,NODE*); @@ -388,8 +399,16 @@ static NODE *gettable_gen(struct parser_params*,ID); #define gettable(id) gettable_gen(parser,id) static NODE *assignable_gen(struct parser_params*,ID,NODE*); #define assignable(id,node) assignable_gen(parser, id, node) + +#else /* if RIPPER */ +static void assignment_var_gen(struct parser_params*,ID); +#define assignment_var(id) assignment_var_gen(parser, id) +#endif /* !RIPPER */ + static void new_bv_gen(struct parser_params*,ID); #define new_bv(id) new_bv_gen(parser, id) + +#ifndef RIPPER static NODE *aryset_gen(struct parser_params*,NODE*,NODE*); #define aryset(node1,node2) aryset_gen(parser, node1, node2) static NODE *attrset_gen(struct parser_params*,NODE*,ID); @@ -403,6 +422,7 @@ static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*); static NODE *match_op_gen(struct parser_params*,NODE*,NODE*); #define match_op(node1,node2) match_op_gen(parser, node1, node2) +#endif /* !RIPPER */ static void local_push_gen(struct parser_params*,int); #define local_push(top) local_push_gen(parser,top) static void local_pop_gen(struct parser_params*); @@ -429,11 +449,14 @@ static int dvar_defined_gen(struct parser_params*,ID); #define dvar_defined(id) dvar_defined_gen(parser, id) static int dvar_curr_gen(struct parser_params*,ID); #define dvar_curr(id) dvar_curr_gen(parser, id) +#ifndef RIPPER static void fixup_nodes(NODE **); +#endif /* !RIPPER */ extern int rb_dvar_defined(ID); extern int rb_local_defined(ID); +#ifndef RIPPER extern int rb_parse_in_eval(void); extern int rb_parse_in_main(void); @@ -763,6 +786,7 @@ program : { $$ = compile_for_eval || rb_parse_in_main(); local_push($$); /*% + local_push(1); %*/ } compstmt @@ -780,11 +804,11 @@ program : { } } ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2)); - local_pop(); /*% $$ = $2; parser->result = dispatch1(program, $$); %*/ + local_pop(); } ; @@ -1235,8 +1259,8 @@ block_command : block_call cmd_brace_block : tLBRACE_ARG { - /*%%%*/ dyna_push(); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ @@ -1248,10 +1272,10 @@ cmd_brace_block : tLBRACE_ARG /*%%%*/ $$ = NEW_ITER($3,$4); nd_set_line($$, $2); - dyna_pop(); /*% $$ = dispatch2(brace_block, escape_Qundef($3), $4); %*/ + dyna_pop(); } ; @@ -1518,6 +1542,7 @@ mlhs_node : variable /*%%%*/ $$ = assignable($1, 0); /*% + assignment_var($1); $$ = $1; %*/ } @@ -1592,6 +1617,7 @@ lhs : variable /*%%%*/ if (!($$ = assignable($1, 0))) $$ = NEW_BEGIN(0); /*% + assignment_var($1); $$ = dispatch1(var_field, $1); %*/ } @@ -2807,8 +2833,8 @@ primary : literal { if (in_def || in_single) yyerror("class definition in method body"); - /*%%%*/ local_push(0); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ @@ -2819,10 +2845,10 @@ primary : literal /*%%%*/ $$ = NEW_CLASS($2, $5, $3); nd_set_line($$, $4); - local_pop(); /*% $$ = dispatch3(class, $2, $3, $5); %*/ + local_pop(); } | k_class tLSHFT expr { @@ -2833,10 +2859,7 @@ primary : literal { $$ = in_single; in_single = 0; - /*%%%*/ local_push(0); - /*% - %*/ } bodystmt k_end @@ -2844,10 +2867,10 @@ primary : literal /*%%%*/ $$ = NEW_SCLASS($3, $7); fixpos($$, $3); - local_pop(); /*% $$ = dispatch2(sclass, $3, $7); %*/ + local_pop(); in_def = $4; in_single = $6; } @@ -2855,8 +2878,8 @@ primary : literal { if (in_def || in_single) yyerror("module definition in method body"); - /*%%%*/ local_push(0); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ @@ -2867,20 +2890,17 @@ primary : literal /*%%%*/ $$ = NEW_MODULE($2, $4); nd_set_line($$, $3); - local_pop(); /*% $$ = dispatch2(module, $2, $4); %*/ + local_pop(); } | k_def fname { $$ = cur_mid; cur_mid = $2; in_def++; - /*%%%*/ local_push(0); - /*% - %*/ } f_arglist bodystmt @@ -2891,10 +2911,10 @@ primary : literal reduce_nodes(&body); $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE); fixpos($$, $4); - local_pop(); /*% $$ = dispatch3(def, $2, $4, $5); %*/ + local_pop(); in_def--; cur_mid = $3; } @@ -2902,10 +2922,7 @@ primary : literal { in_single++; lex_state = EXPR_END; /* force for args */ - /*%%%*/ local_push(0); - /*% - %*/ } f_arglist bodystmt @@ -2916,10 +2933,10 @@ primary : literal reduce_nodes(&body); $$ = NEW_DEFS($2, $5, $7, body); fixpos($$, $2); - local_pop(); /*% $$ = dispatch5(defs, $2, $3, $5, $7, $8); %*/ + local_pop(); in_single--; } | keyword_break @@ -3111,6 +3128,7 @@ f_marg : f_norm_arg /*%%%*/ $$ = assignable($1, 0); /*% + assignment_var($1); $$ = dispatch1(mlhs_paren, $1); %*/ } @@ -3155,6 +3173,7 @@ f_margs : f_marg_list /*%%%*/ $$ = NEW_MASGN($1, assignable($4, 0)); /*% + assignment_var($4); $$ = mlhs_add_star($1, $4); %*/ } @@ -3163,6 +3182,7 @@ f_margs : f_marg_list /*%%%*/ $$ = NEW_MASGN($1, NEW_POSTARG(assignable($4, 0), $6)); /*% + assignment_var($4); $$ = mlhs_add_star($1, $4); %*/ } @@ -3187,6 +3207,7 @@ f_margs : f_marg_list /*%%%*/ $$ = NEW_MASGN(0, assignable($2, 0)); /*% + assignment_var($2); $$ = mlhs_add_star(mlhs_new(), $2); %*/ } @@ -3198,6 +3219,7 @@ f_margs : f_marg_list #if 0 TODO: Check me #endif + assignment_var($2); $$ = mlhs_add_star($2, $4); %*/ } @@ -3407,8 +3429,8 @@ bv_decls : bvar bvar : tIDENTIFIER { - /*%%%*/ new_bv($1); + /*%%%*/ /*% $$ = $1; %*/ @@ -3420,10 +3442,7 @@ bvar : tIDENTIFIER ; lambda : { - /*%%%*/ dyna_push(); - /*% - %*/ $$ = lpar_beg; lpar_beg = ++paren_nest; } @@ -3434,10 +3453,10 @@ lambda : { /*%%%*/ $$ = $2; $$->nd_body = NEW_SCOPE($2->nd_head, $3); - dyna_pop(); /*% $$ = dispatch2(lambda, $2, $3); %*/ + dyna_pop(); } ; @@ -3471,8 +3490,8 @@ lambda_body : tLAMBEG compstmt '}' do_block : keyword_do_block { - /*%%%*/ dyna_push(); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ } @@ -3483,10 +3502,10 @@ do_block : keyword_do_block /*%%%*/ $$ = NEW_ITER($3,$4); nd_set_line($$, $2); - dyna_pop(); /*% $$ = dispatch2(do_block, escape_Qundef($3), $4); %*/ + dyna_pop(); } ; @@ -3617,8 +3636,8 @@ method_call : operation paren_args brace_block : '{' { - /*%%%*/ dyna_push(); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ @@ -3629,15 +3648,15 @@ brace_block : '{' /*%%%*/ $$ = NEW_ITER($3,$4); nd_set_line($$, $2); - dyna_pop(); /*% $$ = dispatch2(brace_block, escape_Qundef($3), $4); %*/ + dyna_pop(); } | keyword_do { - /*%%%*/ dyna_push(); + /*%%%*/ $$ = ruby_sourceline; /*% %*/ @@ -3648,10 +3667,10 @@ brace_block : '{' /*%%%*/ $$ = NEW_ITER($3,$4); nd_set_line($$, $2); - dyna_pop(); /*% $$ = dispatch2(do_block, escape_Qundef($3), $4); %*/ + dyna_pop(); } ; @@ -4130,6 +4149,7 @@ var_lhs : variable /*%%%*/ $$ = assignable($1, 0); /*% + assignment_var($1); $$ = dispatch1(var_field, $1); %*/ } @@ -4349,26 +4369,26 @@ f_norm_arg : f_bad_arg /*%%%*/ if (!is_local_id($1)) yyerror("formal argument must be local variable"); - shadowing_lvar($1); /*% %*/ + shadowing_lvar($1); $$ = $1; } ; f_arg_item : f_norm_arg { + arg_var($1); /*%%%*/ - arg_var($1); $$ = NEW_ARGS_AUX($1, 1); /*% %*/ } | tLPAREN f_margs rparen { - /*%%%*/ ID tid = internal_id(); arg_var(tid); + /*%%%*/ if (dyna_in_block()) { $2->nd_value = NEW_DVAR(tid); } @@ -4405,13 +4425,14 @@ f_arg : f_arg_item f_opt : tIDENTIFIER '=' arg_value { + shadowing_lvar($1); + arg_var($1); /*%%%*/ if (!is_local_id($1)) yyerror("formal argument must be local variable"); - shadowing_lvar($1); - arg_var($1); $$ = NEW_OPT_ARG(0, assignable($1, $3)); /*% + assignment_var($1); $$ = rb_assoc_new($1, $3); %*/ } @@ -4419,13 +4440,14 @@ f_opt : tIDENTIFIER '=' arg_value f_block_opt : tIDENTIFIER '=' primary_value { + shadowing_lvar($1); + arg_var($1); /*%%%*/ if (!is_local_id($1)) yyerror("formal argument must be local variable"); - shadowing_lvar($1); - arg_var($1); $$ = NEW_OPT_ARG(0, assignable($1, $3)); /*% + assignment_var($1); $$ = rb_assoc_new($1, $3); %*/ } @@ -4485,11 +4507,11 @@ restarg_mark : '*' f_rest_arg : restarg_mark tIDENTIFIER { + shadowing_lvar($2); + arg_var($2); /*%%%*/ if (!is_local_id($2)) yyerror("rest argument must be local variable"); - shadowing_lvar($2); - arg_var($2); $$ = $2; /*% $$ = dispatch1(rest_param, $2); @@ -4497,9 +4519,10 @@ f_rest_arg : restarg_mark tIDENTIFIER } | restarg_mark { + ID tid = internal_id(); + arg_var(tid); /*%%%*/ - $$ = internal_id(); - arg_var($$); + $$ = tid; /*% $$ = dispatch1(rest_param, Qnil); %*/ @@ -4517,12 +4540,12 @@ f_block_arg : blkarg_mark tIDENTIFIER yyerror("block argument must be local variable"); else if (!dyna_in_block() && local_id($2)) yyerror("duplicated block argument name"); - shadowing_lvar($2); - arg_var($2); $$ = $2; /*% $$ = dispatch1(blockarg, $2); %*/ + shadowing_lvar($2); + arg_var($2); } ; @@ -4719,12 +4742,6 @@ static int parser_here_document(struct parser_params*,NODE*); # define heredoc_restore(n) parser_heredoc_restore(parser,n) # define whole_match_p(e,l,i) parser_whole_match_p(parser,e,l,i) -#ifdef RIPPER -/* FIXME */ -# define local_id(x) 1 -# define dyna_in_block() 1 -#endif /* RIPPER */ - #ifndef RIPPER # define set_yylval_str(x) yylval.node = NEW_STR(x) # define set_yylval_num(x) yylval.num = x @@ -4735,10 +4752,10 @@ static int parser_here_document(struct parser_params*,NODE*); #else # define set_yylval_str(x) (void)(x) # define set_yylval_num(x) (void)(x) -# define set_yylval_id(x) (void)(x) +# define set_yylval_id(x) yylval.id = x # define set_yylval_literal(x) (void)(x) # define set_yylval_node(x) (void)(x) -# define yylval_id() SYM2ID(yylval.val) +# define yylval_id() yylval.id #endif #ifdef RIPPER @@ -6051,11 +6068,7 @@ arg_ambiguous_gen(struct parser_params *parser) static int lvar_defined_gen(struct parser_params *parser, ID id) { -#ifndef RIPPER return (dyna_in_block() && dvar_defined(id)) || local_id(id); -#else - return 0; -#endif } /* emacsen -*- hack */ @@ -8062,6 +8075,23 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val) } return 0; } +#endif /* !RIPPER */ + +static void +assignment_var_gen(struct parser_params *parser, ID name) +{ + if (!name || !is_local_id(name)) return; + + if (dyna_in_block()) { + if (!dvar_defined(name) && !local_id(name)) { + dyna_var(name); + } + } else { + if (!local_id(name)) { + local_var(name); + } + } +} static void shadowing_lvar_gen(struct parser_params *parser, ID name) @@ -8098,6 +8128,7 @@ new_bv_gen(struct parser_params *parser, ID name) shadowing_lvar(name); dyna_var(name); } +#ifndef RIPPER static NODE * aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx) @@ -8750,6 +8781,7 @@ new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b return node; } +#endif /* !RIPPER */ static void local_push_gen(struct parser_params *parser, int inherit_dvars) { @@ -8895,6 +8927,7 @@ dvar_curr_gen(struct parser_params *parser, ID id) return (vtable_included(lvtbl->args, id) || vtable_included(lvtbl->vars, id)); } +#ifndef RIPPER VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline); VALUE rb_reg_check_preprocess(VALUE); @@ -9229,6 +9262,7 @@ rb_gc_mark_symbols(void) global_symbols.op_sym + tLAST_TOKEN); } +#endif /* !RIPPER */ static ID internal_id_gen(struct parser_params *parser) { @@ -9236,6 +9270,7 @@ internal_id_gen(struct parser_params *parser) id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1; return ID_INTERNAL | (id << ID_SCOPE_SHIFT); } +#ifndef RIPPER static int is_special_global_name(const char *m, const char *e, rb_encoding *enc) diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index fa640a3..9b0985a 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -492,6 +492,15 @@ class TestRipper_ParserEvents < Test::Unit::TestCase end =end + def test_local_variables + cmd = 'command(w,[regexp_literal(xstring_add(xstring_new(),25 # ),/)])' + div = 'binary(ref(w),/,25)' + + assert_equal "[#{cmd}]", parse('w /25 # /') + assert_equal "[assign(var_field(w),1),#{div}]", parse("w = 1; w /25 # /") + assert_equal "[fcall(p,[],&block([w],[#{div}]))]", parse("p{|w|w /25 # /\n}") + assert_equal "[def(p,[w],body_stmt([binary(ref(w),/,25)],,,))]", parse("def p(w)\nw /25 # /\nend") + end end rescue LoadError