在浏览器的背后(二) —— HTML语言的语法解析
当你看到这篇文章意味着我辜负了@教主的殷切期望周末木有去约会,以及苏老师@我思故我在北京鼓楼的落井下石成功了……
本文demo powered by 已经结婚的@老赵的不再维护的wind.js
物是人非啊……
说回正经事,在上一篇文章中,我们取得了初步成果,毫无意义的字符变成了有意义的token。
接下来我们要把这些简单的词变成DOM树,这个过程我们是使用栈来实现的,任何语言几乎都有栈,为了给大家跑着玩我们还是用JS来实现吧,JS中的栈只要用数组就好了:
function HTMLSyntaticalParser(){
    var stack = [new HTMLDocument];
    this.receiveInput = function(token) {
        //TODO
    }
    this.getOutput = function(){
        return stack[0];
    }
}
为了构建DOM树,我们需要一个Node类,接下来我们所有的节点都会是这个Node类的实例。在完全符合标准的浏览器中,不一样的HTML节点对应了不同的Node的子类,我们为了简化,就不完整实现这个继承体系了。我们仅仅把Node分为Element和Text(如果是基于类的OOP的话,我们需要抽象工厂来创建对象。)
function Element(){
    this.childNodes = [];
}
function Text(value){
    this.value = value || "";
}
前面我们的token中,以下两个是需要成对匹配的:
- tag start
 - tag end
 
于是我们的做法是遇到tag start就入栈,遇到tag end就出栈,并且校验一下是否匹配。
对于Text节点,我们则需要把相邻的Text节点合并起来,我们的做法是当字符token入栈时检查栈顶是否是Text节点,如果是的话就合并Text节点
同样我们来看看直观的解析过程:
<html maaa=a >
    <head>
        <title>cool</title>
    </head>
    <body>
        <img src="a" />
    </body>
</html>
 parse
当我们的源代码完全遵循xhtml时,这非常简单问题,然而HTML具有很强的容错能力,奥妙在于当tag end跟栈顶的start tag不匹配的时候如何处理。
于是有一个极其复杂的规则来的,幸好w3c又一次很贴心地把全部规则都整理的很好,我们只要翻译成对应的伪代码就好了:
http://www.w3.org/html/wg/drafts/html/master/syntax.html#tree-construction
略微干净的代码可以在这个gist找到:
https://gist.github.com/wintercn/5618683#file-htmlsyntaticalparser-js
在浏览器的背后(二) —— HTML语言的语法解析的更多相关文章
- Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器
		
Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...
 - MVC框架入门准备(二) - 语言包类与工厂模式
		
语言包类: 相关配置项 LANG_FOLDER : 语言包目录名,默认为Lang LANG_AUTO : 自动识别语言,默认为true DEFAULT_LANG : 默认语言,默认为zh-cn方法 取 ...
 - 火狐浏览器如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?
		
一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 火狐浏览器如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 二次验证码小程序于谷歌身份验证器APP的优势 1.无需下载 ...
 - 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战
		
手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...
 - 一、JavaScript概述 	二、JavaScript的语法 	三、JavaScript的内置对象
		
一.JavaScript的概述###<1>JavaScript的概念 又称ECMAScript,和java没有任何关系 嵌入在HTML元素中的 被浏览器解释运行的 一种脚本语言. ###& ...
 - JVM(二):Java中的语法糖
		
JVM(二):Java中的语法糖 上文讲到在语义分析中会对Java中的语法糖进行解糖操作,因此本文就主要讲述一下Java中有哪些语法糖,每个语法糖在解糖过后的原始代码,以及这些语法糖背后的逻辑. 语法 ...
 - Java语言基本语法
		
Java语言基本语法 一.标识符和关键字 标识符 在java语言中,用来标志类名.对象名.变量名.方法名.类型名.数组名.包名的有效字符序列,称为“标识符”: 标识符由字母.数字.下划线.美元符号组成 ...
 - C语言文件操作解析(五)之EOF解析(转载)
		
C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ...
 - 【转】C语言文件操作解析(三)
		
原文网址:http://www.cnblogs.com/dolphin0520/archive/2011/10/07/2200454.html C语言文件操作解析(三) 在前面已经讨论了文件打开操作, ...
 
随机推荐
- adv
			
1. 对产品质量的认知理念,不仅是是确保没问题,而是通过自身与团队的价值提升产品的质量.潜在问题,竞类产品用户体验,bug产生分析图,流程控制 2. 责任心特质,正能量,热情激情,并且能感染团队成员和 ...
 - iOS之使用模拟器报错:resource fork, Finder information, or similar detritus not allowed
			
很奇怪的问题,使用真机测试没有问题.但使用模拟器测试的时候就会报这样的错误,错误类型为:Code Sign Error 错误提示是这样:resource fork, Finder informatio ...
 - Arduino下LCD1602综合探究(下)——如何减少1602的连线,LiquidCrystal库,LiquidCrystal库中bug的解决方法
			
一.前言: 上文中,笔者系统的阐述了1602的两种驱动方式,并简单的提到了Arduino的LiquidCrystal库.本文紧接上文,对以下两个问题进行更加深入的探讨:如何能够使1602对Arduin ...
 - R内存管理与垃圾清理
			
1.内存查看 memory.limit():查看内存大小 memory.limit(n):申请内存大小 memory.size(NA):查看内存大小 memory.size(T):查看已分配的内存 m ...
 - css 大话盒子模型
			
什么是盒子模型? CSS中, Box Model叫盒子模型(或框模型),Box Model规定了元素框处理元素内容(element content).内边距(padding).边框(border) 和 ...
 - iDB是如何运转的 一
			
郑昀 创建于2015/12/2 最后更新于2015/12/4 关键词:数据库,MySQL,自动化运维,DDL,DML,SQL审核,备份,回滚,Inception,osc 提纲: 普通DBA和文艺DBA ...
 - jquery基本
			
对于jquery属性的访问: //对于bool值的属性,元素标签中如果写了这个属性,attr能够获取到,如果没有写,就获取不到. 如:<input type="checkbox&quo ...
 - FTP命令 - Size的问题
			
今天发现一个服务从某一个外接系统(Linux)FTP取到的文件大小和下载后的文件大小总是不一致. 开始以为是程序那里出错了.但是找来找去发现不了原因.后来用FTP工具上去执行SIZE命令,终于发现返回 ...
 - dedecms功能性函数封装(XSS过滤、编码、浏览器XSS hack、字符操作函数)
			
dedecms虽然有诸多漏洞,但不可否认确实是一个很不错的内容管理系统(cms),其他也不乏很多功能实用性的函数,以下就部分列举,持续更新,不作过多说明.使用时需部分修改,你懂的 1.XSS过滤. f ...
 - Java 用LinkdeList实现52张扑克牌
			
用LinkdeList实现52张扑克牌(不含大小王)的洗牌功能.提示:花色 ,和数字分别用数组存储. import java.util.LinkedList; import java.util.Ran ...