HTML5解析由两部分组成:分词与构建树。
分词属于语法分析部分,它把输入解析成符号序列。在HTML中符号就是开始标签,结束标签,属性名称和属性值。
分词算法
分词算法可以用状态机来描述。每一个状态从输入流中消费一个或者多个字符,并根据它们更新下一状态。
决策受当前符号状态和树的构建状态影响。这意味着同样的字符可能会产生不同的结果,取决于当前的状态。
<html>
<body>
Hello world
</body>
</html>
初始状态是Data state
,当遇到<
时状态改为Tag open state
。吃掉a-z
字符组成的符号后产生了Start tag token
,状态变更为Tag name state
。我们一直保持此状态,直到遇到>
。每个字符都被追加到新的符号名上。在我们的例子中,解出的符号就是html
。
当碰到>
时,当前符号完成,状态改回Data state
。<body>
标签将会以同样的方式处理。现在html
与body
标签都完成了,我们回到Data state
状态。吃掉H
(Hello world
第一个字母)时会产生一个字符符号,直到碰到</body>
的<
符号,我们就完成了一个字符符号Hello world
。
现在我们回到Tag open state
状态。吃掉下一个输入/
时会产生一个end tag token
并变更为Tag name state
状态。同样,此状态保持到我们碰到>
时。这时新标签符号完成,我们又回到Data state
。同样</html>
也会被这样处理。
树的构建算法
当分词解析器被创建时,文档对象也会被创建。
在树的创建过程中DOM树的根节点(Document)将被修改,元素被添加到上面去。每个分词器完成的节点都会被树构建器处理。
除了把元素添加到DOM树外,它还会被添加到一个开放元素堆栈。这个堆栈用于纠正嵌套错误和标签未关闭错误。
<html>
<body>
Hello world
</body>
</html>
树的构建过程中,输入就是分词过程中得到的符号序列。第一个模式叫initial mode
。接收html
符号后会变成before html
模式并重新处理此模式中的符号。这会创建一个HTMLHtmlElement
元素并追加到根文档节点。
然后状态改变为before head
。我们收到body
时,会隐式创建一个HTMLHeadElement
,尽管我们没有这个标签,它也会被创建并添加到树中。
现在我们进入in head
模式,然后是after head
,Body
会被重新处理,创建HTMLBodyElement
元素并插入,然后进入in body
模式。
字符符号Hello world
收到后会创建一个Text
节点,所有字符都被一一追加到上面。
收到body
结束标签后进入after body
模式,收到html
结束标签后进入after after body
模式。所有符号处理完后将终止解析。