[1] 本項では [[HTML]] と [[XML]] の[[構文解析器]]の基礎的な概念を扱います。専ら一方のみに関係する事項は、
[[HTML構文解析器]]と[[XML構文解析器]]の項をご覧ください。

* 状態

[83] 次のような状態を持ちます。
[FIG(list members)[
: [F[型]] : [[HTML構文解析器]]または[[XML構文解析器]]です。
: [F[[[入力バイトストリーム]]]] :
: [F[[[入力ストリーム]]]] :
[[script-created parser]] では書き込みが行われます。
: [F[[[confidence]]]]: 初期値が与えられます。
: [F[[[挿入点]]]] : 
[[入力ストリーム]]中の位置または[[未定義]]です。
[CODE(JS)@en[[[document.write]]]] からも参照されます。
[[仕様書]]は [[HTML構文解析器]]にのみ定義していますが、
[[XML構文解析器]]にも存在すると考えることで、両者の処理を統合できます。
([[仕様書]]でも [[stop parsing]] で[[XML構文解析器]]であっても[F[[[挿入点]]]]が参照されています。)
: [F[[[次入力文字]]]] :
: [F[[[開いている要素のスタック]]]] :
: [F[[[現在節点]]]] :
: [F[[[挿入モード]]]] :
: [F[[[文書]]]] :
: [F[[[abort]] 済み]] :[[構文解析器のabort]]が行われたかどうか。
[[構文解析器]]外部から参照されることがあります。
: [F[[[stop parsing]] 済み]] :[[stop parsing]] が行われたかどうか。
[[構文解析器]]のフラグというよりは[[文書]]の [[completely loaded]] フラグと解釈するのが自然かもしれません ([[stops parsing]] 参照)。
[[構文解析器]]外部から参照されることがあります。
: [DFN[[F[[RUBYB[[[スクリプト入れ子水準]]]@en[script nesting level]]]]]] :
[CODE(JS)@en[[[document.write]]]] の再帰呼び出しを管理する変数です。
初期状態では0に設定されます。
[[仕様書]]は [[HTML構文解析器]]にのみ定義していますが、
[[XML構文解析器]]にも存在すると考えることで、両者の処理を統合できます。
: [DFN[[F[[RUBYB[[[構文解析器停止フラグ]]]@en[[[parser pause flag]]]]]]]] :
[CODE(JS)@en[[[document.write]]]] による[[構文解析器]]の動作停止を管理するフラグです。
初期状態では[[偽]]に設定されます。
[[仕様書]]は [[HTML構文解析器]]にのみ定義していますが、
[[XML構文解析器]]にも存在すると考えることで、両者の処理を統合できます。
: [F[素片構文解析]] :
[[構文解析]]が[[素片構文解析]]モードで実行されるか否か。
[F[現在節点]]が [CODE[null]] ではないか否かと等価。

]FIG]

* 構文解析器と文書

[10] [[構文解析器]]は[[文書]]に関連付けられています。

;; [[navigate]] において[[構文解析器]]を作成した時に関連付けられます。

[11] [[文書]]から見て動作中の[[構文解析器]]のことを(あれば)[[活性構文解析器]]といいます。

[73] [[文書]]が[F[構文解析器]]を持つか否かとその状態は、
[[try to scroll to the fragment]]
で参照されます。

[12] ある[[構文解析器]]の[[インスタンス]]が扱う[[文書]]は1つだけです。

;; ただし [CODE(HTMLe)@en[[[template]]]] [[要素]]があるときは、[[雛形内容]]の[[文書]]も関係してきます。
また、[[スクリプト]]によって挿入先の[[要素]]が別の[[文書]]に移動された時は、その[[文書]]に新しい[[節点]]も挿入されることになります。

[13] [[文書]]に対してそれを扱う[[構文解析器]]は1つとは限りません。例えばその[[文書]]自体を作った[[構文解析器]]と
[CODE(DOMa)@en[[[innerHTML]]]] の[[構文解析器]]は別物です。また [CODE(JS)@en[[[document.open]]]]
では新しい[[構文解析器]]が作られます。

