《TypeScript图形渲染实战:2D架构设计与实现》 —2 使用TypeScript实现Doom 3词法解析器

举报
华章计算机 发表于 2019/12/11 12:10:32 2019/12/11
【摘要】 本节书摘来自华章计算机《TypeScript图形渲染实战:2D架构设计与实现》 一书中第2章,第2.1.1节,作者是步磊峰。

第2章  使用TypeScript实现

Doom 3词法解析器

  本章的目的是想让大家了解TypeScript中常用的一些语法及编程方式(如面向对象编程、面向接口编程、泛型编程,以及常用的设计模式等),因此,特别以面向接口的方式编写了一个Doom3(原id Software公司毁灭战士3游戏引擎)词法解析器,并且在此基础上实现了工厂模式和迭代器两种设计模式,使其支持接口的生成,以及使用迭代方式进行Token的解析输出。

  Doom3引擎中所有的资源都存储在后缀名为.pk4的资源文件包中。该资源文件包实际上就是一个zip压缩文件,因此可以将.pk4后缀名更改为.zip,然后就可以直接使用,例如winzip解压程序进行解压并浏览该文件。

  当打开pk4文件浏览后会发现一个事实:Doom3引擎中大部分的资源都是基于文本描述的(除了图片、视频及音频等资源外),并且基于一套简单的、统一的词法规则。如何将文本按照词法规则描述解析成有意义的标记(Token)是本章的另外一个重要目的。

  最后对XMLHttpRequest对象进行二次封装用于向服务器请求资源。这样就能够利用第1章中部署的lite-server服务器,将所有存储在lite-server服务器上的文本文件、二进制文件、视频文件和音频文件传输到TypeScript(网页客户端)中进行处理。

 实际上,实现的词法解析器不仅仅用于Doom3引擎相关资源的解析,通过些许扩展,还可以支持解析各种不同格式的ASCII编码文本文件,例如Wavefront的obj模型文件,以及mtl材质文件等。

2.1  Token与Tokenizer

  为简单起见,使用JS代码作为示例来了解一下JS的Token相关内容,以加深对Token的理解。代码如下:

 

if ( b === true )

    alert ( "true" ) ;

 

  在浏览器中输入网址http://esprima.org/demo/parse.html后,将上述代码粘贴到左侧文本编辑框内,然后选择Tokens Tab选项,就会获得如下结果:

[

    {

        "type" : "Keyword" ,

        "value" : "if"

    } ,

    {

        "type" : "Punctuator" ,

        "value" : "("

    } ,

    {

        "type" : "Identifier" ,

        "value" : "b"

    } ,

    {

        "type" : "Punctuator" ,

        "value" :  ==="

    } ,

    {

        "type" : "Boolean" ,

        "value" : "true"

    } ,

    {

        "type" : "Punctuator" ,

        "value" : ")"

    } ,

    {

        "type" : "Identifier" ,

        "value" : "alert"

    } ,

    {

        "type" : "Punctuator" ,

        "value" : "("

    } ,

    {

        "type" : "String" ,

        "value": "\"true\""

    } ,

    {

        "type" : "Punctuator" ,

        "value" : ")"

    } ,

    {

        "type" : "Punctuator" ,

        "value" : ";"

    }

]

  通过上述代码可以看到,Esprima(ECMAScript词法语法解析器)会将JS源码解析成Token的集合表示。每个Token具有type属性,表示该Token的类型分类,并且具有value属性,表示该Token的值是什么。

  由此可见,Token(标记或记号)就是指一组不可分割的字符或字符串,它能唯一地、没有歧义地标记出一种状态。从本质上来说,就是特殊的字符或字符串(例如if和=== 等)。而Esprima则是Tokenizer,其作用是将字符串表示的JS源码数据读取进来,按照预先设定的标准进行分类处理,处理的结果就是Token。

  事实上,Esprima是一个ECMAScript解析器,包含词法解析和语法解析,最终会将JS源码解析成抽象语法树(Abstract Syntax Tree,AST),而在这里由于演示的原因,仅仅使用了Esprima的词法解析功能,并没有使用到语法解析功能。

2.1.1  Doom3文本文件格式

  如果要实现一个特定文件格式的词法解析器,一定要了解该文件的词法特征,根据文件的词法特征抽象出分类规则,然后才能编码实现词法解析功能。因此本节来讲解一下Doom3引擎中的文本文件的相关规则,使用如下一段具有普遍性的文本字符串:

 

numMeshes  5

 

/*

* joints关键字定义了骨骼动画的bindPose

*/

joints {

       "origin" -1  ( 0 0 0 )  ( -0.5  -0.5  -0.5 )          

       "Body"  0  ( -12.1038131714  0  79.004776001 )  ( -0.5 -0.5 -0.5 ) // origin

}

 

  例如,numMeshes和joints等没有双引号的单词,作为关键字处理,也就是Doom3引擎预先定义好的具有特定含义的一些词,它们具有唯一性及不可更改性。

  例如,"origin""Body"这些具有双引号的单词,作为标识符处理,这些标识符并非由Doom3引擎预先定义,而是由美术设计等相关人员或者模型制作动画师定义的名称。

  在“/*”和“*/”之间的文字被Doom3引擎的词法解析器视为注释,和TypeScript一样,表示多行注释。斜杠“//”后的文字则被视为单行注释,这也和TypeScript的单行注释保持一致性。

  大括号对“{ }”表示一个块状模块,可以将其视为一个区块分组,和TypeScript作用域类似。小括号对“( )”内部是使用浮点数表示的向量或矩阵数据,可以将其看成数组,需要注意的一点是,数组元素之间不是使用逗号分隔,而是使用空格符号进行分隔。

  Doom3文本文件中的数据类型其实只有两种:字符串和数字,其中关键字和标识符都可以看成字符串类型,而数字可以分为整数和浮点数两种类型。

  上述内容基本囊括了Doom3文本文件格式的关键之处,还有一些隐藏在深处的规则,将在源码实现的过程中进行描述。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。