我们来看一下正常的字符串是如何解析的,实现代码如下所示:

  1. // 进入该函数,说明肯定不是数字,不是单行注释,不是多行注释,也不是子字符串
  2. // 进入该函数只有两种类型的字符串,即不带双引号或单引号的字符串以及specialChar
  3. private _getString ( token: Doom3Token ): void {
  4. // 获取当前字符,因为前面已经判断为字符串了
  5. let c : string = this . _getChar ( ) ;
  6. token . setType ( ETokenType . STRING ) ;
  7. // 进入循环
  8. do {
  9. //将当前的char添加到token中
  10. token . addChar ( c ) ;
  11. if ( ! this . _isSpecialChar ( c ) ) {
  12. c = this . _getChar ( ) ; // 只有不是特殊操作符号的字符,才调用_getChar移动当前索引
  13. }
  14. //如果this . _isSpecialChar ( c )为true,不会调用_getChar函数,并且满足了跳出while循环的条件
  15. //结束条件:数据源解析全部完成或下一个是空白符或者当前字符是特殊符号
  16. } while ( c . length > 0 && ! this._isWhitespace ( c ) && ! this._isSpecialChar ( c ) ) ;
  17. }

  代码注释比较详细,各位读者可以了解一下。这里会看到,和子字符串不同的一点是,我们的_getString会将一些特殊的字符(标点符号)作为单独的Token返回,具体有哪些特殊的字符,其实依赖于你的决策。在默认情况下,我们的实现代码如下所示:

  1. // 我们将左右大中小括号以及点号逗号都当作单独的Token进行处理
  2. // 如果想要增加更多的标点符号作为token,可以在本函数中进行添加
  3. private _isSpecialChar ( c : string ) : boolean {
  4. switch ( c ) {
  5. case '(' :
  6. return true ;
  7. case ')' :
  8. return true ;
  9. case '[' :
  10. return true ;
  11. case ']' :
  12. return true ;
  13. case '{' :
  14. return true ;
  15. case '}' :
  16. return true ;
  17. case ',' :
  18. return true ;
  19. case '.' :
  20. return true ;
  21. }
  22. return false ;
  23. }

  Doom3文本文件词法解析器的源码都演示完毕,最好的研究源码方式是断点调试,大家可以去本书备注的网站下载本章的源码进行调试。