Formal definitions for vocabulary and syntax
詞匯通常是使用正則表達(dá)式來表示的笑窜。舉例來說纹磺,我們上述的語言可以被定義為如下:
INTEGER :0|[1-9][0-9]*
PLUS : +
MINUS: -</pre>
可以看出夭谤,數(shù)字是用正則來表示的攀甚。
句法通常是通過一種叫 BNF 的格式定義的梦皮,我們上述語言可以被定義為如下:
expression := term operation term
operation := PLUS | MINUS
term := INTEGER | expression</pre>
我們可以認(rèn)為如果一個(gè)語言的語法是上下文無關(guān)語法丽已,那么它總是可以被常規(guī)解釋器解釋的。上下文無關(guān)語法的一種直接定義就是可以完全由BNF表示厢绝。
Types of parsers - 解析器的類型
有兩種比較常見的解析器類型: 自頂向下分析和自底向上分析契沫。一種簡單的解釋是自頂向下分析是
根據(jù)形式語法規(guī)則,在語法分析樹
的自頂向下展開中搜索輸入符號串可能的最左推導(dǎo)昔汉。單詞按從左到右的順序依次使用懈万。自底向上分析是
語法分析器從現(xiàn)有的輸入符號串開始,嘗試將其根據(jù)給定的形式語法規(guī)則進(jìn)行改寫靶病,最終改寫為語法的起始符號会通。
自底向上分析將會(huì)掃描所有輸入的項(xiàng)一直到某條規(guī)則可以符合,然后用規(guī)則替換匹配的輸入娄周。這項(xiàng)工程會(huì)一直持續(xù)到輸入的內(nèi)容結(jié)束涕侈。已經(jīng)符合了規(guī)則的部分會(huì)放入解釋器堆棧中。
Stack | Input |
---|---|
2 + 3 - 1 | |
term | + 3 - 1 |
term operation | 3 - 1 |
expression | - 1 |
expression operation | 1 |
expression |
這種自下而上的解析器稱為移位減少解析器煤辨,因?yàn)檩斎胂蛴乙苿?dòng)(想想一個(gè)指針首先指向輸入開始并向右移動(dòng))并逐漸轉(zhuǎn)移到對應(yīng)語法規(guī)則的堆棧中裳涛。
Generating parsers automatically - 自動(dòng)生成解釋器
有一些工具可以幫助你生成解釋器,他們被叫做parser generators众辨。你將語言語法輸入進(jìn)去端三,它會(huì)自動(dòng)幫你生成一個(gè)可以使用的解釋器。手工制作解釋一需要非常專業(yè)的知識所以并不是一件簡單的工作鹃彻,這樣自動(dòng)生成的解釋器就非常有用了郊闯。
Webkit 使用兩個(gè)非常有名的自動(dòng)生成工具。詞法解析使用了 Flex, 解釋器的生成使用了Bison....
HTML Parser - HTML 解釋器
HTML解釋器的工作是將HTML文件編譯進(jìn)解析樹蛛株。
The HTML grammar definition - HTML的語法定義
W3C 阻止制定了HTML的詞法和句法規(guī)范虚婿。
a context free grammar - 不是一種上下文無關(guān)語法
我們曾經(jīng)討論過大多數(shù)的時(shí)候我們都可以使用BNF 的格式定義句法,但很不幸泳挥,這并不適用于 HTML 的解析然痊。HTML不能簡單的被上下文無關(guān)語法解析器解析。正式的HTML的定義格式是DTD屉符。
在世界上第一個(gè)網(wǎng)站出現(xiàn)的時(shí)候看起來很怪異,html文件更像是xml文件而xml文件有許許多多的解析器东涡,XML 有一種比較接近HTML的變體XHTML凸舵,那么他們到底有什么區(qū)別呢掀潮?
那就是HTML更不嚴(yán)格邑商。 有時(shí)候你漏掉了起始標(biāo)簽恶迈,有時(shí)候是結(jié)束標(biāo)簽但最后并沒什么關(guān)系奈附。 這對于苛刻的XML是一種無聲的反抗佑颇。
很顯然,這一點(diǎn)的不同造成了很大的影響移袍。一方面開發(fā)者們更樂意使用HTML,另一方面也讓HTML的解釋器制作起來更加困難奄妨。也就是說直焙,HTML不能簡單的被轉(zhuǎn)譯厨喂。
HTML DTD
HTML是一種DTD格式的定義方法颁褂,這種格式曾經(jīng)是用于定義SGML類型的語言的。這種格式對于所有可使用的元素的屬性和層級關(guān)系進(jìn)行定義。我們已經(jīng)說過歼冰,HTML DTD不是一種上下文無關(guān)的語法靡狞。
DTD 有一些變體。過去隔嫡,嚴(yán)格模式下要求完全符合規(guī)范而其他模式對于標(biāo)簽的支持依賴于瀏覽器的解析甸怕,目的是向下兼容。
W3C對DTD的規(guī)范定義:http://www.w3.org/TR/html4/strict.dtd
DOM
HTML的解析樹是一個(gè)DOM元素和屬性節(jié)點(diǎn)樹腮恩。DOM 是 Document Object Model 的縮寫梢杭。他是HTML的解析也是HTML對外的接口,比如對于JS的接口秸滴。這棵樹的跟節(jié)點(diǎn)是 Document 對象武契。
DOM和HTML幾乎有一一對應(yīng)關(guān)系,比如:
<html>
<body>
<p>
Hello World
</p>
<div> <img src="example.png"/></div>
</body>
</html>
將會(huì)被解析為:
和HTML一樣荡含,DOM的規(guī)范也是由W3C規(guī)定的咒唆。是一個(gè)操作DOM的通用規(guī)范。W3C對此有一個(gè)詳細(xì)文檔释液,它的地址是:
http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.html
當(dāng)我說一顆樹包括DOM節(jié)點(diǎn)的時(shí)候钧排,我指的是這棵樹是由有DOM接口的元素組成的。瀏覽器內(nèi)部有他們自己的實(shí)踐均澳。
The parsing algorithm - 解析的算法
之前我們說過恨溜,HTML的解析不能簡單的使用自頂向下或自底向上的方法解析,原因有以下:
- 是一種不嚴(yán)格的語言找前。
- 瀏覽器對于無效HTML的支持糟袁。
- 解析過程是來回折返的。大多數(shù)語言在解析的時(shí)候已經(jīng)不會(huì)改變代碼了躺盛,但是HTML當(dāng)遇到Script標(biāo)簽并存在document.write的時(shí)候還是可能添加額外的信息项戴,所以解析過程實(shí)際上也會(huì)改變源代碼。
由于不能使用常用的方式解析HTML槽惫,瀏覽器粗昂早了新的解釋器解析HTML周叮。
解析算法由HTML5規(guī)范詳細(xì)描述,這種算法由兩個(gè)階段組成: 符號化和形成解析樹界斜。
符號化是詞法解析仿耽,將輸入解析成符號。HTML的符號主要是由起始標(biāo)簽各薇、結(jié)束標(biāo)簽项贺、屬性名和屬性值組成君躺。
詞法解析器解析符號,然后將符號交給構(gòu)建解析樹的構(gòu)建起开缎,然后解析剩下的符號一直到所有的輸入結(jié)束棕叫。
Figure 6: HTML parsing flow (taken from HTML5 spec)