Adams の字下げ文法による YAML 風構文 (その2)

絶対カラム位置で字下げを扱うようにすることで、 構文の生成規則が簡潔になる上、 変更しやすくなります。 昨日は YAML を尊重して、 ブロック・シーケンスで許している、 コンパクト形式と呼ばれている同一行でのブロック要素の入れ子をブロック・マッピングでは禁止していました。 それを、 後者でも入れ子を許すようにしてみましょう。 書き換えが必要なのは block_mapping だけです。 コロンの後に空白でない文字があるかどうかのチェックを取り除いて、 常に block を使うようにします。

def block_mapping(d, n, pos1)
  h = {}
  while true
    key = trim_right(d.str, pos1, d.pos - 1)
    d, v = block(d, n + 1)
    h[key] = v
    d.col == n or break
    q = Derivs.new(d.str, d.pos, d.col)
    block_mapping_key(q) or break
    pos1, d.pos, d.col = d.pos, q.pos, q.col
  end
  [d, h]
end

これでマッピングもコンパクト形式に対応します。

src = <<'EOS'
K : L : M
    N : O
L : - value 9
    - value a
    - value b
EOS

d = Derivs.new(src, 0, 0)
x = block(d, 0)
pp x[1]
#=> {"K"=>{"L"=>"M", "N"=>"O"}, "L"=>["value 9", "value a", "value b"]}

YAML 1.2 では、 この記述は構文エラーになります。 例えば、 K の値を平文ブロックとして解釈しようとし、 平文ブロックにはコロン・空白の記述を許さないので、 解釈できない入力になります。 YAMLマッピングのコンパクト形式を許していない理由はあるのでしょうけど、 許す方が使う側にとって覚えやすいと思えます。