Dev Study
← 解説「挿入モードと開いている要素のスタック — トークンを木に置く場所の決め方」に戻る

サンプルコードで身につける: 挿入モードと開いている要素のスタック — トークンを木に置く場所の決め方

解説で学んだ概念を、3つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1挿入モードの遷移と reprocess を enum と match で書く

(insertion mode)はの動作を決める変数で、HTML Standard 13.2.6 は「合わないが来たらモードを切り替えて同じトークンをもう一度処理する(reprocess)」と定めます。step 関数が (次のモード, 再処理するか) を返す形にすると、この規則が素直に書けます。実行すると、全部書いた HTML では各タグでモードが 1 段ずつ進み、<p> だけの HTML では Start("p") 1 つが 4 回再処理されて Initial から InBody まで一気に進む遷移の記録が出ます。

Rust

2開いている要素のスタックと一緒に動かす

挿入モードに「」(stack of open elements)を足した、参照実装 HtmlParser の芯だけを抜き出した構築器です。開始タグが来たらをスタックの一番上の要素の子にして積み、終了タグが来たらその要素まで下ろします。実行すると <div><p><b></b></p></div> だけの入力から、暗黙の html / head / body が積まれ、各トークンの後のスタックの中身が 1 行ずつ出て、最後に ["html", "body"] が残ります。

Rust

3実務に写す: ヘッダ + 本文の文書を挿入モードで読む

メッセージやメールと同じ「行 → 空行 → 」の形を、Start / InHeaders / InBody の 3 モードで読みます。InHeaders でヘッダに見えない行が来たら「ヘッダはここで終わった」と判断して InBody に切り替え、その行を本文としてもう一度処理するので、空行が抜けた文書でも止まらずに読めます。実行すると正規の形と空行が抜けた形の両方で同じヘッダが取れ、後者には InHeaders → InBody の再処理の記録が 1 行出ます。

Rust

図やコードに出てくる用語(タップで説明)