1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

parse.y: fix var_field

* parse.y (mlhs_node): dispatch var_field as well as lhs.

* parse.y (lhs, var_hs): dispatch var_field before assignable
  check so it is inside assign_error at a wrong assignment, as
  well as backref_assign_error.

* parse.y (var_field_gen): wrap var_field value with the variable
  ID.

* parse.y (assignable_gen, const_decl_gen): return the callback
  result on a syntax error.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60116 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-10-04 06:47:29 +00:00
parent 3be412834d
commit 2afb729f57
2 changed files with 59 additions and 40 deletions

38
parse.y
View file

@ -548,7 +548,8 @@ static VALUE new_xstring_gen(struct parser_params *, VALUE);
static VALUE const_decl_gen(struct parser_params *parser, VALUE path);
#define const_decl(path) const_decl_gen(parser, path)
#define var_field(n) dispatch1(var_field, (n))
static VALUE var_field_gen(struct parser_params *parser, VALUE a);
#define var_field(a) var_field_gen(parser, (a))
static VALUE assign_error_gen(struct parser_params *parser, VALUE a);
#define assign_error(a) assign_error_gen(parser, (a))
#define backref_assign_error(n, a) assign_error(a)
@ -1711,11 +1712,11 @@ mlhs_post : mlhs_item
mlhs_node : user_variable
{
$$ = assignable($1, 0);
$$ = assignable(var_field($1), 0);
}
| keyword_variable
{
$$ = assignable($1, 0);
$$ = assignable(var_field($1), 0);
}
| primary_value '[' opt_call_args rbracket
{
@ -1766,20 +1767,18 @@ mlhs_node : user_variable
lhs : user_variable
{
$$ = assignable($1, 0);
$$ = assignable(var_field($1), 0);
/*%%%*/
if (!$$) $$ = NEW_BEGIN(0);
/*%
$$ = dispatch1(var_field, $$);
%*/
}
| keyword_variable
{
$$ = assignable($1, 0);
$$ = assignable(var_field($1), 0);
/*%%%*/
if (!$$) $$ = NEW_BEGIN(0);
/*%
$$ = dispatch1(var_field, $$);
%*/
}
| primary_value '[' opt_call_args rbracket
@ -4142,19 +4141,11 @@ var_ref : user_variable
var_lhs : user_variable
{
$$ = assignable($1, 0);
/*%%%*/
/*%
$$ = dispatch1(var_field, $$);
%*/
$$ = assignable(var_field($1), 0);
}
| keyword_variable
{
$$ = assignable($1, 0);
/*%%%*/
/*%
$$ = dispatch1(var_field, $$);
%*/
$$ = assignable(var_field($1), 0);
}
;
@ -9258,8 +9249,8 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val)
{
#ifdef RIPPER
ID id = get_id(lhs);
# define assignable_result(x) get_value(lhs)
# define parser_yyerror(parser, x) assign_error_gen(parser, lhs)
# define assignable_result(x) (lhs)
# define parser_yyerror(parser, x) (lhs = assign_error_gen(parser, lhs))
#else
# define assignable_result(x) (x)
#endif
@ -10296,7 +10287,8 @@ static VALUE
const_decl_gen(struct parser_params *parser, VALUE path)
{
if (in_def || in_single) {
assign_error(path);
path = dispatch1(assign_error, path);
ripper_error();
}
return path;
}
@ -10308,6 +10300,12 @@ assign_error_gen(struct parser_params *parser, VALUE a)
ripper_error();
return a;
}
static VALUE
var_field_gen(struct parser_params *parser, VALUE a)
{
return ripper_new_yylval(get_id(a), dispatch1(var_field, a), 0);
}
#endif
static void

View file