[81] [[スクリプトの準備]]では、[CODE(HTMLe)@en[[[script]]]]
[[要素]]の[[節点文書]]と [CODE(HTMLe)@en[[[script]]]]
[[要素]]を作成した[[構文解析器]]の[F[[[文書]]]]が等しいか比較されます。

[82] [[スクリプトの準備]]では、 [CODE(HTMLe)@en[[[script]]]]
[[要素]]を作成した[[構文解析器]]の種別 ([[HTML]] or [[XML]])
や[F[[[スクリプト入れ子水準]]]]が参照されます。
作成した[[構文解析器]]の[F[[[文書]]]]の[[スクリプトをブロックしているスタイルシートを持つ]]かどうかや、
[[スクリプト]]に関するリストや集合各種も参照されます。

[100] この他、[[文書]]には [CODE(JS)@en[document.write]] の動作に関わる内部状態がいくつかあり、
[[構文解析器]]から参照・変更されます。

-*-*-

[26] 
[[文書]]は、
[DFN[[F[[RUBYB[[[活性構文解析器]]][active parser]]]]]]を持つことがあります。

[75] 
[[文書]]は、
[DFN[[F[[RUBYB[[[活性構文解析器がabortされた]]][active parser was aborted]]]]]]を持ちます。
初期値は[[偽]]です。
[SRC[[CITE[HTML Standard]]]]
[[文書のabort]]で[[真]]に設定されます。
[CODE[document.open]], [CODE[document.write]] などに影響します。


* 入力

[24] [[構文解析]]の対象となる入力は、[[入力バイトストリーム]] ([[バイト列]])
または[[入力ストリーム]] ([[文字列]]) として[[構文解析器]]に与えられます。

[FIG(list)[
- [76] [[バイト列]] ([[ストリーム]])
-- [36] [[navigate]] 中は、 [[fetch]] が受信した[[バイト列]]毎にキューに入れる[[タスク]]により、
[[入力バイトストリーム]]に[[バイト列]]が追加されていき、[[構文解析]]が行われます [SRC[>>32]]。
[[fetch]] がキューに入れた末尾を表す[[タスク]]により、 [[EOF]] が[[入力バイトストリーム]]に挿入されます [SRC[>>32]]。
- [79] [[バイト列]]
-- [44] [CODE(DOMa)@en[[[responseXML]]]] は[[応答]]に含まれる[[バイト列]]を[[入力バイトストリーム]]として一度に[[構文解析]]を行います [SRC[>>43]]。
-- [47] [CODE(JS)@en[[[document.load]]]] は[[応答]]に含まれる[[バイト列]]を[[入力バイトストリーム]]として一度に[[構文解析]]を行います [SRC[>>46]]。
-- [45] [CODE(XML)@en[[[xml-stylesheet]]]] によって指定された [[XSLT]]
[[文書]]については仕様書がなく不明です。
- [77] [[文字列]] ([[ストリーム]])
-- [37] [CODE(JS)@en[[[document.write]]]] や [CODE(JS)@en[[[document.writeln]]]] は、
[[入力ストリーム]]の[[挿入点]]前に[[文字列]]を追加していき、[[構文解析]]を行います [SRC[>>33]]。
[[挿入点]]は[[入力ストリーム]]の末尾とは限りません。
-- [38] [CODE(JS)@en[[[document.close]]]] は、[[入力ストリーム]]に [[EOF]]
を挿入します [SRC[>>34]]。
- [78] [[文字列]]
-- [39] [CODE(DOMm)@en[[[parseFromString]]]], [CODE(DOMa)@en[[[innerHTML]]]],
[CODE(DOMa)@en[[[innerHTML]]]], [CODE(DOMm)@en[[[insertAdjacentHTML]]]],
[CODE(DOMm)@en[createContextualFragment]] [SRC[>>35]], [CODE(DOM)@en[insertHTML]]
は[[文字列]]を[[入力ストリーム]]として一度に[[構文解析]]を行います。

[REFS[
- [32] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#read-html>
- [33] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#dom-document-write>
- [34] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close>
- [35] [CITE[DOM Parsing and Serialization Standard]] ([TIME[2014-06-28 14:24:26 +09:00]] 版) <https://domparsing.spec.whatwg.org/>
- [43] [CITE@en-US[XMLHttpRequest Standard]] ([TIME[2014-06-30 13:50:27 +09:00]] 版) <http://xhr.spec.whatwg.org/#document-response>
- [46] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2014-07-10 19:47:06 +09:00]] 版) <http://www.whatwg.org/specs/web-apps/current-work/#dom-xmldocument-load>
]REFS]
]FIG]

