加載部分HTML文本(即主資源)後即可以開始解析HTML元素(對輸入字節流進行逐字掃描,識別HTML元素),最後生成DOM樹,本文只講HTML解析。html
HTML解析部分時序圖:app
其中最爲重要的過程是(1)startToken(2)nextToken(3)endToken(4)constructTreeFromHTMLToken,這裏的4步是循環執行的,當輸入字符結束時,則跳出循環。spa
HTMLTokenizer::nextToken則建立了token,而後能夠根據token建立html元素,解析的整個過程就是一個狀態機.net
HTML解析狀態機:code
初始狀態爲DataState,狀態機結束後會返回一個HTMLToken對象,不一樣的結束方式(上圖中有三個出口一、二、3)HTMLToken的類型也會不一樣。htm
class HTMLToken { enum Type { Uninitialized, DOCTYPE, StartTag, EndTag, Comment, Character, EndOfFile, }; } ;
對於1結束位置:Type=EndOfFile對象
對於2結束位置:Type=Characterblog
對於3結束位置:解析註釋-Type=Comment,解析文檔類型-Type=DOCTYPE,解析標籤(Type=StartTag/EndTag)token
子狀態機/解析註釋:資源
子狀態機/解析文檔類型:
子狀態機/解析標籤名、屬性名、屬性值
最後以一個簡單的HTML爲例,描述解析過程:
<!Doctype html>
<!--comment-->
<html>
<body>
<p>First name:</p>
<input type="text"/>
</body>
</html>
1.解析文檔類型
'<!Doctype html>',DataState狀態遷移到TagOpenState狀態
'<!Doctype html>',TagOpenState狀態遷移到MarkupDeclarationOpenState狀態
'<!Doctype html>',MarkupDeclarationOpenState狀態遷移到DOCTYPEState狀態
'<!Doctype html>',DOCTYPEState狀態遷移到BeforeDOCTYPENameState狀態
'<!Doctype html>',BeforeDOCTYPENameState狀態遷移到DOCTYPENameState狀態,並執行beginDOCTYPE
'<!Doctype html>',DOCTYPENameState狀態遷移到DOCTYPENameState狀態,並執行appendToName
'<!Doctype html>',結束
二、解析註釋
'<!--comment-->',DataState狀態遷移到TagOpenState狀態
'<!--comment-->',TagOpenState狀態遷移到MarkupDeclarationOpenState狀態
'<!--comment-->',MarkupDeclarationOpenState狀態遷移到CommentStartState狀態
'<!--comment-->',CommentStartState狀態遷移到CommentState狀態,並執行appendToComment
'<!--comment-->',CommentState狀態遷移到CommentState狀態,並執行appendToComment
'<!--comment-->',CommentState狀態遷移到CommentEndDashState狀態
'<!--comment-->',CommentEndDashState狀態遷移到CommentEndState狀態
'<!--comment-->',結束
三、解釋'html'元素
'<html>',DataState狀態遷移到TagOpenState狀態
'<html>',TagOpenState狀態遷移到TagNameState狀態,並執行beginStartTag
'<html>',TagNameState狀態遷移到TagNameState狀態,並執行appendToName
'<html>',結束
四、解釋'body'和'p'元素,同3
六、解析'p'元素內容
'First name:</p>',DataState狀態遷移到DataState狀態,並執行bufferCharacter
'First name:</p>',DataState狀態遷移到DataState狀態,並執行bufferCharacter
'First name:</p>',判斷bufferCharacter是否存在字符,存在則結束
七、解析'/p'元素
'</p>',DataState狀態遷移到TagOpenState狀態
'</p>',TagOpenState狀態遷移到EndTagOpenState狀態
'</p>',EndTagOpenState狀態遷移到TagNameState狀態,並執行beginEndTag
'</p>',結束
八、解析'input'元素
'<input type="text" />',DataState -> TagOpenState
'<input type="text" />',TagOpenState -> TagNameState,並執行beginStartTag
'<input type="text" />',TagNameState -> TagNameState,並執行appendToName
'<input type="text" />',TagNameState -> BeforeAttributeNameState
'<input type="text" />',BeforeAttributeNameState -> AttributeNameState,並執行beginAttribute
'<input type="text" />',AttributeNameState -> AttributeNameState,並執行appendToAttributeName
'<input type="text" />',AttributeNameState -> BeforeAttributeValueState
'<input type="text" />',BeforeAttributeValueState -> AttributeValueDoubleQuotedState
'<input type="text" />',BeforeAttributeValueState -> AttributeValueDoubleQuotedState,並執行appendToAttributeValue
'<input type="text" />',AttributeValueDoubleQuotedState -> AttributeValueDoubleQuotedState,並執行appendToAttributeValue
'<input type="text" />',AttributeValueDoubleQuotedState -> AfterAttributeValueQuotedState,並執行endAttribute
'<input type="text" />',AfterAttributeValueQuotedState-> BeforeAttributeNameState
'<input type="text" />',BeforeAttributeNameState-> SelfClosingStartTagState
'<input type="text" />',結束,並執行setSelfClosing
九、解析'/body'和'/html'元素,同7
參考文章: