@@ -554,6 +554,7 @@ impl<ANS: AreNewlinesSpaces> ExpressionParser<ANS> {
554554 // arglist: argument (',' argument)* [',']
555555
556556 // argument: ( test [comp_for] |
557+ // test ':=' test |
557558 // test '=' test |
558559 // '**' test |
559560 // '*' test )
@@ -563,6 +564,12 @@ impl<ANS: AreNewlinesSpaces> ExpressionParser<ANS> {
563564 alt!(
564565 preceded!( tag!( "**" ) , call!( Self :: test) ) => { |kwargs: Box <_>| Argument :: Kwargs ( * kwargs) }
565566 | 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+ )
566573 | do_parse!(
567574 name: name >> // According to the grammar, this should be a 'test', but cpython actually refuses it (for good reasons)
568575 value: preceded!( char !( '=' ) , call!( Self :: test) ) >> (
@@ -1175,6 +1182,24 @@ mod tests {
11751182 ) ;
11761183 }
11771184
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+
11781203 #[ test]
11791204 fn test_call_positional ( ) {
11801205 let atom_expr = ExpressionParser :: < NewlinesAreNotSpaces > :: atom_expr;
0 commit comments