[25] 入力がバイト列の場合は、[[バイト]]の解釈に用いる[[文字符号化]]や[[ロケール]]、
呼び出される文脈 ([[navigate]] か [[XHR]] か) といった情報も与える必要があります。
詳しくは [[charset sniffing]] を参照。

[HISTORY[
[92] かつては[[ロケール]]が [CODE(HTMLe)@en[[[isindex]]]] [[開始タグ]]の解釈にも影響しました。
]HISTORY]

[30] [[HTML構文解析器]]と[[XML構文解析器]]では、[[構文解析]]の各段階の動作に様々な違いが生じます。

[27] [[HTML構文解析器]]の動作は、[[スクリプト有効]]か否かで変化します。

;; [[スクリプトフラグ]]を参照してください。

;; [72] [[スクリプト]]を実装しない場合は、[[スクリプトが無効]]な場合の動作だけ実装すれば十分です。[[スクリプト]]を実装する場合は、
[[スクリプトが無効]]な場合と[[スクリプトが有効]]な場合の両方を実装する必要があります。

[29] [CODE(DOMa)@en[[[innerHTML]]]] など[[素片構文解析]]では、
[[文脈要素]]によって[[構文解析]]の開始の時点の状態やその後の動作が左右されます。

;; [[文脈要素]]の名前や[[属性]]の他、[[祖先]]が影響することもあります。

* 出力

[28] [[構文解析]]の結果は、開始時に指定された[[親]]となる[[節点]]の[[子孫]]という形で現れます。
また、[[奇癖モード]]か否かなど、内部状態 ([[IDL属性]]など) を変化させることもあります。

[31] また、[[構文解析器]]は、1つ以上の[[構文解析エラー]]を発見すると、
これを報告することがあります。仕様上義務付けられてはいませんが、
[[Webブラウザー]]によっては [[Console]] に[[構文解析エラー]]を報告するようです。

;; [[スクリプト]]などで[[著者]]がこれを受け取ることはできないようです。

* 一時停止

** 構文解析器内部での一時停止

[2] [[構文解析器]]は [[HTML]] の [CODE(HTMLe)@en[[[script]]]] [[終了タグ]]の処理の一部で[[イベントループをスピン]]することがあります。
また[[字句解析器]]・[[構文解析器]]が[[ブロック][字句化器のブロック]]されます。これらにより、特定のスクリプト群の実行が終わるまで[[構文解析器]]は処理を停止することになります。

;; [CODE(HTMLe)@en[script]]、[[字句化器のブロック]]参照。

[3] [[HTML構文解析器]]に(のみ)は、 [[parser pause flag]] があり、このフラグが設定されている間は[[字句化器]]の処理が止まります。
これは入れ子の [CODE(JS)@en[[[document.write]]]] の呼び出しや
[[SVG]] [CODE(XMLe)@en[[[script]]]] [[要素]]からの [CODE(JS)@en[[[document.write]]]] の呼び出しの[[構文解析]]処理を[[スクリプト]]実行後まで遅延させるために使われています。

;; [[XML]] では [CODE(JS)@en[[[document.write]]]] が使えないので、相当するフラグはありません。

[15] [[XML構文解析器]]で[[外部実体]]を展開する時は、主たる構文解析を一時停止して、外部実体側の構文解析が終了したら戻ってくる形で実装することになるでしょう。
これは [CODE(JS)@en[[[document.write]]]] のように[[入力ストリーム]]の現在位置に外部実体側の[[入力ストリーム]]からバイト列を挿入していく形でも実装できるでしょうし、
別の構文解析器の結果を受け取って主たる構文解析器の出力に挿入する形でも実装できるでしょう。

;; [16] ただし [[HTML Standard]] に従う[[XML構文解析器]]は[[外部実体]]の展開を行いません。

