Skip to content
Permalink
Browse files

Rightward-assign by ASSOC

[Feature #15921]
  • Loading branch information
nobu committed Apr 10, 2020
1 parent d94960f commit 1b2d351b216661e03d497dfdce216e0d51474664
Showing with 52 additions and 2 deletions.
  1. +7 −0 NEWS.md
  2. +38 −2 parse.y
  3. +7 −0 test/ruby/test_syntax.rb
@@ -38,6 +38,12 @@ sufficient information, see the ChangeLog file or Redmine
instead of a warning. yield in a class definition outside of a method
is now a SyntaxError instead of a LocalJumpError. [[Feature #15575]]

* Rightward assignment statement is added. [[Feature #15921]]

```ruby
fib(10) => x
```

## Command line options

## Core classes updates
@@ -170,5 +176,6 @@ Excluding feature bug fixes.
[Feature #16274]: https://bugs.ruby-lang.org/issues/16274
[Feature #16377]: https://bugs.ruby-lang.org/issues/16377
[Bug #12706]: https://bugs.ruby-lang.org/issues/12706
[Feature #15921]: https://bugs.ruby-lang.org/issues/15921
[Feature #16555]: https://bugs.ruby-lang.org/issues/16555
[GH-2991]: https://github.com/ruby/ruby/pull/2991
40 parse.y
@@ -1083,7 +1083,7 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> string_contents xstring_contents regexp_contents string_content
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
%type <node> literal numeric simple_numeric ssym dsym symbol cpath
%type <node> top_compstmt top_stmts top_stmt begin_block
%type <node> top_compstmt top_stmts top_stmt begin_block rassign
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
%type <node> expr_value expr_value_do arg_value primary_value fcall rel_expr
%type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure
@@ -1481,9 +1481,44 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
/*% %*/
/*% ripper: massign!($1, $3) %*/
}
| rassign
| expr
;

rassign : primary tASSOC lhs
{
/*%%%*/
value_expr($1);
$$ = node_assign(p, $3, $1, &@$);
/*% %*/
/*% ripper: assign!($3, $1) %*/
}
| primary tASSOC mlhs
{
/*%%%*/
value_expr($1);
$$ = node_assign(p, $3, $1, &@$);
/*% %*/
/*% ripper: massign!($3, $1) %*/
}
| rassign tASSOC lhs
{
/*%%%*/
value_expr($1);
$$ = node_assign(p, $3, $1, &@$);
/*% %*/
/*% ripper: assign!($3, $1) %*/
}
| rassign tASSOC mlhs
{
/*%%%*/
value_expr($1);
$$ = node_assign(p, $3, $1, &@$);
/*% %*/
/*% ripper: massign!($3, $1) %*/
}
;

command_asgn : lhs '=' command_rhs
{
/*%%%*/
@@ -8866,10 +8901,11 @@ parser_yylex(struct parser_params *p)
pushback(p, c);
if (space_seen) dispatch_scan_event(p, tSP);
goto retry;
case '=':
case '&':
case '.': {
dispatch_delayed_token(p, tIGNORED_NL);
if (peek(p, '.') == (c == '&')) {
if (c == '=' ? peek(p, '>') : (peek(p, '.') == (c == '&'))) {
pushback(p, c);
dispatch_scan_event(p, tSP);
goto retry;
@@ -1559,6 +1559,13 @@ def obj3.bar(*args, &block)
end
end
def test_rightward_assign
assert_equal(1, eval("1 => a"))
assert_equal([2,3], eval("13.divmod(5) => a,b; [a, b]"))
assert_equal([2,3,2,3], eval("13.divmod(5) => a,b => c, d; [a, b, c, d]"))
assert_equal([2,3], eval("13.divmod(5)\n => a,b; [a, b]"))
end
private
def not_label(x) @result = x; @not_label ||= nil end

0 comments on commit 1b2d351

Please sign in to comment.
You can’t perform that action at this time.