語言的解析一般分為詞法分析(lexical analysis)和語法分析(syntax analysis)兩個階段,webkit中的html解析也不例外,本文主要討論詞法分析。
詞法分析的任務是對輸入位元組流進行逐字掃瞄,根據構詞規則識別單詞和符號,分詞。
在webkit中,有兩個類,同詞法分析密切相關,它是htmltoken和htmltokenizer類,可以簡單將htmltoken類理解為標記,htmltokenizer類理解為詞法解析器。html詞法解析的任務,就是將輸入的位元組流解析成乙個個的標記(htmltoken),然後由語法解析器進行下一步的分析。
在xml/html的文件解析中,token這個詞經常用到,我將其理解為乙個有完整語義的單元(也就是分出來的「詞」),乙個元素通常對應於3個 token,乙個是元素的起始標籤,乙個是元素的結束標籤,乙個是元素的內容,這點同dom樹是不一樣的,在dom樹上,起始標籤和結束標籤對應於乙個元素節點,而元素內容對應另乙個節點。
除了起始標籤(starttag)、結束標籤(endtag)和元素內容(character),html標籤還有doctype(文件型別),comment(注釋),uninitialized(預設型別)和endoffile(文件結束)等型別,參見htmltoken.h中的 type列舉。
htmltoken
上圖是htmltoken類的成員變數,從中我們可以看到乙個標記的組成:型別,在位元組流中的偏移,資料(m_data,不同的型別具有不同的意義),文件型別,是否自封閉(對於開始和結束標籤),屬性列表,當前屬性。
htmltokenizer就是要從位元組流解析出乙個個這樣的結構體來,他的實現是基於狀態機來做的,狀態機模型在中已經明確定義,nexttoken方法實現了該狀態機。
對有限狀態機不熟悉的童子建議先學習下absurd大大的文章系統程式設計師成長計畫-文字處理(一)狀態機(
下面以乙個簡單的html文件來復盤狀態機的幾條路線。
w3c不考慮類似和之間的回車換行(webkit裡面有做特殊處理,也就是所謂的「authoring convenience」,m_skipleadingnewlineforlisting),從前面的描述中,我們可以確認,該文件有9個 htmltoken,分別是文件型別宣告,注釋,html的起始標籤,body的起始標籤,a的起始標籤,a的元素內容,a的介紹標籤,body的結束標籤,html的結束標籤。
起始狀態為datastate。
1)doctype
datastate:,碰到』」』,進入
afterdoctypepublicidentifierstate 狀態。(htmltoken的m_publicidentifier確定)
afterdoctypepublicidentifierstate: ,碰到』>』,進入datastate狀態,完成文件型別
的解析2)comment
datastate:,碰到』<』,進入tagopenstate
tagopenstate:, 碰到』!』,進入markupdeclarationopenstate狀態
markupdeclarationopenstate:,碰到』-』,匹配doctype和--字數都不夠,保持現狀
markupdeclarationopenstate:,匹配--,進入commentstartstate狀態(htmltoken的type為comment)
commentstartstate: ,碰到』c』,進入commentstate
commentstate:,碰到』-『,進入commentenddashstate狀態(htmltoken的m_data為comment)
commentenddashstate: ,碰到』-『,進入commentendstate狀態
commentendstate:,碰到』>『,進入datastate狀態,完成解析。
3)起始標籤a
datastate:,碰到』<』,進入tagopenstate狀態
tagopenstate:,碰到』a』,進入tagnamestate狀態(htmltoken的type為starttag)
tagnamestate:,碰到空格,進入beforeattributenamestate狀態(htmltoken的m_data為a)
beforeattributenamestate:,碰到『h』,進入attributenamestate狀態
attributenamestate:,碰到『=』,進入beforeattributevaluestate狀態(htmltoken
屬性列表中加入乙個屬性,屬性名為href)
beforeattributevaluestate: ,碰到『「』,進入attributevaluedoublequotedstate狀態
attributevaluedoublequotedstate:,碰到『w』,保持狀態,提取屬性值
attributevaluedoublequotedstate:,碰到『「』,進入afterattributevaluequotedstate
(htmltoken當前屬性的值為w3c.org).
afterattributevaluequotedstate: ,碰到『>』,進入datastate,完成解析。
html,body起始標籤類似a起始標籤,但沒有屬性解析
4)a元素
datastate:w3c,碰到』w』,維持原狀態,提取元素內容(htmltoken的type為character)。
datastate:w3c,碰到』<』,完成解析,不consume 』<』。(htmltoken的m_data為w3c)。
5)a結束標籤
datastate:w3c,碰到』<』,進入tagopenstate。
tagopenstate:w3c,碰到』/』,進入到endtagopenstate。(htmltoken的type為endtag)。
endtagopenstate:w3c,碰到』a』,進入到tagnamestate。
tagnamestate:w3c,碰到』>』,進入到datastate,完成解析。
通過以上的覆盤,乙個標記的token過程清晰呈現在眼前,基本上就是實現這一章的乙個過程,html的規範是相當寬鬆的,所以詞法解析要考慮到的問題很多,html5 specfication在這方面為實現者做了絕大部分工作。
另外,html的語法解析會影響詞法解析,比如語法解析在解析到head裡面title的起始標籤後,會將htmltokenizer解析器的狀態設定為rcdatastate。
WebKit中的智慧型指標
前幾天看了下webkit裡的幾種常用的智慧型指標 小結一下 refcounted 提供引用計數器功能。使用時繼承之 class foo public refcounted 為了更為方便安全地使用引用計數功能,webkit提供了refptr。threadsafeshared 多執行緒版本的引用計數 r...
WebKit中的智慧型指標
智慧型指標的實現原理 智慧型指示通常是通過引用計數器來自動維護物件的引用情況。引用計數跟蹤該類有多少個物件共享同一指標。每次通過adoptref 函式建立智慧型指標時將引用計數置為 1 當物件被另乙個智慧型指標引用時增加與之相應的引用計數 對智慧型指標進行賦值時,賦值操作符減少左運算元所指物件的引用...
popstate事件在webkit中的詭異行為
雖然官方的文件中對popstate的描述也沒有細節上的描述,不過以我的邏輯來判斷,這貨是就webkit的bug。html5的這一套historyapi和傳統的history不同,或者說這一套historyapi是 session history entries 雖然官方的文件並沒有強調它與傳統的hi...