前回は単純化のため改行と空白を同一視した構文にしました。 これを修正して、仕様通りに改行をいれるべき場所と、改行をいれてはいけない場所を構文で扱えるようにします。 さらに、 ベアキーの特別扱いフラグを構文と字句解析の両方で操作する方法も考えます。
title="TOML の仕様は行指向" [section1] key1="value1" key2="value2" [section2] key3="value3" key4="value4" [section3] key5="value5" key6="value6"
改行の終端記号 ENDLINE を section と statements に追加します。 これで、 改行をするべき場所が決まります。 配列には改行が途中にあっても良いので、 非終端記号の optional_endline を終端記号 array の生成規則と終端記号 value_list の生成規則に加えます。 optional_endline の生成規則を追加します。
字句解析部をペアのキーを扱う状態と値を扱う状態に分けて、 前者の場合にベアキーを、 後者の場合に数値と真偽値を求めるようにします。 生成規則では pair を還元するときに字句解析部でキーを扱う状態にします。 もう一ヶ所、 table を還元するときに字句解析部で値を扱う状態にします。
toml : | statements | statements sections | sections sections : sections section | section section : '[' keypath ']' ENDLINE statements | '[' keypath ']' ENDLINE | '[' '[' keypath ']' ']' ENDLINE statements | '[' '[' keypath ']' ']' ENDLINE keypath : keypath '.' key | key key : BAREKEY | STRKEY statements : statements pair ENDLINE | pair ENDLINE pair : key '=' value { key_value_flag = LEXKEY; } value : BOOLEAN | FIXNUM | FLONUM | DATETIME | STRKEY | STRING | '[' array ']' | '{' table '}' { key_value_flag = LEXVALUE; } array : optional_endline | value_list ',' optional_endline | value_list value_list : value_list ',' optional_endline value optional_endline | optional_endline value optional_endline optional_endline : | ENDLINE table : | pair_list ',' | pair_list pair_list : pair_list ',' pair | pair
一方、 字句解析部自体では、 等号で値を扱う状態にし、 左波括弧でキーを扱う状態にします。 初期状態はキーを扱うようにします。 これで、 字句解析部でキーを扱う状態のときはベアキーを、 値を扱う状態のときに数値と真偽値を認識するように切り替えることができます。
if ('=' == octet) key_value_flag = LEXVALUE; else if ('{' == octet) key_value_falg = LEXKEY;