Skip to content

Commit

Permalink
+ ruby28.y: add right hand assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Apr 30, 2020
1 parent 9b32b47 commit 534941f
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 1 deletion.
22 changes: 22 additions & 0 deletions doc/AST_FORMAT.md
Expand Up @@ -730,6 +730,28 @@ Format:
~~~

### Right-hand assignment

Format:

~~~
(rasgn (int 1) (lvasgn :a))
"1 => a"
~~~~~~ expression
~~ operator
~~~

#### Multiple right-hand assignment

Format:

~~~
(mrasgn (send (int 13) :divmod (int 5)) (mlhs (lvasgn :a) (lvasgn :b)))
"13.divmod(5) => a,b"
~~~~~~~~~~~~~~~~~~~ expression
^^ operator},
~~~

## Class and module definition

### Module
Expand Down
3 changes: 3 additions & 0 deletions lib/parser/ast/processor.rb
Expand Up @@ -75,6 +75,9 @@ def on_op_asgn(node)
alias on_mlhs process_regular_node
alias on_masgn process_regular_node

alias on_rasgn process_regular_node
alias on_mrasgn process_regular_node

def on_const(node)
scope_node, name = *node

Expand Down
9 changes: 9 additions & 0 deletions lib/parser/builders/default.rb
Expand Up @@ -619,6 +619,15 @@ def multi_assign(lhs, eql_t, rhs)
binary_op_map(lhs, eql_t, rhs))
end

def rassign(lhs, assoc_t, rhs)
n(:rasgn, [lhs, rhs], binary_op_map(lhs, assoc_t, rhs))
end

def multi_rassign(lhs, assoc_t, rhs)
n(:mrasgn, [ lhs, rhs ],
binary_op_map(lhs, assoc_t, rhs))
end

#
# Class and module definition
#
Expand Down
2 changes: 1 addition & 1 deletion lib/parser/meta.rb
Expand Up @@ -12,7 +12,7 @@ module Meta
sym dsym xstr regopt regexp array splat
pair kwsplat hash irange erange self
lvar ivar cvar gvar const defined? lvasgn
ivasgn cvasgn gvasgn casgn mlhs masgn
ivasgn cvasgn gvasgn casgn mlhs masgn rasgn mrasgn
op_asgn and_asgn ensure rescue arg_expr
or_asgn back_ref nth_ref
match_with_lvasgn match_current_line
Expand Down
18 changes: 18 additions & 0 deletions lib/parser/ruby28.y
Expand Up @@ -206,8 +206,26 @@ rule
{
result = @builder.multi_assign(val[0], val[1], val[2])
}
| rassign
| expr

rassign: arg_value tASSOC lhs
{
result = @builder.rassign(val[0], val[1], val[2])
}
| arg_value tASSOC mlhs
{
result = @builder.multi_rassign(val[0], val[1], val[2])
}
| rassign tASSOC lhs
{
result = @builder.rassign(val[0], val[1], val[2])
}
| rassign tASSOC mlhs
{
result = @builder.multi_rassign(val[0], val[1], val[2])
}

command_asgn: lhs tEQL command_rhs
{
result = @builder.assign(val[0], val[1], val[2])
Expand Down
50 changes: 50 additions & 0 deletions test/test_parser.rb
Expand Up @@ -9520,6 +9520,56 @@ def test_endless_method_without_brackets
[:error, :unexpected_token, { :token => 'tEQL' }],
%Q{def obj.foo = 42},
%q{ ^ location},
SINCE_2_8
)
end

def test_rasgn
assert_parses(
s(:rasgn,
s(:int, 1), s(:lvasgn, :a)),
%q{1 => a},
%q{~~~~~~ expression
| ^^ operator},
SINCE_2_8)

assert_parses(
s(:rasgn,
s(:send, s(:int, 1), :+, s(:int, 2)),
s(:gvasgn, :$a)),
%q{1 + 2 => $a},
%q{~~~~~~~~~~~ expression
| ^^ operator},
SINCE_2_8)
end

def test_mrasgn
assert_parses(
s(:mrasgn,
s(:send, s(:int, 13), :divmod, s(:int, 5)),
s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
%q{13.divmod(5) => a,b},
%q{~~~~~~~~~~~~~~~~~~~ expression
| ^^ operator},
SINCE_2_8)

assert_parses(
s(:mrasgn,
s(:mrasgn,
s(:send, s(:int, 13), :divmod, s(:int, 5)),
s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
s(:mlhs, s(:lvasgn, :c), s(:lvasgn, :d))),
%q{13.divmod(5) => a,b => c, d},
%q{~~~~~~~~~~~~~~~~~~~ expression (mrasgn)
|~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression},
SINCE_2_8)
end

def test_rasgn_line_continuation
assert_diagnoses(
[:error, :unexpected_token, { :token => 'tASSOC' }],
%Q{13.divmod(5)\n=> a,b; [a, b]},
%{ ^^ location},
SINCE_2_8)
end
end

0 comments on commit 534941f

Please sign in to comment.