Project

General

Profile

Backport #1939 ยป patch.diff

Patch - judofyr (Magnus Holm), 10/01/2009 11:19 PM

View differences:

parse.y
#include <errno.h>
#include <ctype.h>
#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)
......
#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)
{
......
int nonspc;
struct token_info *next;
} token_info;
#endif
/*
Structure of Lexer Buffer:
......
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*);
......
#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);
......
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*);
......
#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);
......
$<num>$ = compile_for_eval || rb_parse_in_main();
local_push($<num>$);
/*%
local_push(1);
%*/
}
compstmt
......
}
}
ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2));
local_pop();
/*%
$$ = $2;
parser->result = dispatch1(program, $$);
%*/
local_pop();
}
;
......
cmd_brace_block : tLBRACE_ARG
{
/*%%%*/
dyna_push();
/*%%%*/
$<num>$ = ruby_sourceline;
/*%
%*/
......
/*%%%*/
$$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
$$ = dispatch2(brace_block, escape_Qundef($3), $4);
%*/
dyna_pop();
}
;
......
/*%%%*/
$$ = assignable($1, 0);
/*%
assignment_var($<id>1);
$$ = $1;
%*/
}
......
/*%%%*/
if (!($$ = assignable($1, 0))) $$ = NEW_BEGIN(0);
/*%
assignment_var($<id>1);
$$ = dispatch1(var_field, $1);
%*/
}
......
{
if (in_def || in_single)
yyerror("class definition in method body");
/*%%%*/
local_push(0);
/*%%%*/
$<num>$ = ruby_sourceline;
/*%
%*/
......
/*%%%*/
$$ = NEW_CLASS($2, $5, $3);
nd_set_line($$, $<num>4);
local_pop();
/*%
$$ = dispatch3(class, $2, $3, $5);
%*/
local_pop();
}
| k_class tLSHFT expr
{
......
{
$<num>$ = in_single;
in_single = 0;
/*%%%*/
local_push(0);
/*%
%*/
}
bodystmt
k_end
......
/*%%%*/
$$ = NEW_SCLASS($3, $7);
fixpos($$, $3);
local_pop();
/*%
$$ = dispatch2(sclass, $3, $7);
%*/
local_pop();
in_def = $<num>4;
in_single = $<num>6;
}
......
{
if (in_def || in_single)
yyerror("module definition in method body");
/*%%%*/
local_push(0);
/*%%%*/
$<num>$ = ruby_sourceline;
/*%
%*/
......
/*%%%*/
$$ = NEW_MODULE($2, $4);
nd_set_line($$, $<num>3);
local_pop();
/*%
$$ = dispatch2(module, $2, $4);
%*/
local_pop();
}
| k_def fname
{
$<id>$ = cur_mid;
cur_mid = $2;
in_def++;
/*%%%*/
local_push(0);
/*%
%*/
}
f_arglist
bodystmt
......
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 = $<id>3;
}
......
{
in_single++;
lex_state = EXPR_END; /* force for args */
/*%%%*/
local_push(0);
/*%
%*/
}
f_arglist
bodystmt
......
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
......
/*%%%*/
$$ = assignable($1, 0);
/*%
assignment_var($<id>1);
$$ = dispatch1(mlhs_paren, $1);
%*/
}
......
/*%%%*/
$$ = NEW_MASGN($1, assignable($4, 0));
/*%
assignment_var($<id>4);
$$ = mlhs_add_star($1, $4);
%*/
}
......
/*%%%*/
$$ = NEW_MASGN($1, NEW_POSTARG(assignable($4, 0), $6));
/*%
assignment_var($<id>4);
$$ = mlhs_add_star($1, $4);
%*/
}
......
/*%%%*/
$$ = NEW_MASGN(0, assignable($2, 0));
/*%
assignment_var($<id>2);
$$ = mlhs_add_star(mlhs_new(), $2);
%*/
}
......
#if 0
TODO: Check me
#endif
assignment_var($<id>2);
$$ = mlhs_add_star($2, $4);
%*/
}
......
bvar : tIDENTIFIER
{
/*%%%*/
new_bv($1);
/*%%%*/
/*%
$$ = $1;
%*/
......
;
lambda : {
/*%%%*/
dyna_push();
/*%
%*/
$<num>$ = lpar_beg;
lpar_beg = ++paren_nest;
}
......
/*%%%*/
$$ = $2;
$$->nd_body = NEW_SCOPE($2->nd_head, $3);
dyna_pop();
/*%
$$ = dispatch2(lambda, $2, $3);
%*/
dyna_pop();
}
;
......
do_block : keyword_do_block
{
/*%%%*/
dyna_push();
/*%%%*/
$<num>$ = ruby_sourceline;
/*% %*/
}
......
/*%%%*/
$$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
$$ = dispatch2(do_block, escape_Qundef($3), $4);
%*/
dyna_pop();
}
;
......
brace_block : '{'
{
/*%%%*/
dyna_push();
/*%%%*/
$<num>$ = ruby_sourceline;
/*%
%*/
......
/*%%%*/
$$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
$$ = dispatch2(brace_block, escape_Qundef($3), $4);
%*/
dyna_pop();
}
| keyword_do
{
/*%%%*/
dyna_push();
/*%%%*/
$<num>$ = ruby_sourceline;
/*%
%*/
......
/*%%%*/
$$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
dyna_pop();
/*%
$$ = dispatch2(do_block, escape_Qundef($3), $4);
%*/
dyna_pop();
}
;
......
/*%%%*/
$$ = assignable($1, 0);
/*%
assignment_var($<id>1);
$$ = dispatch1(var_field, $1);
%*/
}
......
/*%%%*/
if (!is_local_id($1))
yyerror("formal argument must be local variable");
shadowing_lvar($1);
/*%
%*/
shadowing_lvar($<id>1);
$$ = $1;
}
;
f_arg_item : f_norm_arg
{
arg_var($<id>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);
}
......
f_opt : tIDENTIFIER '=' arg_value
{
shadowing_lvar($<id>1);
arg_var($<id>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($<id>1);
$$ = rb_assoc_new($1, $3);
%*/
}
......
f_block_opt : tIDENTIFIER '=' primary_value
{
shadowing_lvar($<id>1);
arg_var($<id>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($<id>1);
$$ = rb_assoc_new($1, $3);
%*/
}
......
f_rest_arg : restarg_mark tIDENTIFIER
{
shadowing_lvar($<id>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);
......
}
| restarg_mark
{
ID tid = internal_id();
arg_var(tid);
/*%%%*/
$$ = internal_id();
arg_var($$);
$$ = tid;
/*%
$$ = dispatch1(rest_param, Qnil);
%*/
......
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($<id>2);
arg_var($<id>2);
}
;
......
# 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
......
#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
......
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 */
......
}
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)
......
shadowing_lvar(name);
dyna_var(name);
}
#ifndef RIPPER
static NODE *
aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
......
return node;
}
#endif /* !RIPPER */
static void
local_push_gen(struct parser_params *parser, int inherit_dvars)
{
......
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);
......
global_symbols.op_sym + tLAST_TOKEN);
}
#endif /* !RIPPER */
static ID
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)
test/ripper/test_parser_events.rb
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
    (1-1/1)