Bug #18080
openSyntax error on one-line pattern matching
Added by ko1 (Koichi Sasada) over 3 years ago. Updated about 1 year ago.
Description
One line pattern matching with a method return value with parameters which are not surrounded by parenthesis raises syntax error.
I think it is not intentional, but nobu said it's hard to support because of parse.y limitation.
p do
end => a
p a #=> nil
p(1) do
end => a
p a #=> 1
p 1 do
end => a
#=>
# syntax error, unexpected =>, expecting end-of-input
# end => a
# ^~
p 1 do
end in a
#=>
# syntax error, unexpected `in', expecting end-of-input
# end in a
# ^~
Updated by jeremyevans0 (Jeremy Evans) about 1 year ago
@kddnewton (Kevin Newton) Is this possible to support in YARP?
@yui-knk (Kaneko Yuichiro) Is this possible to support in parse.y/lrama?
Updated by mdalessio (Mike Dalessio) about 1 year ago
Looks like YARP already supports this.
"> YARP.parse <<~EOF
"> p 1 do
"> end in a
"> p 1 do
"> end => a
>> EOF
=>
#<YARP::ParseResult:0x00007f0f326c5280
@comments=[],
@errors=[],
@source=#<YARP::Source:0x00007f0f328c35a0 @offsets=[0, 7, 16, 23, 32], @source="p 1 do\nend in a\np 1 do\nend => a\n">,
@value=
ProgramNode(0...31)(
[:a],
StatementsNode(0...31)(
[MatchPredicateNode(0...15)(
CallNode(0...10)(
nil,
nil,
(0...1),
nil,
ArgumentsNode(2...3)([IntegerNode(2...3)()]),
nil,
BlockNode(4...10)([], nil, nil, (4...6), (7...10)),
0,
"p"
),
LocalVariableWriteNode(14...15)(:a, 0, nil, (14...15), nil),
(11...13)
),
MatchRequiredNode(16...31)(
CallNode(16...26)(
nil,
nil,
(16...17),
nil,
ArgumentsNode(18...19)([IntegerNode(18...19)()]),
nil,
BlockNode(20...26)([], nil, nil, (20...22), (23...26)),
0,
"p"
),
LocalVariableWriteNode(30...31)(:a, 0, nil, (30...31), nil),
(27...29)
)]
)
),
@warnings=[]>
Updated by kddnewton (Kevin Newton) about 1 year ago
As Mike said, there's no issue with this for YARP.
Updated by yui-knk (Kaneko Yuichiro) about 1 year ago
It's possible https://github.com/yui-knk/ruby/tree/bugs_18080.
However need to notice about inconsistency for one line pattern matching for command call without block, like [].append 1 => a
. Because this is interpreted as #append
call with hash (1 => a
) now, so it's impossible to change the behavior without introducing incompatibility.
[].append => a
[].append in a
[].append do
end => a
[].append do
end in a
[].append(1) => a
[].append(1) in a
[].append(1) do
end => a
[].append(1) do
end in a
# Only this is interpreted as #append method call with hash argument
[].append 1 => a
[].append 1 in a
[].append 1 do
end => a
[].append 1 do
end in a
In my opinion (1) is more clear than (2).
(1) Method call without surrounding parameters parenthesis can not be put on left of single line pattern matching
(2) Almost all method calls can be on left of single line pattern matching but there is one exception (a) without block (b) without parenthesis for parameters (c) pattern matching with =>
Note¶
The inconsistency can be found as Shift/Reduce conflict. In this state, shift derives arg_value • "=>" arg_value
(hash), on the other hand reduce derives command_call => p_top_expr_body
(pattern matching).
https://github.com/yui-knk/ruby/tree/bugs_18080_2
State 223
shift/reduce conflict on token "=>":
308 args: arg_value •
759 assoc: arg_value • "=>" arg_value
First example: $@1 k_return arg_value • "=>" arg_value opt_block_arg "=>" @7 @8 p_top_expr_body opt_terms "end-of-input"
Shift derivation
$accept
↳ 0: program "end-of-input"
↳ 2: $@1 top_compstmt
↳ 3: top_stmts opt_terms
↳ 5: top_stmt
↳ 7: stmt
↳ 37: expr
↳ 65: command "=>" @7 @8 p_top_expr_body
↳ 97: k_return call_args
↳ 299: assocs opt_block_arg
↳ 757: assoc
↳ 759: arg_value • "=>" arg_value
Second example: $@1 k_return arg_value • opt_block_arg "=>" @7 @8 p_top_expr_body opt_terms "end-of-input"
Reduce derivation
$accept
↳ 0: program "end-of-input"
↳ 2: $@1 top_compstmt
↳ 3: top_stmts opt_terms
↳ 5: top_stmt
↳ 7: stmt
↳ 37: expr
↳ 65: command_call "=>" @7 @8 p_top_expr_body
↳ 82: command
↳ 97: k_return call_args
↳ 298: args opt_block_arg
↳ 308: arg_value •