do end で引数リストにカッコを付けてはいけない謎の文法環境

Ruby ではメソッドに渡すブロックの表記に do end と {} の2つがあるが、その違いの一つは、do end は引数リストの括弧を省略できるということだ。次のようなテスト用のメソッドを用意して、確かめてみる。

# 渡された引数とブロック引数を配列にして返す。
def f x, &blk
  [:f, x, blk ? blk.call : nil ]
end
f(1) do 2 end
# => [:f, 1, 2]
f 1 do 2 end
# => [:f, 1, 2]
f(1) { 2 }
# => [:f, 1, 2]
f 1 { 2 }
# => SyntaxError

ところが、なぜか特定の文法環境でこのカッコの省略が必須になる。

p (f 1 do 2 end)
# => [:f, 1, 2]
p (f(1) do 2 end)
# => SyntaxError

もう一回カッコで囲むとコンパイルが通る。なぜだか知らない。

p ((f(1) do 2 end))
# => [:f, 1, 2]

代入の右辺や、引数リストとしての括弧の中では問題ない。

x = (f(1) do 2 end)
# => [:f, 1, 2]
x = f(1) do 2 end
# => [:f, 1, 2]
p(f(1) do 2 end)
# => [:f, 1, 2]