接下来我们来看一下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这种形式无法正确解析,如果想要支持正号(+)解析操作,也不难,毕竟我们已经完成了负号(-)解析,处理流程类似,这个问题就交给各位读者去解决。