《TypeScript图形渲染实战:2D架构设计与实现》 —2.2.10 实现_getNumber方法解析数字类型
2.2.10 实现_getNumber方法解析数字类型
接下来看一下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.
// 只能进来3种类型的字符 : [ -, ., 数字]
do {
// 将当前的字符添加到Token中
token . addChar ( c ) ;
// 如果当前的字符是.的话,设置为浮点数类型
if ( c === '.' ) {
isFloat = true ;
} else if ( c !== '-' ) {
// 十进制从字符到浮点数的转换算法
// 否则如果不是-符号的话,说明是数字(代码运行到这里已经将点和负号操作符都
排斥掉了,仅可能是数字)
//这里肯定是数字了,获取当前的数字字符的ASCII编码
let ascii : number = c . charCodeAt ( 0 ) ;
//将当前数字的ASCII编码减去0的ASCII编码的算法,其实就是进行字符串-
数字的类型转换算法
let vc : number = ( ascii - ascii0 ) ;
if ( ! isFloat ) // 整数部分算法,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 ) ;
}
上面这段代码还是比较复杂的,要理解这段代码,最好的方式就是使用一个具有典型性的例子,来看一下如下代码:
let 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 不支持的数字解析格式
- 点赞
- 收藏
- 关注作者
评论(0)