@ -194,7 +194,10 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_assign_error
# for test_coverage
thru_assign_error = false
result = parse('self = 1', :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_equal '[assign(assign_error(var_field(self)),1)]', result
end
def test_assign_error_backref
@ -208,29 +211,47 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
result =
parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_equal '[massign([assign_error(var_field($`)),_],1)]', result
assert_equal '[massign([assign_error(var_field($`)),var_field(_)],1)]', result
end
def test_assign_error_const_qualified
thru_assign_error = false
parse('self::X = 1', :on_assign_error) {thru_assign_error = true}
result =
parse('self::X = 1', :on_assign_error) {thru_assign_error = true}
assert_equal false, thru_assign_error
parse("def m\n self::X = 1\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_equal "[assign(const_path_field(ref(self),X),1)]", result
thru_assign_error = false
parse("def m\n self::X, a = 1, 2\nend", :on_assign_error) {thru_assign_error = true}
result =
parse("def m\n self::X = 1\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_include result, "assign_error(const_path_field(ref(self),X))"
thru_assign_error = false
result =
parse("def m\n self::X, a = 1, 2\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_include result, "assign_error(const_path_field(ref(self),X))"
end
def test_assign_error_const
thru_assign_error = false
parse('X = 1', :on_assign_error) {thru_assign_error = true}
result = parse('X = 1', :on_assign_error) {thru_assign_error = true}
assert_equal false, thru_assign_error
parse("def m\n X = 1\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_equal "[assign(var_field(X),1)]", result
thru_assign_error = false
parse("def m\n X, a = 1, 2\nend", :on_assign_error) {thru_assign_error = true}
result = parse('X, a = 1, 2', :on_assign_error) {thru_assign_error = true}
assert_equal false, thru_assign_error
assert_include result, "massign([var_field(X),var_field(a)],"
result = parse("def m\n X = 1\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_include result, "assign_error(var_field(X))"
thru_assign_error = false
result = parse("def m\n X, a = 1, 2\nend", :on_assign_error) {thru_assign_error = true}
assert_equal true, thru_assign_error
assert_include result, "assign_error(var_field(X))"
end
def test_assign_error_const_toplevel
@ -475,46 +496,46 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
thru_mlhs_add_star = false
tree = parse("a, *b = 1, 2", :on_mlhs_add_star) {thru_mlhs_add_star = true}
assert_equal true, thru_mlhs_add_star
assert_include(tree, "massign([a,*b]")
assert_include(tree, "massign([var_field(a),*var_field(b)]")
thru_mlhs_add_star = false
tree = parse("a, *b, c = 1, 2", :on_mlhs_add_star) {thru_mlhs_add_star = true}
assert_equal true, thru_mlhs_add_star
assert_include(tree, "massign([a,*b,c]", bug2232)
assert_include(tree, "massign([var_field(a),*var_field(b),var_field(c)]", bug2232)
thru_mlhs_add_star = false
tree = parse("a, *, c = 1, 2", :on_mlhs_add_star) {thru_mlhs_add_star = true}
assert_equal true, thru_mlhs_add_star
assert_include(tree, "massign([a,*,c]", bug4364)
assert_include(tree, "massign([var_field(a),*,var_field(c)]", bug4364)
thru_mlhs_add_star = false
tree = parse("*b, c = 1, 2", :on_mlhs_add_star) {thru_mlhs_add_star = true}
assert_equal true, thru_mlhs_add_star
assert_include(tree, "massign([*b,c]", bug4364)
assert_include(tree, "massign([*var_field(b),var_field(c)]", bug4364)
thru_mlhs_add_star = false
tree = parse("*, c = 1, 2", :on_mlhs_add_star) {thru_mlhs_add_star = true}
assert_equal true, thru_mlhs_add_star
assert_include(tree, "massign([*,c],", bug4364)
assert_include(tree, "massign([*,var_field(c)],", bug4364)
end
def test_mlhs_add_post
thru_mlhs_add_post = false
tree = parse("a, *b = 1, 2", :on_mlhs_add_post) {thru_mlhs_add_post = true}
assert_equal false, thru_mlhs_add_post
assert_include(tree, "massign([a,*b],")
assert_include(tree, "massign([var_field(a),*var_field(b)],")
thru_massign_add_post = false
tree = parse("a, *b, c = 1, 2", :on_mlhs_add_post) {thru_mlhs_add_post = true}
assert_equal true, thru_mlhs_add_post
assert_include(tree, "massign([a,*b,c],")
assert_include(tree, "massign([var_field(a),*var_field(b),var_field(c)],")
thru_mlhs_add_post = false
tree = parse("a, *, c = 1, 2", :on_mlhs_add_post) {thru_mlhs_add_post = true}
assert_equal true, thru_mlhs_add_post
assert_include(tree, "massign([a,*,c],")
assert_include(tree, "massign([var_field(a),*,var_field(c)],")
thru_mlhs_add_post = false
tree = parse("*b, c = 1, 2", :on_mlhs_add_post) {thru_mlhs_add_post = true}
assert_equal true, thru_mlhs_add_post
assert_include(tree, "massign([*b,c],")
assert_include(tree, "massign([*var_field(b),var_field(c)],")
thru_mlhs_add_post = false
tree = parse("*, c = 1, 2", :on_mlhs_add_post) {thru_mlhs_add_post = true}
assert_equal true, thru_mlhs_add_post
assert_include(tree, "massign([*,c],")
assert_include(tree, "massign([*,var_field(c)],")
end
def test_mlhs_new