Back to take 1
This commit is contained in:
@@ -13,7 +13,6 @@ Nonterminals
|
||||
expr container_expr block_expr access_expr
|
||||
no_parens_expr no_parens_zero_expr no_parens_one_expr no_parens_one_ambig_expr
|
||||
bracket_expr bracket_at_expr bracket_arg matched_expr unmatched_expr sub_matched_expr
|
||||
at_stab_expr
|
||||
unmatched_op_expr matched_op_expr no_parens_op_expr no_parens_many_expr
|
||||
comp_op_eol at_op_eol unary_op_eol and_op_eol or_op_eol capture_op_eol
|
||||
dual_op_eol mult_op_eol power_op_eol concat_op_eol xor_op_eol pipe_op_eol
|
||||
@@ -113,7 +112,6 @@ expr_list -> expr_list eoe expr : ['$3' | annotate_eoe('$2', '$1')].
|
||||
expr -> matched_expr : '$1'.
|
||||
expr -> no_parens_expr : '$1'.
|
||||
expr -> unmatched_expr : '$1'.
|
||||
expr -> at_stab_expr : '$1'.
|
||||
|
||||
%% In Elixir we have three main call syntaxes: with parentheses,
|
||||
%% without parentheses and with do blocks. They are represented
|
||||
@@ -251,13 +249,6 @@ no_parens_op_expr -> arrow_op_eol no_parens_expr : warn_pipe('$1', '$2'), {'$1',
|
||||
%% Allow when (and only when) with keywords
|
||||
no_parens_op_expr -> when_op_eol call_args_no_parens_kw : {'$1', '$2'}.
|
||||
|
||||
at_stab_expr -> at_op_eol no_parens_one_expr stab_op_eol expr :
|
||||
build_at_stab('$1', '$2', {'$3', '$4'}).
|
||||
at_stab_expr -> at_op_eol no_parens_one_ambig_expr stab_op_eol expr :
|
||||
build_at_stab('$1', '$2', {'$3', '$4'}).
|
||||
at_stab_expr -> at_op_eol no_parens_many_expr stab_op_eol expr :
|
||||
build_at_stab('$1', '$2', {'$3', '$4'}).
|
||||
|
||||
no_parens_one_ambig_expr -> dot_op_identifier call_args_no_parens_ambig : build_no_parens('$1', '$2').
|
||||
no_parens_one_ambig_expr -> dot_identifier call_args_no_parens_ambig : build_no_parens('$1', '$2').
|
||||
|
||||
@@ -364,6 +355,12 @@ stab_expr -> empty_paren stab_op_eol_and_expr :
|
||||
build_op_with_meta([], '$2', parens_meta('$1')).
|
||||
stab_expr -> empty_paren when_op expr stab_op_eol_and_expr :
|
||||
build_op_with_meta([{'when', meta_from_token('$2'), ['$3']}], '$4', parens_meta('$1')).
|
||||
stab_expr -> at_op_eol no_parens_one_expr stab_op_eol_and_expr :
|
||||
build_at_stab('$1', '$2', '$3').
|
||||
stab_expr -> at_op_eol no_parens_one_ambig_expr stab_op_eol_and_expr :
|
||||
build_at_stab('$1', '$2', '$3').
|
||||
stab_expr -> at_op_eol no_parens_many_expr stab_op_eol_and_expr :
|
||||
build_at_stab('$1', '$2', '$3').
|
||||
stab_expr -> call_args_no_parens_all stab_op_eol_and_expr :
|
||||
build_op(unwrap_when(unwrap_splice('$1')), '$2').
|
||||
stab_expr -> stab_parens_many stab_op_eol_and_expr :
|
||||
@@ -781,11 +778,16 @@ build_unary_op({_Kind, {Line, Column, _}, '//'}, Expr) ->
|
||||
{'/', [{line, Line} | Outer], [{'/', [{line, Line} | Inner], nil}, Expr]};
|
||||
|
||||
build_unary_op({_Kind, Location, Op}, Expr) ->
|
||||
{Op, meta_from_location(Location), [Expr]}.
|
||||
{Op, meta_from_location(Location), [normalize_unary_op(Op, Expr)]}.
|
||||
|
||||
build_at_stab(At, {Call, Meta, Args}, {Op, Right}) ->
|
||||
build_unary_op(At, {Call, Meta, [build_op(Args, Op, Right)]}).
|
||||
|
||||
normalize_unary_op('@', {Call, Meta, [[{'->', _, [_, _]} = Stab]]}) when is_atom(Call), is_list(Meta) ->
|
||||
{Call, Meta, [Stab]};
|
||||
normalize_unary_op(_, Expr) ->
|
||||
Expr.
|
||||
|
||||
build_nullary_op({_Kind, Location, Op}) ->
|
||||
{Op, meta_from_location(Location), []}.
|
||||
|
||||
|
||||
@@ -7,8 +7,14 @@ defmodule Kernel.TypingSyntaxTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
describe "@ with -> in quote" do
|
||||
test "wraps the arrow as the attribute call argument at the root" do
|
||||
assert parse_quote("@sig foo -> bar") ==
|
||||
test "does not parse arrows at the root" do
|
||||
assert_raise SyntaxError, ~r/syntax error before: '->'/, fn ->
|
||||
parse_quote("@sig foo -> bar")
|
||||
end
|
||||
end
|
||||
|
||||
test "wraps parenthesized arrows as the attribute call argument at the root" do
|
||||
assert parse_quote("(@sig foo -> bar)") ==
|
||||
{:@, [line: 1],
|
||||
[
|
||||
{:sig, [line: 1],
|
||||
@@ -16,8 +22,14 @@ defmodule Kernel.TypingSyntaxTest do
|
||||
]}
|
||||
end
|
||||
|
||||
test "wraps multi-argument arrows as the attribute call argument at the root" do
|
||||
assert parse_quote("@sig foo, bar -> baz") ==
|
||||
test "does not parse multi-argument arrows at the root" do
|
||||
assert_raise SyntaxError, ~r/syntax error before: '->'/, fn ->
|
||||
parse_quote("@sig foo, bar -> baz")
|
||||
end
|
||||
end
|
||||
|
||||
test "wraps parenthesized multi-argument arrows as the attribute call argument at the root" do
|
||||
assert parse_quote("(@sig foo, bar -> baz)") ==
|
||||
{:@, [line: 1],
|
||||
[
|
||||
{:sig, [line: 1],
|
||||
@@ -159,14 +171,29 @@ defmodule Kernel.TypingSyntaxTest do
|
||||
[
|
||||
do:
|
||||
{:@, [line: 2],
|
||||
[
|
||||
{:sig, [line: 2], [[{:->, [line: 2], [[], {:bar, [line: 2], nil}]}]]}
|
||||
]}
|
||||
[{:sig, [line: 2], [{:->, [line: 2], [[], {:bar, [line: 2], nil}]}]}]}
|
||||
]
|
||||
]}
|
||||
end
|
||||
|
||||
test "allows explicit parenthesized arrows with arguments as attribute call arguments" do
|
||||
test "normalizes parenthesized arrows to the same AST as arrow arguments" do
|
||||
assert parse_quote("""
|
||||
quote do
|
||||
pre
|
||||
@sig foo -> bar
|
||||
post
|
||||
end
|
||||
""") ==
|
||||
parse_quote("""
|
||||
quote do
|
||||
pre
|
||||
@sig (foo -> bar)
|
||||
post
|
||||
end
|
||||
""")
|
||||
end
|
||||
|
||||
test "normalizes explicit parenthesized arrows with arguments as attribute call arguments" do
|
||||
assert parse_quote("""
|
||||
quote do
|
||||
@sig (foo -> bar)
|
||||
@@ -179,11 +206,7 @@ defmodule Kernel.TypingSyntaxTest do
|
||||
{:@, [line: 2],
|
||||
[
|
||||
{:sig, [line: 2],
|
||||
[
|
||||
[
|
||||
{:->, [line: 2], [[{:foo, [line: 2], nil}], {:bar, [line: 2], nil}]}
|
||||
]
|
||||
]}
|
||||
[{:->, [line: 2], [[{:foo, [line: 2], nil}], {:bar, [line: 2], nil}]}]}
|
||||
]}
|
||||
]
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user