/
622.txt
202 lines (149 loc) · 13.4 KB
/
622.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
[1] 本項では [[HTML]] と [[XML]] の[[構文解析器]]の基礎的な概念を扱います。専ら一方のみに関係する事項は、
[[HTML構文解析器]]と[[XML構文解析器]]の項をご覧ください。
* 構文解析器と文書
[10] [[構文解析器]]は[[文書]]に関連付けられています。
[11] [[文書]]から見て動作中の[[構文解析器]]のことを(あれば)[[活性構文解析器]]といいます。
[12] ある[[構文解析器]]の[[インスタンス]]が扱う[[文書]]は1つだけです。
;; ただし [CODE(HTMLe)@en[[[template]]]] [[要素]]があるときは、[[雛形内容]]の[[文書]]も関係してきます。
また、[[スクリプト]]によって挿入先の[[要素]]が別の[[文書]]に移動された時は、その[[文書]]に新しい[[節点]]も挿入されることになります。
[13] [[文書]]に対してそれを扱う[[構文解析器]]は1つとは限りません。例えばその[[文書]]自体を作った[[構文解析器]]と
[CODE(DOMa)@en[[[innerHTML]]]] の[[構文解析器]]は別物です。また [CODE(JS)@en[[[document.open]]]]
では新しい[[構文解析器]]が作られます。
* 入力
[24] [[構文解析]]の対象となる入力は、[[入力バイトストリーム]] ([[バイト列]])
または[[入力ストリーム]] ([[文字列]]) として[[構文解析器]]に与えられます。
[FIG(list)[
- [36] [[navigate]] 中は、 [[fetch]] が受信した[[バイト列]]毎にキューに入れる[[タスク]]により、
[[入力バイトストリーム]]に[[バイト列]]が追加されていき、[[構文解析]]が行われます [SRC[>>32]]。
[[fetch]] がキューに入れた末尾を表す[[タスク]]により、 [[EOF]] が[[入力バイトストリーム]]に挿入されます [SRC[>>32]]。
- [37] [CODE(JS)@en[[[document.write]]]] や [CODE(JS)@en[[[document.writeln]]]] は、
[[入力ストリーム]]の[[挿入点]]前に[[文字列]]を追加していき、[[構文解析]]を行います [SRC[>>33]]。
[[挿入点]]は[[入力ストリーム]]の末尾とは限りません。
- [38] [CODE(JS)@en[[[document.close]]]] は、[[入力ストリーム]]に [[EOF]]
を挿入します [SRC[>>34]]。
- [39] [CODE(DOMm)@en[[[parseFromString]]]], [CODE(DOMa)@en[[[innerHTML]]]],
[CODE(DOMa)@en[[[innerHTML]]]], [CODE(DOMm)@en[[[insertAdjacentHTML]]]],
[CODE(DOMm)@en[[[insertContextualFragment]]]] は[[文字列]]を[[入力ストリーム]]として一度に[[構文解析]]を行います
[SRC[>>35]]。
- [44] [CODE(DOMa)@en[[[responseXML]]]] は[[応答]]に含まれる[[バイト列]]を[[入力バイトストリーム]]として一度に[[構文解析]]を行います [SRC[>>43]]。
- [47] [CODE(JS)@en[[[document.load]]]] は[[応答]]に含まれる[[バイト列]]を[[入力バイトストリーム]]として一度に[[構文解析]]を行います [SRC[>>46]]。
- [45] [CODE(XML)@en[[[xml-stylesheet]]]] によって指定された [[XSLT]]
[[文書]]については仕様書がなく不明です。
[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]] 版) <http://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] 入力がバイト列の場合は、[[バイト]]の解釈に用いる[[文字符号化]]も入力として与えられる場合があります。
これには、他の情報により上書きされる可能性のある[[文字符号化]]の指定と、
必ずそれにより[[復号]]される[[文字符号化]]の指定の2種類があります。
[26] [[構文解析器]]の動作には[[ロケール]]の指定も影響します。
[[入力バイトストリーム]]の[[文字符号化]]の決定や、
[CODE(HTMLe)@en[[[isindex]]]] [[開始タグ]]の解釈に作用します。
[30] [[HTML構文解析器]]と[[XML構文解析器]]では、[[構文解析]]の各段階の動作に様々な違いが生じます。
[27] [[HTML構文解析器]]の動作は、[[スクリプト有効]]か否かで変化します。
[29] [CODE(DOMa)@en[[[innerHTML]]]] など素片構文解析では、
[[文脈要素]]によって[[構文解析]]の開始の時点の状態やその後の動作が左右されます。
* 出力
[28] [[構文解析]]の結果は、開始時に指定された[[親]]となる[[節点]]の[[子孫]]という形で現れます。
また、[[奇癖モード]]か否かなど、内部状態 ([[IDL属性]]など) を変化させることもあります。
[31] また、[[構文解析器]]は、1つ以上の[[構文解析エラー]]を発見すると、
これを報告することがあります。仕様上義務付けられてはいませんが、
どの[[Webブラウザー]]も [[Console]] に[[構文解析エラー]]を報告するようです。
;; [[スクリプト]]などで[[著者]]がこれを受け取ることはできないようです。
* 一時停止
[2] [[構文解析器]]は [[HTML]] の [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構文解析器]]は[[外部実体]]の展開を行いません。
* 停止
[40] [[構文解析]]は、正常終了 (>>6) か中断 (>>4) のいずれかによって終了します。
;; [41] [[構文解析]]は、終了するとは限りません。[[鯖]]から無限の[[バイト列]]が送信され続けている場合は、
[[構文解析]]も無限に続きます。
** 正常終了
[6] [[構文解析]]の処理がすべて終了すると、 [[stop parsing]] が実行されます。
** 中断
[4] [[構文解析器]]は [[abort a parser]] が呼び出されると[[入力ストリーム]]や[[開いている要素のスタック]]を破棄します。
これによって未処理の入力は捨てられ、それ以降の[[字句化]]が行われません。
[5] abort は、 [CODE(JS)@en[[[window.close]]]] や [CODE(JS)@en[[[document.open]]]] が呼ばれた時や、
[[navigate]] されて現在の[[文書]]が破棄される場合などに呼ばれます。
* 再帰的実行
[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]] しなおすというかなり強引な形で行われます。[[スクリプト]]により[[著者]]に、
[[レンダリング]]により[[利用者]]に観測可能なこともあります。
* DOM 操作
[21] [[構文解析器]]による[[DOM木]]の操作は、基本的には [[DOM]] [[API]]
によって行われる操作と同じものですが、一部は特別な動作が定義されていることもあります。
[22] [[構文解析器]]による [[DOM]] 操作の動作については、次の各項を参照してください。
[FIG(list)[
- [[要素の作成]]
- [[開いている要素のスタック]]
]FIG]
[23] [[節点]]の作成や[[節点]]の内部状態 ([[IDL属性]]の値) の設定
([CODE(HTMLm)@en[[[createElementNS]]]] や [CODE(DOMa)@en[[[compatMode]]]]
など) に加えて、次のような[[メソッド]]に相当する操作が行われます。
[FIG(list)[
- [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]
* 歴史
[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年頃から数年かけて整備されました。