@@ -554,6 +554,7 @@ impl<ANS: AreNewlinesSpaces> ExpressionParser<ANS> {
554
554
// arglist: argument (',' argument)* [',']
555
555
556
556
// argument: ( test [comp_for] |
557
+ // test ':=' test |
557
558
// test '=' test |
558
559
// '**' test |
559
560
// '*' test )
@@ -563,6 +564,12 @@ impl<ANS: AreNewlinesSpaces> ExpressionParser<ANS> {
563
564
alt!(
564
565
preceded!( tag!( "**" ) , call!( Self :: test) ) => { |kwargs: Box <_>| Argument :: Kwargs ( * kwargs) }
565
566
| preceded!( char !( '*' ) , call!( Self :: test) ) => { |args: Box <_>| Argument :: Starargs ( * args) }
567
+ | do_parse!(
568
+ name: call!( Self :: test) >>
569
+ value: preceded!( tag!( ":=" ) , call!( Self :: test) ) >> (
570
+ Argument :: Positional ( Expression :: Named ( name, value) )
571
+ )
572
+ )
566
573
| do_parse!(
567
574
name: name >> // According to the grammar, this should be a 'test', but cpython actually refuses it (for good reasons)
568
575
value: preceded!( char !( '=' ) , call!( Self :: test) ) >> (
@@ -1175,6 +1182,24 @@ mod tests {
1175
1182
) ;
1176
1183
}
1177
1184
1185
+ #[ test]
1186
+ fn test_call_positional_namedexpr ( ) {
1187
+ let atom_expr = ExpressionParser :: < NewlinesAreNotSpaces > :: atom_expr;
1188
+ assert_parse_eq (
1189
+ atom_expr ( make_strspan ( "foo(bar := baz)" ) ) ,
1190
+ Ok ( (
1191
+ make_strspan ( "" ) ,
1192
+ Box :: new ( Expression :: Call (
1193
+ Box :: new ( Expression :: Name ( "foo" . to_string ( ) ) ) ,
1194
+ vec ! [ Argument :: Positional ( Expression :: Named (
1195
+ Box :: new( Expression :: Name ( "bar" . to_string( ) ) ) ,
1196
+ Box :: new( Expression :: Name ( "baz" . to_string( ) ) ) ,
1197
+ ) ) ] ,
1198
+ ) ) ,
1199
+ ) ) ,
1200
+ ) ;
1201
+ }
1202
+
1178
1203
#[ test]
1179
1204
fn test_call_positional ( ) {
1180
1205
let atom_expr = ExpressionParser :: < NewlinesAreNotSpaces > :: atom_expr;
0 commit comments