热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【手写简易浏览器】htmlparser篇

思路分析实现htmlparser主要分为词法分析和语法分析两步。词法分析词法分析需要把每一种类型的token识别出来,具体的类型有:开始标签,如<div>结束标签,如<div>注释标签,如<!--comment-->do

思路分析

实现 html parser 主要分为词法分析和语法分析两步。

词法分析

词法分析需要把每一种类型的 token 识别出来,具体的类型有:

  • 开始标签,如
  • 结束标签,如
  • 注释标签,如
  • doctype 标签,如
  • text,如 aaa
  • 这是最外层的 token,开始标签内部还要分出属性,如 这种。

    也就是有这几种情况:

    【手写简易浏览器】html parser 篇

     

     

    第一层判断是否包含 <,如果不包含则是 text,如果包含则再判断是哪一种,如果是开始标签,还要对其内容再取属性,直到遇到 > 就重新判断。

    语法分析

    语法分析就是对上面分出的 token 进行组装,生成 ast。

    html 的 ast 的组装主要是考虑父子关系,记录当前的 parent,然后 text、children 都设置到当前 parent 上。

    【手写简易浏览器】html parser 篇

     

     

    我们来用代码实现一下:

    代码实现

    词法分析

    首先,我们要把 startTag、endTag、comment、docType 还有 attribute 的正则表达式写出来:

    正则

    const endTagReg = /^<\/([a-zA-Z0-9\-]+)>/;
     
    const commentReg = /^)]*\-\->/;
     
    const docTypeReg = /^]+>/;
     
    const attributeReg = /^(?:[ ]+([a-zA-Z0-9\-]+=[^>]+))/;
     
    const startTagReg = /^<([a-zA-Z0-9\-]+)(?:([ ]+[a-zA-Z0-9\-]+=[^> ]+))*>/;
     

    分词

    之后,我们就可以基于这些正则来分词,第一层处理 <和 text:

    function parse(html, options) {
        function advance(num) {
            html = html.slice(num);
        }
    
        while(html){
            if(html.startsWith('<')) {
                //...
            } else {
                let textEndIndex = html.indexOf('<');
                options.onText({
                    type: 'text',
                    value: html.slice(0, textEndIndex)
                });
                textEndIndex = textEndIndex === -1 ? html.length: textEndIndex;
                advance(textEndIndex);
            }
        }
    }
     

    第二层处理

    box1 box1 box1

    box2 box2 box2

    `); console.log(JSON.stringify(domTree, null, 4));
     

    成功生成了正确的 AST。

    【手写简易浏览器】html parser 篇

     

     

    总结

    这篇是简易浏览器中 html parser 的实现,少了自闭合标签的处理,就是差一个 if else,后面会补上。

    我们分析了思路并进行了实现:通过正则来进行 token 的拆分,把拆出的 token 通过回调函数暴露出去,之后进行 AST 的组装,需要记录当前的 parent,来生成父子关系正确的 AST。

    html parser 其实也是淘系前端的多年不变的面试题之一,而且 vue template compiler 还有 jsx 的 parser 也会用到类似的思路。还是有必要掌握的。希望本文能帮大家理清思路。

    代码在 github:https://github.com/QuarkGluonPlasma/tiny-browser

    转自https://mp.weixin.qq.com/s/ku6yNZqIKH9wBSGbUdhW0A


    推荐阅读
    author-avatar
    假爱多慌乱
    这个家伙很懒,什么也没留下!
    Tags | 热门标签
    RankList | 热门文章
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有