有限状态机处理字符串
有限状态机
- 每一个状态都是一个机器:
- 在每一个机器里,我们可以做计算、存储、输出;
- 所有的这些机器接受的输入是一致的;
- 状态机的每一个机器本身没有状态,如果我们用函数来表示的话,它应该是纯函数(无副作用)。
- 每一个机器知道下一个状态:
- 每个机器都有确定的下一个状态(Moore)
- 每个机器根据输入决定下一个状态(Mealy)
JS中的有限状态机(Mealy)
// 每个函数是一个状态
function state(input) // 函数参数就是输入
{
//在函数中,可以自由地编写代码,处理每个状态的逻辑
return next;// 返回值作为下一个状态
}
//////以下是调用//////
while(input){
// 获取输入
state = state(input)
}
HTML解析
第一步 拆分文件
- 为了方便文件管理,先把parser单独拆到文件中
- parser接受HTML文本作为参数,返回一颗DOM树
第二步 创建状态机
https://html.spec.whatwg.org/multipage/parsing.html#data-state
第三步 解析标签
- 主要的标签:开始标签、结束标签、自封闭标签(暂时忽略属性)
第四步 创建元素
- 在状态机中,除了状态迁移,还需要加入业务逻辑
- 在标签结束状态提交标签token
第五步 处理属性
- 属性值分为单引号、双引号、无引号三种写法,因此需要较多状态进行处理
- 处理属性的方式跟标签类似
- 属性结束时,把属性加到标签Token上
第六步 构造树
- 从标签构建DOM树的基本技巧是使用栈
- 遇到开始时创建元素并入栈,遇到结束标签时出栈
- 自封闭标签可视为入栈后立刻出栈
- 任何元素的父元素是它入栈前的栈顶
CSS解析
第一步 收集CSS规则
- 遇到style标签时保存css规则
- 调用现成库css parser分析css规则
第二步 添加调用
- 创建一个元素后,立即计算CSS
- 理论上当分析一个元素时,所有CSS规则已经收集完毕
- 真实浏览器中,可能遇到写在body的style标签,需要重新CSS计算,这里忽略,所以最佳实践是所有的style尽可能写在所有元素之前,避免重新计算、重排、重绘
第三步 获取父元素序列
- 在computeCSS函数中,我们必须知道元素的所有父元素才能判断元素与规则是否匹配
- 可通过浅拷贝并转置上一步的stack,获取从自身到父元素的元素序列
- 因为首先获取的事当前元素,所以获得和计算父元素匹配的顺序是从内向外
第四步 拆分选择器
- 选择器也要从当前元素向外排列
- 复杂选择器拆成针对单个元素的选择器,用循环匹配父元素队列
第五步 计算选择器与元素匹配
- 根据选择器的类型和元素属性,计算是否与当前元素匹配
- 只实现了三种基本选择器,实际浏览器中处理复合选择器 暂不支持空格的Class选择器
第六步 生成computed属性
- 一旦选择匹配,就应用选择器到元素上,形成computedStyle
第七步 确定规则覆盖关系
- 计算并比较优先级specificity
网友评论