zoukankan      html  css  js  c++  java
  • sizzle分析记录:词法分析器(tokenize)

    词法分析器(tokenize)?

    词法分析器又称扫描器。词法分析是指将我们编写的文本代码流解析为一个一个的记号,分析得到的记号以供后续语法分析使用。

    sizzle引入了tokenize这个概念,意义?

    jQuery的选择器,实现了css1-css3的API,但是ECMAScript低版本的API中本身没有针对这种CSS的处理API,在IE8以上就引入了querySelectorAll

    各种浏览器实现还有差异,这里不是主题,我们看如果是低版本的接口要如果处理复杂的CSS选择器

    首先面临的就是要对复杂的选择器进行分解

    例如:

    div > div.Aaron p span.red

    只能针对每个版本的浏览器的支持力度去匹配各自的选择

    所以此时会引入一个词法分析器(tokenize)用来把用户复杂的匹配选择,分解成各自的单元,可以提供给后面对应的接口处理


    选择器总的来说分四大类:

    并联就是合并分组,用逗号分隔

    简单的选择器,ID,TAG,CLASS,ATTR,*

    关系选择器:> ,+ , ~, 空格

    伪类:动作伪类,目标伪类,语言伪类,状态伪类,结构伪类,取反伪类

    Sizzle的Token格式如下 :

    {
       value:'匹配到的字符串', 
       type:'对应的Token类型',
       matches:'正则匹配到的一个结构'
    
    }

    tokenize需要解析的几种情况:

    情况一:多重选择器分组

    soFar :$("div, span, p.myClass" )

    在出现逗号分隔符的时候,就说明选择所有指定的选择器的组合结果,所以需要分割成各自的处理模块

    这种事情当然交给正则来干是最合适的

    常规的思路先是通过split(,)先把选择器劈成三部分,然后依次处理各自的模块

    jQuery对于过滤正则都有一个特点,就是都是元字符^开头,开限制匹配的初始,所以tokenize也是从左边开始一层一层的剥离

    rcomma.exec( soFar )) 
    
    var whitespace = "[\x20\t\r\n\f]";
    var rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" )

    匹配第一个出现的非显示字符

    换句话匹配

    , span, p.myClass

    然后在划分容器

    if ( !matched || (match = rcomma.exec( soFar )) ) {
        if ( match ) {
            // Don't consume trailing commas as valid
            soFar = soFar.slice( match[0].length ) || soFar;
        }
        groups.push( (tokens = []) );
    }

    其结果就是:(结构不合理,先理解这个意思)

    groups:[
          tokens :{div, span},
          tokens :{p.myClass}
    ]

    情况二:关系处理器分组

    在层级关系中有几种特殊的划分 Token : >, +, 空格, ~ 用来表明父与子,兄弟,祖辈子孙之间的层级关系

    $( "ul.topnav > li" )

    从 > 划分

    rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

    可以是>+~或者空白

    这个分组是为了之后的关系选择确定

    if ( (match = rcombinators.exec( soFar )) ) {
        matched = match.shift();
        tokens.push({
            value: matched,
            // Cast descendant combinators to space
            type: match[0].replace( rtrim, " " )
        });
        soFar = soFar.slice( matched.length );
    }

    剩余几种Token :

    Expr.filter :TAG, ID, CLASS, ATTR, CHILD, PSEUDO

    通过一系列的正则抽出表达式中的内容

    ID:

    ///^#((?:\.|[w-] | [^x00-xa0] ) +)/
    var characterEncoding = "(?:\\.|[\w-]|[^\x00-\xa0])+";
    var ID = new RegExp("^#(" + characterEncoding + ")")
    console.log(ID.exec("#div > li"))  //["#div", "div", index: 0, input: "#div > li"]

    TAG:

    var TAG =  new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" );
    console.log(TAG.exec("li > sadf.da dsf"))  //["#div", "div", index: 0, input: "#div > li"]

    CLASS:

    var Class = new RegExp( "^\.(" + characterEncoding + ")" );
    console.log(Class.exec(".li > sadf.da dsf"))

    ATTR:

    属性选择器有点复杂,通过第一次正则只能匹配器出整体,所以需要第二次分解,引入了Expr.preFilter

    Expr.preFilter保留了3个兼容处理分别是ATTR,CHILD,PSEUDO复杂的选择器

    var identifier = characterEncoding.replace( "w", "w#" );
    var attributes = "\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
        // Operator (capture 2)
        "*([*^$|!~]?=)" + whitespace +
        // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
        "*(?:'((?:\\.|[^\\'])*)'|"((?:\\.|[^\\"])*)"|(" + identifier + "))|)" + whitespace +
        "*\]";
    
    var ATTR = new RegExp( "^" + attributes );
    
    console.log(ATTR.exec("[name*='man']")

    preFilter:

    preFilter: {
        "ATTR": function( match ) {
            match[1] = match[1].replace( runescape, funescape );
    
            // Move the given value to match[3] whether quoted or unquoted
            match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
    
            if ( match[2] === "~=" ) {
                match[3] = " " + match[3] + " ";
            }
    
            return match.slice( 0, 4 );
        },

    伪类放下一章

  • 相关阅读:
    每次VS code中添加新项目格式化就会失效
    Odoo14学习笔记(14) 设置记录规则
    Odoo14学习笔记(13) 用户组权限设置
    微信小程序学习笔记(6) 使用wx.navigateTo做页面跳转
    微信小程序学习笔记(5) 使用wx:for循环显示数据
    微信小程序学习笔记(4) 第三方库request promise使用
    微信小程序学习笔记(3) 第一版小程序发布
    微信小程序学习笔记(2) 图片不显示问题总结
    微信小程序学习笔记(1) 学习开始
    Odoo14学习笔记(12) 在Tree/View中增加自增序号
  • 原文地址:https://www.cnblogs.com/aaronjs/p/3842352.html
Copyright © 2011-2022 走看看