@@ -20,7 +20,7 @@ Nonterminals
2020 call_args_no_parens_comma_expr call_args_no_parens_all call_args_no_parens_many
2121 call_args_no_parens_many_strict
2222 stab stab_eoe stab_expr stab_op_eol_and_expr stab_parens_many
23- kw_eol kw_base kw call_args_no_parens_kw_expr call_args_no_parens_kw
23+ kw_eol kw_base kw_data kw_call call_args_no_parens_kw_expr call_args_no_parens_kw
2424 dot_op dot_alias dot_bracket_identifier dot_call_identifier
2525 dot_identifier dot_op_identifier dot_do_identifier dot_paren_identifier
2626 do_block fn_eoe do_eoe end_eoe block_eoe block_item block_list
@@ -285,7 +285,7 @@ number -> char : handle_number(?exprs('$1'), '$1', number_value('$1')).
285285parens_call -> dot_call_identifier call_args_parens : build_parens ('$1' , '$2' , {[], []}).
286286parens_call -> dot_call_identifier call_args_parens call_args_parens : build_nested_parens ('$1' , '$2' , '$3' , {[], []}).
287287
288- bracket_arg -> open_bracket kw close_bracket : build_access_arg ('$1' , '$2' , '$3' ).
288+ bracket_arg -> open_bracket kw_data close_bracket : build_access_arg ('$1' , '$2' , '$3' ).
289289bracket_arg -> open_bracket container_expr close_bracket : build_access_arg ('$1' , '$2' , '$3' ).
290290bracket_arg -> open_bracket container_expr ',' close_bracket : build_access_arg ('$1' , '$2' , '$4' ).
291291
@@ -513,7 +513,7 @@ container_args_base -> container_args_base ',' container_expr : ['$3' | '$1'].
513513
514514container_args -> container_args_base : reverse ('$1' ).
515515container_args -> container_args_base ',' : reverse ('$1' ).
516- container_args -> container_args_base ',' kw : reverse (['$3' | '$1' ]).
516+ container_args -> container_args_base ',' kw_call : reverse (['$3' | '$1' ]).
517517
518518% Function calls with parentheses
519519
@@ -528,16 +528,16 @@ call_args_parens -> open_paren ')' :
528528 {newlines_pair ('$1' , '$2' ), []}.
529529call_args_parens -> open_paren no_parens_expr close_paren :
530530 {newlines_pair ('$1' , '$3' ), ['$2' ]}.
531- call_args_parens -> open_paren kw_base close_paren :
532- {newlines_pair ('$1' , '$3' ), [reverse ( '$2' ) ]}.
533- call_args_parens -> open_paren kw_base ',' close_paren :
534- warn_trailing_comma ('$3' ), {newlines_pair ('$1' , '$4' ), [reverse ( '$2' ) ]}.
531+ call_args_parens -> open_paren kw_call close_paren :
532+ {newlines_pair ('$1' , '$3' ), ['$2' ]}.
533+ call_args_parens -> open_paren kw_call ',' close_paren :
534+ warn_trailing_comma ('$3' ), {newlines_pair ('$1' , '$4' ), ['$2' ]}.
535535call_args_parens -> open_paren call_args_parens_base close_paren :
536536 {newlines_pair ('$1' , '$3' ), reverse ('$2' )}.
537- call_args_parens -> open_paren call_args_parens_base ',' kw_base close_paren :
538- {newlines_pair ('$1' , '$5' ), reverse ([reverse ( '$4' ) | '$2' ])}.
539- call_args_parens -> open_paren call_args_parens_base ',' kw_base ',' close_paren :
540- warn_trailing_comma ('$5' ), {newlines_pair ('$1' , '$6' ), reverse ([reverse ( '$4' ) | '$2' ])}.
537+ call_args_parens -> open_paren call_args_parens_base ',' kw_call close_paren :
538+ {newlines_pair ('$1' , '$5' ), reverse (['$4' | '$2' ])}.
539+ call_args_parens -> open_paren call_args_parens_base ',' kw_call ',' close_paren :
540+ warn_trailing_comma ('$5' ), {newlines_pair ('$1' , '$6' ), reverse (['$4' | '$2' ])}.
541541
542542% KV
543543
@@ -551,21 +551,27 @@ kw_eol -> kw_identifier_unsafe eol : build_quoted_atom('$1', false, [{format, ke
551551kw_base -> kw_eol container_expr : [{'$1' , '$2' }].
552552kw_base -> kw_base ',' kw_eol container_expr : [{'$3' , '$4' } | '$1' ].
553553
554- kw -> kw_base : reverse ('$1' ).
555- kw -> kw_base ',' : reverse ('$1' ).
554+ kw_call -> kw_base : reverse ('$1' ).
555+ kw_call -> kw_base ',' : reverse ('$1' ).
556+ kw_call -> kw_base ',' matched_expr : error_bad_keyword_call_follow_up ('$2' ).
557+
558+ kw_data -> kw_base : reverse ('$1' ).
559+ kw_data -> kw_base ',' : reverse ('$1' ).
560+ kw_data -> kw_base ',' matched_expr : error_bad_keyword_data_follow_up ('$2' ).
556561
557562call_args_no_parens_kw_expr -> kw_eol matched_expr : {'$1' , '$2' }.
558563call_args_no_parens_kw_expr -> kw_eol no_parens_expr : {'$1' , '$2' }.
559564
560565call_args_no_parens_kw -> call_args_no_parens_kw_expr : ['$1' ].
561566call_args_no_parens_kw -> call_args_no_parens_kw_expr ',' call_args_no_parens_kw : ['$1' | '$3' ].
567+ call_args_no_parens_kw -> call_args_no_parens_kw_expr ',' matched_expr : error_bad_keyword_call_follow_up ('$2' ).
562568
563569% Lists
564570
565- list_args -> kw : '$1' .
571+ list_args -> kw_data : '$1' .
566572list_args -> container_args_base : reverse ('$1' ).
567573list_args -> container_args_base ',' : reverse ('$1' ).
568- list_args -> container_args_base ',' kw : reverse ('$1' , '$3' ).
574+ list_args -> container_args_base ',' kw_data : reverse ('$1' , '$3' ).
569575
570576list -> open_bracket ']' : build_list ('$1' , [], '$2' ).
571577list -> open_bracket list_args close_bracket : build_list ('$1' , '$2' , '$3' ).
@@ -595,8 +601,8 @@ assoc_expr -> parens_call : '$1'.
595601assoc_update -> matched_expr pipe_op_eol assoc_expr : {'$2' , '$1' , ['$3' ]}.
596602assoc_update -> unmatched_expr pipe_op_eol assoc_expr : {'$2' , '$1' , ['$3' ]}.
597603
598- assoc_update_kw -> matched_expr pipe_op_eol kw : {'$2' , '$1' , '$3' }.
599- assoc_update_kw -> unmatched_expr pipe_op_eol kw : {'$2' , '$1' , '$3' }.
604+ assoc_update_kw -> matched_expr pipe_op_eol kw_data : {'$2' , '$1' , '$3' }.
605+ assoc_update_kw -> unmatched_expr pipe_op_eol kw_data : {'$2' , '$1' , '$3' }.
600606
601607assoc_base -> assoc_expr : ['$1' ].
602608assoc_base -> assoc_base ',' assoc_expr : ['$3' | '$1' ].
@@ -607,9 +613,9 @@ assoc -> assoc_base ',' : reverse('$1').
607613map_op -> '%{}' : '$1' .
608614map_op -> '%{}' eol : '$1' .
609615
610- map_close -> kw close_curly : {'$1' , '$2' }.
616+ map_close -> kw_data close_curly : {'$1' , '$2' }.
611617map_close -> assoc close_curly : {'$1' , '$2' }.
612- map_close -> assoc_base ',' kw close_curly : {reverse ('$1' , '$3' ), '$4' }.
618+ map_close -> assoc_base ',' kw_data close_curly : {reverse ('$1' , '$3' ), '$4' }.
613619
614620map_args -> open_curly '}' : build_map ('$1' , [], '$2' ).
615621map_args -> open_curly map_close : build_map ('$1' , element (1 , '$2' ), element (2 , '$2' )).
@@ -1053,6 +1059,24 @@ error_bad_atom(Token) ->
10531059 " If the '.' was meant to be part of the atom's name, "
10541060 " the atom name must be quoted. Syntax error before: " , " '.'" ).
10551061
1062+ error_bad_keyword_call_follow_up (Token ) ->
1063+ return_error (meta_from_token (Token ),
1064+ " unexpected expression after keyword list. Keyword lists must always come as the last argument. Therefore, this is not allowed:\n\n "
1065+ " function_call(1, some: :option, 2)\n\n "
1066+ " Instead, wrap the keyword in brackets:\n\n "
1067+ " function_call(1, [some: :option], 2)\n\n "
1068+ " Syntax error after: " , " ','" ).
1069+
1070+ error_bad_keyword_data_follow_up (Token ) ->
1071+ return_error (meta_from_token (Token ),
1072+ " unexpected expression after keyword list. Keyword lists must always come last in lists and maps. Therefore, this is not allowed:\n\n "
1073+ " [some: :value, :another]\n "
1074+ " %{some: :value, another => value}\n\n "
1075+ " Instead, reorder it to be the last entry:\n\n "
1076+ " [:another, some: :value]\n "
1077+ " %{another => value, some: :value}\n\n "
1078+ " Syntax error after: " , " ','" ).
1079+
10561080error_no_parens_strict (Token ) ->
10571081 return_error (meta_from_token (Token ), " unexpected parentheses. If you are making a "
10581082 " function call, do not insert spaces between the function name and the "
0 commit comments