从输入流转换document出错_从"算法"角度回答—输入URL后页面呈现发生了什么?...

老生常谈的问题,可以另辟蹊径来回答!本文不讲解 URL 输入后发生的网络部分,只从算法角度讲解拿到页面后的解析部分,主要分为以下几个步骤:

  • 构建 DOM
  • 样式计算
  • 生成布局树(Layout Tree)

构建 DOM 树

由于浏览器无法直接理解HTML字符串,因此将这一系列的字节流转换为一种有意义并且方便操作的数据结构,这种数据结构就是DOM树DOM树本质上是一个以document为根节点的多叉树。

那通过什么样的方式来进行解析呢?

HTML文法的本质

首先,我们应该清楚把握一点: HTML 的文法并不是上下文无关文法

这里,有必要讨论一下什么是上下文无关文法

在计算机科学的编译原理学科中,有非常明确的定义:

若一个形式文法G = (N, Σ, P, S) 的产生式规则都取如下的形式:V->w,则叫上下文无关语法。其中 V∈N ,w∈(N∪Σ)* 。

其中把 G = (N, Σ, P, S) 中各个参量的意义解释一下:

  1. N 是非终结符(顾名思义,就是说最后一个符号不是它, 下面同理)集合。
  2. Σ 是终结符集合。
  3. P 是开始符,它必须属于 N ,也就是非终结符。
  4. S 就是不同的产生式的集合。如 S -> aSb 等等。

通俗一点讲,上下文无关的文法就是说这个文法中所有产生式的左边都是一个非终结符。

看到这里,如果还有一点懵圈,我举个例子你就明白了。

比如:

A -> B

这个文法中,每个产生式左边都会有一个非终结符,这就是上下文无关的文法。在这种情况下,xBy一定是可以规约出xAy的。

我们下面看看看一个反例:

aA -> BAa -> B

这种情况就是不是上下文无关的文法,当遇到B的时候,我们不知道到底能不能规约出A,取决于左边或者右边是否有a存在,也就是说和上下文有关。

关于它为什么是非上下文无关文法,首先需要让大家注意的是,规范的 HTML 语法,是符合上下文无关文法的,能够体现它非上下文无关的是不标准的语法。在此我仅举一个反例即可证明。

比如解析器扫描到form标签的时候,上下文无关文法的处理方式是直接创建对应 form 的 DOM 对象,而真实的 HTML5 场景中却不是这样,解析器会查看 form 的上下文,如果这个 form 标签的父标签也是 form, 那么直接跳过当前的 form 标签,否则才创建 DOM 对象。

常规的编程语言都是上下文无关的,而HTML却相反,也正是它非上下文无关的特性,决定了HTML Parser并不能使用常规编程语言的解析器来完成,需要另辟蹊径。

解析算法

HTML5 规范详细地介绍了解析算法。这个算法分为两个阶段:

  1. 标记化。
  2. 建树。

对应的两个过程就是词法分析语法分析

标记化算法

这个算法输入为HTML文本,输出为HTML标记,也成为标记生成器。其中运用有限自动状态机来完成。即在当当前状态下,接收一个或多个字符,就会更新到下一个状态。

      Hello sanyuan  

通过一个简单的例子来演示一下标记化的过程。

遇到<, 状态为标记打开

接收[a-z]的字符,会进入标记名称状态

这个状态一直保持,直到遇到>,表示标记名称记录完成,这时候变为数据状态

接下来遇到body标签做同样的处理。

这个时候htmlbody的标记都记录好了。

现在来到

中的>,进入 数据状态,之后保持这样状态接收后面的字符 hello sanyuan

接着接收 中的<,回到标记打开, 接收下一个/后,这时候会创建一个end tag的token。

随后进入标记名称状态, 遇到>回到数据状态

接着以同样的样式处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值