Let's start Scheme

2018-08-15

YAMLパーサー

個人的にはYAMLは好きではないのだが、世の中の流れはYAMLに行っているのは明白かなぁと思っている。ということで、SagittariusにはYAMLのサポートを入れることにした。こんな感じで使える。
# test.yaml
%YAML 1.2
---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    first_name:   Dorothy
    family_name:  Gale

items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      size:      8
      price:     133.7
      quantity:  1

bill-to:  &id001
    street: |
            123 Tornado Alley
            Suite 16
    city:   East Centerville
    state:  KS

ship-to:  *id001

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.
(import (rnrs)
        (text yaml))

(call-with-input-file "test.yaml" yaml-read)

#|
(#(("receipt" . "Oz-Ware Purchase Invoice")
   ("date" . "2012-08-06T00:00:00Z")
   ("customer"
    .
    #(("first_name" . "Dorothy")
      ("family_name" . "Gale")))
   ("items"
    #(("part_no" . "A4786")
      ("descrip" . "Water Bucket (Filled)")
      ("price" . 1.47)
      ("quantity" . 4))
    #(("part_no" . "E1628")
      ("descrip" . "High Heeled \"Ruby\" Slippers")
      ("size" . 8)
      ("price" . 133.7)
      ("quantity" . 1)))
   ("bill-to"
    .
    #(("street" . "123 Tornado Alley
Suite 16
")
      ("city" . "East Centerville")
      ("state" . "KS")))
   ("ship-to"
    .
    #(("street" . "123 Tornado Alley
Suite 16
")
      ("city" . "East Centerville")
      ("state" . "KS")))
   ("specialDelivery"
    .
    "Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.
")))
|#
YAMLは一ファイルの中に複数ドキュメント含むことを許しているのでリストを返すことにした。デフォルトでは(text json)が返す書式と同じものを返すが、オプショナル引数でその辺を制御することもできる。書き出しは以下のようにする。

;; suppose variable yaml is bound to a YAML document
(yaml-write yaml)

;; if it's read by yaml-read, then it should be like this
(for-each yaml-write yaml)
書き出しはあまりこみったことをしないので(複数ラインリテラルとか、ラベルとか)、完全に元のドキュメントに復元はしない可能性がある。(ラベルくらいは実装してもいいかなぁとはブログ書いてて思った。)

これ書いてて思ったのは、YAMLの文法は思った以上に機械に優しくないということか。ヒューマンリーダブルかどうかは議論する気はないが(個人的には読みづらいと思ってる)、一文字ずつ読む感じのPEGでの実装はやる気をなくすレベルであった(ついでに公式サイトにあるBNFは人にも機械にも辛い気がする)。

あとは適当に使ってみて不具合をつぶしていくかね。

No comments:

Post a Comment