XionのSAX風パーザー、つまり、構文解析の結果をコールバックとしてハンドラに知らせるようなスタイルの処理系ですが、担当(?)・ショー君の仕様は、構文に忠実過ぎるかも。
JSONを定義するBNFにこだわらずに、Xion構文を直接に書き下してみましょう。次の点に注意してください。
- 例えば、objectは、JSONのobjectではなくて、taggedObject(XionObject)です。
- tagとkey(の名前)として有効な文字列は前もって定義されているとします。
- 繰り返し記号「*」は、カンマを区切り文字としての繰り返しを表すとします。
- アンダスコアから始まる構文要素は、BNF上でだけ使い、構文イベントにはなりません。
[1] object ::= tag? '{' (key ':' _value)* '}'
[2] array ::= tag? '[' _value* ']'[3] _value ::= object | array | _taggedBasicValue | atomicValue
[4] _taggedBasicValue ::= stringValue | integerValue | decimalValue
[5] atomicValue ::= true | false | null
これを次のように書き換えてみます。(今度の「*」は区切り記号なしの繰り返し。)
[1] object ::= startObject(tag) (key(name) _value)* endObject()
[2] array ::= startArray(tag) _value* endArray()[3] _value ::= object | array | _taggedBasicValue | atomicValue
[4] _taggedBasicValue ::= stringValue(tag, data) |
integerValue(tag, data) |
decimalValue(tag, data)
[5] atomicValue ::= atomicValue(which)
これから、構文イベント(コールバック)を抜き出して、出来上がり。(戻り値は全部void、例外はたぶんXionException。)
[1] objectの定義から:
- startObject(String tag)
- key(String name)
- endObject()
[2] arrayの定義から:
- startArray(String tag)
- endArray()
[4] _taggedBasicValueの定義から:
- stringValue(String tag, String data)
- integerValue(String tag, String data)
- decimalValue(String tag, String data)
[5] atomicValueの定義から(enum AtomicValue {TRUE, FALSE, NULL}
):
- atomicValue(AtomicValue which)