[52] [[HTML字句化器]]は「各ステップ前」に [[parser pause flag]] をチェックして、
[[真]]なら[[字句化]]しないことになっています。「各ステップ」が何を指しているか不明瞭ですが、
[[parser pause flag]] は [[HTML]]/[[SVG]] [CODE(HTMLe)@en[[[script]]]] 
[[タグ]]による[[スクリプト]]処理の際と[[字句の要素の作成]]で[[カスタム要素]]を作成する際にのみ[[真]]になることがあるものなので、
[[スクリプト]]実行の次の[[字句]]の取得の処理や、
次の[[タスク]]による[[字句化器]]からの[[字句]]の取得の処理を実行しようとした時にチェックすれば十分そうです。

;; [53] [[parser pause flag]] と「ブロック」は同じ動作のように見えますが、
[[parser pause flag]] はあらゆる[[字句化器]]の呼び出しを止めるのに対し、
ブロックは別の[[タスク]]による[[字句化器]]の呼び出しだけを止めます。
ですから、ブロック中に実行された[[スクリプト]]によって [CODE(JS)@en[[[document.write]]]]
が呼び出された場合は、 [[parser pause flag]] が[[真]]でなければ、
その[[字句化]]は行われます。

** スクリプトによる一時停止

[54] [[構文解析器]]による[[スクリプト]]実行のための一時停止以外にも、
[[構文解析器]]から呼び出された[[スクリプト]]の処理のために[[イベントループ]]の実行の一時停止が発生することがあります。
当然ながらその間も[[構文解析器]]は停止したままです。

[EG[
[55] 例えば[[スクリプト]]内部で [CODE(JS)@en[[[alert]]]] を実行すると[[イベントループ]]は
[[pause]] します。また [CODE(DOMm)@en[[[showModalDialog]]]] を実行すると[[イベントループのスピン]]が派生します。
]EG]

[56] 明示的に実行が停止されなくても、処理の実行が長時間に渡り実質的に停止状態となることもあります。

[EG[
[57] 例えば [[XHR]] を同期モードで呼び出すと、 [[fetch]] が完了するまで[[メソッド]]呼び出しが完了しないので、
当然その間[[構文解析器]]は停止したままです。
]EG]

* 停止

[40] [[構文解析]]は、正常終了 (>>6) か中断 (>>4) のいずれかによって終了します。

;; [41] [[構文解析]]は、終了するとは限りません。[[鯖]]から無限の[[バイト列]]が送信され続けている場合は、
[[構文解析]]も無限に続きます。

** 正常終了

[6] [[構文解析]]の処理がすべて終了すると、 [[stop parsing]] が実行されます。

** 中断

[4] [[構文解析器]]は [[abort a parser]] が呼び出されると[[入力ストリーム]]や[[開いている要素のスタック]]を破棄します。
これによって未処理の入力は捨てられ、それ以降の[[字句化]]が行われません。

[5] abort は、 [CODE(JS)@en[[[window.close]]]] や [CODE(JS)@en[[[document.open]]]] が呼ばれた時や、
[[navigate]] されて現在の[[文書]]が破棄される場合などに呼ばれます。

;; [74] [[abort a parser]] を参照。

[58] [[スクリプト]]は実行時間等の制限超過によって停止させられることがあります
([[スクリプト]]の項を参照)。[[構文解析器]]から呼び出された[[スクリプト]]が停止された場合、
[[スクリプト]]が正常終了した場合と同じように[[構文解析器]]の処理が再開されるものと思われます。

[59] [[スクリプト]]から呼び出した[[構文解析器]]の処理に時間がかかるような場合、
[[構文解析器]]の動作が途中で停止させられることもあるかもしれません。
[[構文解析器]]から呼び出された[[スクリプト]]からの[[構文解析器]]の呼び出しに時間がかかる場合どのように処理されるのか謎です。

* 再帰的実行

[7] [[HTML構文解析器]](のみ)は [CODE(JS)@en[[[document.write]]]] や [CODE(JS)@en[[[document.writeln]]]]
により、[[スクリプト]]を介して再帰的に呼び出されることがあります。外側と内側でどちらも同じ[[構文解析器]]ですから、
入力ストリームや種々の状態はすべて共有されています。外側の構文解析処理は、内側で行われた構文解析器への操作により発生する処理の続きとしてスクリプト終了後に継続されます。

