Rubyコードでデータを定義するためにDslhというライブラリを作った。
たとえば以下のような一見、設定ファイルのようなRubyコードをDslhでパースすると…
dsl = <<-EOS
menu {
id "file"
value ["File", "(F)"]
popup {
menuitem {
value "New"
onclick "CreateNewDoc()"
}
}
misc {
desc "File menu"
version 3
}
}
EOS
Hashに変換される。
h = Dslh.eval(<<-EOS)
# h
{"menu"=>
{"id"=>"file",
"value"=>["File", "(F)"],
"popup"=>{"menuitem"=>{"value"=>"New", "onclick"=>"CreateNewDoc()"}},
"misc"=>{"desc"=>"File menu", "version"=>3}}}
逆にデータをRubyコードに変換することもできる。
h = {"menu"=>
{"id"=>"file",
"value"=>["File", "(F)"],
"popup"=>{"menuitem"=>{"value"=>"New", "onclick"=>"CreateNewDoc()"}},
"misc"=>{"desc"=>"File menu", "version"=>3}}}
dslh_opts = {use_braces_instead_of_do_end: true, force_dump_braces: true}
puts Dslh.deval(h, dslh_opts)
menu {
id "file"
value ["File", "(F)"]
popup {
menuitem {
value "New"
onclick "CreateNewDoc()"
}
}
misc {
desc "File menu"
version 3
}
}
Hashの配列
設定ファイルをデータに変換する場合に、Hashの配列というのは割とよく出てくる。
若干コードっぽさが出てしまうが、これも記述できる。
h = Dslh.eval(<<-EOS)
menu {
id "file"
value ["File", "(F)"]
popup {
menuitem {|*|
value "New"
onclick "CreateNewDoc()"
}
menuitem {|*|
value "Open"
onclick "OpenDoc()"
}
menuitem {|*|
value "Close"
onclick "CloseDoc()"
}
}
misc {
desc "File menu"
version 3
}
}
EOS
# h
{"menu"=>
{"id"=>"file",
"value"=>["File", "(F)"],
"popup"=>
{"menuitem"=>
[{"value"=>"New", "onclick"=>"CreateNewDoc()"},
{"value"=>"Open", "onclick"=>"OpenDoc()"},
{"value"=>"Close", "onclick"=>"CloseDoc()"}]},
"misc"=>{"desc"=>"File menu", "version"=>3}}}
こちらもデータをRubyコードに変換することができる。
h = {"menu"=>
{"id"=>"file",
"value"=>["File", "(F)"],
"popup"=>
{"menuitem"=>
[{"value"=>"New", "onclick"=>"CreateNewDoc()"},
{"value"=>"Open", "onclick"=>"OpenDoc()"},
{"value"=>"Close", "onclick"=>"CloseDoc()"}]},
"misc"=>{"desc"=>"File menu", "version"=>3}}}
dslh_opts = {use_braces_instead_of_do_end: true, force_dump_braces: true}
puts Dslh.deval(h, dslh_opts)
menu {
id "file"
value ["File", "(F)"]
popup {
menuitem {|*|
value "New"
onclick "CreateNewDoc()"
}
menuitem {|*|
value "Open"
onclick "OpenDoc()"
}
menuitem {|*|
value "Close"
onclick "CloseDoc()"
}
}
misc {
desc "File menu"
version 3
}
}