「まとめないといかんな」とは思いつつ日記エントリーにとりあえず書いてしまうのだった。
名前
まず「名前」という概念は、XMLに合わせましょう。「XML→JSON改」という埋め込みにそれほどこだわってはいませんが、可能な限り(無理はしないで)XMLを自然に埋め込めるようにはしたいので。
XML1.1の「名前」の定義を引用すると:
[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] [5] Name ::= NameStartChar (NameChar)*
NameCharの#xB7はナカグロ(・)です -- 1.1を採用したい唯一の理由はこれ。[追記 date="2006-05-26"]Nameにコロンが入るのはダメ、詳しくは「XMLとJSONにおけるコロン文字の扱い」。[/追記]
さて、true, false, nullはJSONで予約語扱いだから、名前から除外しておきましょう。つまり、
name = Name - {'true', 'false', 'null'}
構文規則
stringとnumberはJSONと同じだとして:
taggedString ::= name? string taggedNumber ::= name? number value ::= taggedString | taggedNumber | true | false | null | taggedObject | taggedArray taggedObject ::= name? object taggedArray ::= name? array key ::= name | string object ::= '{' '}' | '{' members '}' members ::= key ':' value | members ',' key ':' value array ::= '[' ']' | '[' elements ']' elements ::= value | elements ',' value
補足と注意
トークンは以下の通り、JSONからの拡張はnameだけ。
- 特殊文字:'{'、'}'、':'、','、'['、']'
- 予約語: true, false, null
- その他:name, string, number
true, false(型はbooleanに固定)とnull以外のJSON表現には、タグ(構文的には名前、意味的には型情報)を前置してもかまいません -- ここが主たる拡張。オブジェクトの項目(メンバ)のキーに名前も許すところがもうひとつの拡張ですね(こっちの拡張は書きやすさを改善するだけで本質的ではない)。空列""も項目キーに許すのはJSONでもOKみたいですから、拡張にはなってません。
名前や文字列を正しく認識するには、文字符号化方式(character encoding scheme)をトークナイズ作業の前に知る必要がありますが、この話は後回しにします。