[8] このため [[HTML構文解析器]]は[[スクリプト]]が実行するまで続きを[[字句解析]]・[[構文解析]]できません
(投機的実行はできますが)。

;; [9] [CODE(JS)@en[[[document.write]]]] がなかったとしても、また実際に無い [[XML]] であっても、
[[DOM]] に反映させると[[スクリプト]]から観測可能になってしまうので、その直前までしか処理できません。

;; [42] ここでいう再帰的呼び出しとは、同一の[[構文解析器]]の[[インスタンス]]が[[スクリプト]]を介して呼び出されることをいいます。
別の対象を[[構文解析]]する別の[[インスタンス]]が[[スクリプト]]から呼び出されること
(例えば [[navigate]] によって呼び出された [[HTML構文解析器]]の処理中に[[スクリプト]]から
[CODE(DOMa)@en[[[innerHTML]]]] によって別の[[構文解析器]]が作られ、実行されること) はよくあります。

* 再起動

[14] [[HTML構文解析器]](のみ)は[[文字符号化宣言]]を発見し、処理中の[[文字符号化]]と実際の[[文字符号化]]が一致していないことを検出したとき、
[[change the encoding]] 処理により再起動することがあります。この再起動は、現在の[[文書]]破棄して同じ入力バイト列に対して
[[navigate]] しなおすというかなり強引な形で行われます。[[スクリプト]]により[[著者]]に、
[[レンダリング]]により[[利用者]]に観測可能なこともあります。

[70] [[HTML構文解析器]]や[[XML構文解析器]]によって呼び出される[[アプリケーションキャッシュ選択アルゴリズム]]も、
[[navigate]] 全体をやり直させることがあります。

* 構成要素

[61] [[構文解析器]]は次の部分で構成されます。

;; [62] なお、これはあくまで仕様書上の構成であって、同じ入力に対して同じ動作をする限り、
この構成に従う必要はありません。

[FIG(list)[
- [[入力バイトストリーム]]、[[入力ストリーム]]
- [[字句化器]]
-- [[字句化器の状態]]
- [[木構築器]]
-- [[挿入モード]]
-- [[開いている要素のスタック]]
-- [[活性書式付け要素のリスト]]
]FIG]

[FIG(flow)[
:net:[[ネットワーク]]
:v:
:->:ibs

:ibs:[[入力バイトストリーム]]
:->:is

:is:[[入力ストリーム]]
:->:token

:token:[[字句]]列
:->:dom

:dom:[[DOM]] [[木]]
:->:ibs
:->:script

:script:[[スクリプト]]
:->:is
:->:net
:>>:2
:v:
]FIG]

** 字句化器と木構築器

[63] [[字句化]]と[[木構築]]は、2つのほぼ独立した処理段階として規定されていますが、
いくつか例外的に両者の動作が干渉することがあります。いずれも[[HTML構文解析器]]のみの動作です。

[FIG(list)[
- [64] [[木構築器]]の[[開始タグ]]・[[終了タグ]]の処理が、[[字句化器]]の[[状態]]を変更することがあります。
-- [CODE(HTMLe)@en[[[title]]]] や [CODE(HTMLe)@en[[[plaintext]]]] 
など[[内容]]を特別な方法で[[字句化]]する[[要素]]の処理で発生します。
- [65] [[木構築器]]の状態である[[調整済み現在節点]]の種類により、
[[字句化器]]が[[CDATA区間]]を認識するかどうかが変化します。
-- [[親要素]]となる[[要素]]が[[SVG]]か[[MathML]]なら[[CDATA区間]]として[[字句化]]され、
[[HTML]]なら[[注釈]]として[[字句化]]されます。
- [66] [[開始タグ]]字句の[[認められている斜線]]が[[構文解析エラー]]となるか否かは、
[[木構築器]]で承認されるかどうかに依存します。
]FIG]

