接下来我们来看一下IDoom3Tokenizer词法解析器中最复杂的一个解析方法,具体代码如下所示:

private _getNumber ( token: Doom3Token ) : void {
    let val : number = 0.0 ;
    let isFloat : boolean = false ; // 是不是浮点数
    let scaleValue : number = 0.1 ; // 缩放的倍数

    //获取当前的字符(当前可能的值是[数字,小数点,负号] )
    //目前不支持+3.14类似的表示
    //如果 - 3.14这种情况,由于负号和数字之间有空格,所以目前会解析成[ '-' , 3.14 ]这两个token
    //目前支持例如:[ 3.14 , -3.14 ,  .14  , -.14 , 3.  , -3.  ]的表示
    let c : string = this . _getChar ( ) ;
    //预先判断是不是负数
    let isNegate : boolean = ( c === '-' ) ; // 是不是负数
    let consumed : boolean = false ;
    //获得0的ascii编码,使用了字符串的charCodeAt实列方法
    let ascii0 = "0" . charCodeAt ( 0 ) ;
    // 3.14 -3.14 .13 -.13 3. -3.
    // 只能进来三种类型的字符 :  [  -  . 数字 ]
    do {
        // 将当前的字符添加到token中去
        token . addChar ( c ) ;
        // 如果当前的字符是.的话,设置为浮点数类型
        if ( c === '.' ) {
            isFloat = true ;
        } else if ( c !== '-' ) {
            // 10进制从字符到浮点数的转换算法
            // 否则如果不是-符号的话,说明是数字(代码运行到这里已经将点和负号操作符都排斥掉了,仅可能是数字)

            //这里肯定是数字了,我们获取当前的数字字符的ascii编码
            let ascii : number = c . charCodeAt ( 0 ) ;
            //将当前数字的ascii编码减去"0"的ascii编码的算法其实就是进行字符串-数字的类型转换算法
            let vc : number = ( ascii - ascii0 ) ;
            if ( ! isFloat ) // 整数部分算法,10倍递增,因为10进制
                val = 10 * val + vc ;
            else {
                // 小数部分算法
                val = val + scaleValue * vc ;
                //10倍递减
                scaleValue *= 0.1 ;
             }
        } /* else { // 运行到这段代码时,当前的变量c肯定为负号 
console.log ( " 运行到此处的只能是 : " + c ) ;
}*/
       //上面循环中的代码没有消费字符,之所以使用consumed变量,是为了探测下一个字符
        if ( consumed === true )
            this . _getChar ( ) ;
       //获得下一个字符后,才设置consumed为true
        c = this . _peekChar() ;
        consumed = true ;
     //结束条件:数据源解析全部完成或下一个字符既不是数字也不是小数点(如果是浮点数表示的话)
    } while (c . length > 0 && ( this . _isDigit ( c ) || ( ! isFloat && c === '.' ) ) ) ;
    //如果是负数的话,要取反
    if ( isNegate ) {
        val = - val ;
    }

    //设置数字值和NUMBER类型
    token.setVal ( val ) ;
}

  上面这段代码还是比较复杂的,要理解这段代码,最好的方式就是使用一个具有典型性的例子,我们来看一下如下代码:

et input:string = " [ 3.14 , -3.14 ,  .14  , -.14 , 3.  , -3. , +3.14 ] " ;
//我们使用setSource重新设置数据源
tokenizer . setSource ( input ) ;
while ( tokenizer . getNextToken ( token ) ) {
    if ( token . type === ETokenType . NUMBER ) {
        console . log ( "NUMBER : " + token . getFloat () ) ;
    }
    else {
        console . log( "STRING : " + token . getString ( ) ) ;
    }
}

  运行代码后的结果如图2.3所示:

  • 左右中括号以及逗号作为STRING类型的Token正常的解析出来。
  • [3.14 , -3.14 , .14 , -.14 , 3. , -3.]表示方式也正常解析出来。   +3.14这种形式无法正确解析,如果想要支持正号(+)解析操作,也不难,毕竟我们已经完成了负号(-)解析,处理流程类似,这个问题就交给各位读者去解决。

图2.3  不支持的数字解析格式

随风而行之青衫磊落险峰行(www.buleifeng.top) all right reserved,powered by Gitbook本文件修订时间: 2019-10-10 16:33:17

results matching ""

    No results matching ""