Skip to content

Commit 05cd7f1

Browse files
author
José Valim
committed
Fix list with keywords expansion
The list `[1, 2, three: :four]` now correctly expands to `[1, 2, {:three, :four}]`.
1 parent 0d4655d commit 05cd7f1

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Bug fixes
1010
* [Atom] Inspect `:...` and `:foo@bar` without quoting
1111
* [File] Respect source directories terminating with "/" in `File.cp_r/3` with the same semantics as Unix
12+
* [Keyword] The list `[1, 2, three: :four]` now correctly expands to `[1, 2, {:three, :four}]`
1213
* [Kernel] Ensure undefined `@attributes` shows proper stacktrace in warnings
1314
* [Kernel] Guarantee nullary funs/macros are allowed in guards
1415
* [Process] Ensure monitoring functions are inlined by the compiler

lib/elixir/src/elixir_parser.yrl

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ Nonterminals
1010
open_bracket close_bracket
1111
open_curly close_curly
1212
open_bit close_bit
13-
container_comma_expr_base container_comma_expr container_arg container_args
14-
call_args_parens_comma_expr call_args_parens parens_call
13+
container_args_base container_args
14+
call_args_parens_base call_args_parens parens_call
1515
call_args_no_parens_one call_args_no_parens_expr call_args_no_parens_comma_expr
1616
call_args_no_parens_all call_args_no_parens_many call_args_no_parens_many_strict
1717
stab stab_eol stab_expr stab_maybe_expr stab_parens_many
1818
kw_eol kw_expr kw_comma kw
1919
call_args_no_parens_kw_expr call_args_no_parens_kw_comma call_args_no_parens_kw
2020
dot_op dot_alias dot_identifier dot_op_identifier dot_do_identifier
2121
dot_paren_identifier dot_bracket_identifier
22-
var list bit_string tuple
22+
var list list_args bit_string tuple
2323
do_block fn_eol do_eol end_eol block_eol block_item block_list
2424
.
2525

@@ -396,27 +396,22 @@ container_expr -> matched_expr : '$1'.
396396
container_expr -> unmatched_expr : '$1'.
397397
container_expr -> no_parens_expr : throw_no_parens_many_strict('$1').
398398

399-
container_comma_expr_base -> container_expr ',' : ['$1'].
400-
container_comma_expr_base -> container_comma_expr_base container_expr ',' : ['$2'|'$1'].
399+
container_args_base -> container_expr : ['$1'].
400+
container_args_base -> container_args_base ',' container_expr : ['$3'|'$1'].
401401

402-
container_comma_expr -> container_expr : ['$1'].
403-
container_comma_expr -> kw : ['$1'].
404-
container_comma_expr -> container_comma_expr_base : '$1'.
405-
container_comma_expr -> container_comma_expr_base container_expr : ['$2'|'$1'].
406-
container_comma_expr -> container_comma_expr_base kw : ['$2'|'$1'].
402+
container_args -> kw : ['$1'].
403+
container_args -> container_args_base : lists:reverse('$1').
404+
container_args -> container_args_base ',' : lists:reverse('$1').
405+
container_args -> container_args_base ',' kw : lists:reverse(['$3'|'$1']).
407406

408-
container_arg -> container_expr : '$1'.
409-
container_arg -> container_expr ',' : '$1'.
410-
container_args -> container_comma_expr : lists:reverse('$1').
411-
412-
call_args_parens_comma_expr -> container_expr : ['$1'].
413-
call_args_parens_comma_expr -> call_args_parens_comma_expr ',' container_expr : ['$3'|'$1'].
407+
call_args_parens_base -> container_expr : ['$1'].
408+
call_args_parens_base -> call_args_parens_base ',' container_expr : ['$3'|'$1'].
414409

415410
call_args_parens -> empty_paren : [].
416411
call_args_parens -> open_paren no_parens_expr close_paren : ['$2'].
417412
call_args_parens -> open_paren kw close_paren : ['$2'].
418-
call_args_parens -> open_paren call_args_parens_comma_expr close_paren : lists:reverse('$2').
419-
call_args_parens -> open_paren call_args_parens_comma_expr ',' kw close_paren : lists:reverse(['$4'|'$2']).
413+
call_args_parens -> open_paren call_args_parens_base close_paren : lists:reverse('$2').
414+
call_args_parens -> open_paren call_args_parens_base ',' kw close_paren : lists:reverse(['$4'|'$2']).
420415

421416
% KV
422417

@@ -426,6 +421,7 @@ kw_eol -> kw_identifier eol : '$1'.
426421
kw_expr -> kw_eol container_expr : { ?exprs('$1'),'$2' }.
427422
kw_comma -> kw_expr ',' : ['$1'].
428423
kw_comma -> kw_comma kw_expr ',' : ['$2'|'$1'].
424+
429425
kw -> kw_expr : ['$1'].
430426
kw -> kw_comma : lists:reverse('$1').
431427
kw -> kw_comma kw_expr : lists:reverse(['$2'|'$1']).
@@ -437,16 +433,18 @@ call_args_no_parens_kw -> call_args_no_parens_kw_comma : '$1'.
437433

438434
% Lists
439435

436+
list_args -> kw : '$1'.
437+
list_args -> container_args_base : lists:reverse('$1').
438+
list_args -> container_args_base ',' : lists:reverse('$1').
439+
list_args -> container_args_base ',' kw : lists:reverse('$1') ++ '$3'.
440+
440441
list -> open_bracket ']' : { [], ?line('$1') }.
441-
list -> open_bracket kw close_bracket : { '$2', ?line('$1') }.
442-
list -> open_bracket container_arg close_bracket : { ['$2'], ?line('$1') }.
443-
list -> open_bracket container_expr ',' container_args close_bracket : { ['$2'|'$4'], ?line('$1') }.
442+
list -> open_bracket list_args close_bracket : { '$2', ?line('$1') }.
444443

445444
% Tuple
446445

447446
tuple -> open_curly '}' : build_tuple('$1', []).
448-
tuple -> open_curly container_arg close_curly : build_tuple('$1', ['$2']).
449-
tuple -> open_curly container_expr ',' container_args close_curly : build_tuple('$1', ['$2'|'$4']).
447+
tuple -> open_curly container_args close_curly : build_tuple('$1', '$2').
450448

451449
% Bitstrings
452450

lib/elixir/test/elixir/keyword_test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ defmodule KeywordTest do
77
assert [B: 1] == [{ :B, 1 }]
88
assert [foo?: :bar] == [{:foo?, :bar}]
99
assert [||: 2, +: 1] == [{:||, 2}, {:+, 1}]
10+
assert [1, 2, three: :four] == [1, 2, { :three, :four }]
1011
end
1112

1213
test :ambiguity do

lib/elixir/test/elixir/tuple_test.exs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ defmodule TupleTest do
1111
assert set_elem({ :a, :b, :c }, 1, :d) == { :a, :d, :c }
1212
end
1313

14+
test :keywords do
15+
assert { 1, 2, three: :four } == { 1, 2, [three: :four] }
16+
assert { one: :two } == { [one: :two] }
17+
end
18+
1419
test :optional_comma do
1520
assert { 1 } == { 1, }
1621
assert { 1, 2, 3 } == { 1, 2, 3, }

0 commit comments

Comments
 (0)