[67] これは一例として次のように実現できます。
[FIG(steps)[
= [[入力ストリーム]]が [[EOF]] に達するまで次の処理を繰り返す。
== [[字句化]]を行う。ただし、次の条件のいずれかを満たしたら停止する。
==- [[字句化器の状態]]を変化させ得る[[タグ名]]の[[開始タグ]]・[[終了タグ]]を[[送出]]した時
==- [[マーク付け宣言開き状態]]で [CODE[''[''[[CDATA]]''['']] まで到達した時
== 得られた[[字句]]の列を[[木構築器]]に渡して処理させる。
]FIG]

[94] ここで、 >>63 だけでなく、[[スクリプト]]が [CODE(JS)@en[document.write]] 
から[[入力ストリーム]]に介入する可能性も考慮する必要があります。
具体的には、次のものがあります。
[FIG(list)[
- [95] [[HTML]] [CODE(HTMLe)@en[script]] [[終了タグ]]
- [96] [[SVG]] [CODE(HTMLe)@en[script]] [[終了タグ]]
- [97] [[自律カスタム要素]]の[[開始タグ]] ([F[タグ名]]に [CODE[-]] が含まれるもの)
- [98] [[カスタム化組み込み要素]]の[[開始タグ]] ([CODE(HTMLa)@en[is][is=""]] 
[[属性]]が含まれるもの)
]FIG]

[71] [[アプリケーションキャッシュ選択アルゴリズム]]の実行タイミングにも注意が必要です。
>>67 だけでは正しく処理できないケースがあります。 ([[構文解析器]]の動作そのものには影響しませんが、
[[スクリプト]]と [[fetch]] 経由で動作が変化する可能性はあります。)

** 字句化器と API

[68] [[navigate]] によって、あるいは[[スクリプト]]が [[DOM API]] によって[[構文解析器]]・[[字句化器]]を作成し動作させる場合以外に、
次の場合に外部から[[字句化器]]の挙動が操作されることがあります。
これは[[構文解析器]]中の[[文書]]に含まれる[[スクリプト]]の実行によって呼び出されることもあれば、
他の[[閲覧文脈]]から呼び出されることもあります。

[FIG(flow)[
:open:[CODE(JS)@en[[[document.open]]]]
:->:write
:->:writeln

:write:[CODE(JS)@en[[[document.write]]]] / [CODE(JS)@en[[[document.writeln]]]]
:->:write
:->:close

:close:[CODE(JS)@en[[[document.close]]]]
]FIG]

;; [69] [[平文]]への [[navigate]] や [CODE(MIME)@en[[[text/plain]]]] などを指定した
[CODE(JS)@en[[[document.open]]]] は、[[字句化器]]の初期状態を
[[PLAINTEXT state]] に設定します。

* 字句化

[84] [[HTML]] でも [[XML]] でも、[[文字字句]]以外のすべての[[字句]]に対応するソース上の構造は
[CODE[[[<]]]] から始まります。

;; [85] [[文字字句]] (の連続) も、 [[CDATA区間]]の場合は [CODE[[[<]]]] から始まります。

;; [86] [[字句]]より細かな[[字句]]に類する単位としては、[[属性]] ([[要素字句]]内) や[[属性定義]]
([[DOCTYPE字句]]内の[[要素宣言]]内) が [CODE[[[<]]]] 以外から始まりますが、
その他は [CODE[[[<]]]] から始まります。

[87] 特定の[[属性]]の値によって分岐することは、[[字句化器]]内ではありません。

[88] [[HTML構文解析器]]の[[木構築器]]では次の分岐があります。

[FIG(list)[
- [CODE(HTMLe)@en[[[meta]]]] [[要素]]の [CODE(HTMLa)@en[[[charset]]]] [[属性]]、
[CODE(HTMLa)@en[[[http-equiv]]]] [[属性]]、[CODE(HTMLa)@en[[[content]]]] [[属性]]
([[change the encoding]])
- [CODE(XMLe)@en[[[annotation-xml]]]] [[要素]]の [CODE(XMLa)@en[[[encoding]]]] [[属性]]
([[MathMLテキスト統合点]])
- [CODE(HTMLe)@en[[[font]]]] [[要素]]の [CODE(HTMLa)@en[[[color]]]] [[属性]]、
[CODE(HTMLa)@en[[[face]]]] [[属性]]、[CODE(HTMLa)@en[[[size]]]] [[属性]]
([[外来要素]]内)
- [CODE(HTMLe)@en[[[input]]]] [[要素]]の [CODE(HTMLa)@en[[[type]]]] [[属性]]
([["in table"]] [[挿入モード]])
- [CODE(HTMLe)@en[[[html]]]] [[要素]]の [CODE(HTMLa)@en[[[manifest]]]] [[属性]]
([[応用キャッシュ選択アルゴリズム]])

[HISTORY[
- [CODE(HTMLe)@en[[[isindex]]]] [[要素]]の [CODE(HTMLa)@en[[[action]]]] [[属性]]、
[CODE(HTMLa)@en[[[name]]]] [[属性]]、[CODE(HTMLa)@en[[[prompt]]]] [[属性]]
]HISTORY]
]FIG]

[89] [[XML構文解析器]]の[[木構築器]]では次の分岐があります。

[FIG(list)[
- [[根]] [CODE(HTMLe)@en[[[html]]]] [[要素]]の [CODE(HTMLa)@en[[[manifest]]]] [[属性]]
([[応用キャッシュ選択アルゴリズム]])
- [[名前空間属性]]
]FIG]

;; [90] [CODE(XMLa)@en[[[xml:space]]]] [[属性]]は[[構文解析器]]の動作には影響しません。

[99] [[字句の要素の作成]]では次の分岐があります。
[FIG(list)[
- [[カスタム化組み込み要素]]の [CODE(HTMLa)@en[is][is=""]] [[属性]]
- [[被列挙要素]]の [CODE(HTMLa)@en[form][form=""]] [[属性]]
- [[外来要素]]の [CODE(XMLa)@en[[[xmlns]]]] [[属性]] ([[構文解析エラー]])
- [[外来要素]]の [CODE(XMLa)@en[[[xmlns:xlink]]]] [[属性]] ([[構文解析エラー]])
]FIG]

[91] なお、[[属性]]はこれ以外には、 [CODE(DOMi)@en[[[Element]]]] 
の作成時に[[内容属性]]として設定される他は、
既存の [CODE(HTMLe)@en[[[html]]]] [[要素]]や [CODE(HTMLe)@en[[[body]]]] [[要素]]に追加されるケース、
[[活性書式付け要素のリスト]]への追加時に比較されるケースがあります (いずれも[[HTML構文解析器]]のみ)。

* DOM 操作

[21] [[構文解析器]]による[[DOM木]]の操作は、基本的には [[DOM]] [[API]]
によって行われる操作と同じものですが、一部は特別な動作が定義されていることもあります。

[22] [[構文解析器]]による [[DOM]] 操作の動作については、次の各項を参照してください。

[FIG(short list)[
- [[要素の作成]]
- [[開いている要素のスタック]]
]FIG]

[23] [[節点]]の作成や[[節点]]の内部状態 ([[IDL属性]]の値) の設定
([CODE(HTMLm)@en[[[createElementNS]]]] や [CODE(DOMa)@en[[[compatMode]]]]
など) に加えて、次のような[[メソッド]]に相当する操作が行われます。

[FIG(list short)[
- [CODE(DOMm)@en[[[ownerDocument]]]] ([[節点]]の作成時)
- [CODE(DOMa)@en[[[nodeType]]]]
- [CODE(DOMa)@en[[[namespaceURI]]]]
- [CODE(DOMa)@en[[[localName]]]]
- [CODE(DOMm)@en[[[appendChild]]]]
- [CODE(DOMa)@en[[[content]]]] ([CODE(HTMLe)@en[[[template]]]] への挿入時)
- [CODE(DOMa)@en[[[lastChild]]]] ([[テキスト]]の挿入時)
- [CODE(DOMa)@en[[[previousSibling]]]] ([[里親付け]]で[[テキスト]]の挿入時)
- [CODE(DOMm)@en[[[insertBefore]]]] ([[里親付け]])
- [CODE(DOMm)@en[[[setAttributeNS]]]]
- [CODE(DOMm)@en[[[hasAttributeNS]]]] ([CODE(HTMLe)@en[[[html]]]]/[CODE(HTMLe)@en[[[body]]]] [[開始タグ]]重複時)
- [CODE(DOMa)@en[[[parentNode]]]] ([[里親付け]])
- [CODE(DOMm)@en[[[remove]]]] ([CODE(HTMLe)@en[[[body]]]] 内の [CODE(HTMLe)@en[[[frameset]]]] [[開始タグ]]時)
- [CODE(DOMa)@en[[[childNodes]]]] ([[AAA]] による[[節点]]移動時)
]FIG]

[49] [[構文解析器]]による [[DOM]] の操作は、[[変異観察器]]に報告されます。

;; [50] [[変異イベント]]は[[発火]]しません。

[51] [[雛形内容]]は別の[[文書]]に属するため、また[[スクリプト]]によって[[節点]]がまったく別の[[文書]]に移動される可能性があるため、
[[構文解析器]]が扱う[[節点]]が同じ[[文書]]に属する保証はありません。

* 特別な動作

[60] [[構文解析器]]は純粋な[[DOM木]]の構築操作の他に、次のような動作をします。

[FIG(list short)[
- [[符号化の変更]] (>>14)
- [[構文解析エラー]]の報告
- 文書のモードの設定 ([[DOCTYPEスイッチ]])
- [[要素の作成]]やスタックからの除去に付随する動作 (>>22)
- [[スクリプト]]の実行 (>>48)
- [[アプリケーションキャッシュ選択アルゴリズム]]
]FIG]

[48] [[構文解析器]]の動作中に[[スクリプト]]が実行されることがあります。
[[スクリプト]]と[[構文解析器]]の処理は複雑に関わっています。

;; 詳しくは [CODE(HTMLe)@en[script]] や[[字句の要素の作成]]の項を参照してください。

[93] [[スクリプト]]の前後には、[[マイクロタスク]]が実行されます。
[[構文解析器]]による[[挿入]]に伴う[[変異観察器]]への報告 (>>49) は、
このタイミングで実行されます。

[80] [[Webブラウザー]]によっては、[[文書要素]]の[[文書への挿入]]のタイミングで[[内容スクリプト]]を実行できるかもしれません。

* 歴史

[FIG(quote)[
[17] 
>
:[RUBYB[構文解析][parsing]]:
構文解析とは、[[文書]]を走査し、
[[文書]]の中に含まれている[[情報]]を[[情報]]が[[構造化]]されている[[要素]]の文脈において濾過する行為です。

[FIGCAPTION[
[REFS[
- [[XHTML 1.0]]
--[CITE[2.2. General Terms]]
<IW:XHTML10:"general">
]REFS]
]FIGCAPTION]
]FIG]

[18] [[HTML構文解析器]]の動作は、長らく明確に規定されていませんでしたが、
2007年頃、 [[Web Applications 1.0]] (後の [[HTML5]]) によって初めて詳細な動作が記述されました。

;; 詳しくは [[HTML構文解析器]]を参照。

[19] [[XML構文解析器]]の動作は、 [[XML]] 本体仕様によってごく限定的に制約が規定されていました。
より詳細な動作は [[XML5]] (後の [[XML-ER]]) によって [[HTML構文解析器]]に倣って定義されましたが、
[[XML]] に対する関心の低さのため、仕様書は未完成のまま保留状態にあります。
[[HTML Standard]] にも限定的ながら[[XML構文解析器]]の動作の規定があります。

[20] [[構文解析器]]を呼び出したり、操作したりする [[API]] は、
[[HTML Standard]] と [[DOM Parsing]] の両仕様書によって定義されています。
これらも長らく明確な定義が存在していませんでしたが、 [[WHATWG]]
において2007年頃から数年かけて整備されました。

[101] [CITE@en[Ignore document.open/write after the active parser has been aborted]]
([[foolip]]著, [TIME[2019-10-16 17:25:18 +09:00]])
<https://github.com/whatwg/html/commit/ead4aa8ec576d7d330a04f7ec8508e336b895fdb>


[102] [CITE@en['''['''css-selectors-4''']''' Include whitespace in non-optional `<combinator>` · Issue #7027 · w3c/csswg-drafts · GitHub]], [TIME[2022-02-10T03:27:09.000Z]] <https://github.com/w3c/csswg-drafts/issues/7027>


[103] [[Hixie]] が形式的言語記述を避けて[[英語]]による厳密な構文・構文解析器の記述にこだわったのはこういう混乱を避けるためだったというのがわかる一件。
