您的位置:首页 > 其它

开发自己的脚本引擎(一)先吹吹水,再干事情。

2006-10-08 02:36 267 查看
开发自己的脚本引擎(一)先吹吹水,再干事情。
vczh
其实我很早以前就想写一些关于脚本引擎开发的文章了。后来由于自己要写一些程序而暂停了这个计划。其实写这篇文章的原因很简单,我在开发脚本引擎的时候在网上找不到适合自己看的资料,不过最后还是做成了,那么就贡献一下吧。
在文章的开头我先声明一下,本文章不是学术论文,不是《编译原理》的入门资料。我写的只是我自己知道的一些东西。本文章讨论的技术之可以用来参考,在实际开发过程中还是要结合自己的实际情况进行优化。
记得我第一次开发ARPG的时候是高一,当时基本上处于小鸟状态,为了支持剧情就自己琢磨了一个简单的命令控制脚本。后来觉得不爽就开发了一个语法类似Pascal的。后来由于转到了VC++,就用C++再写了一次脚本引擎。这次语法当然是模仿C++的啦。后来在开发这个脚本引擎的过程中也学到一些东西。

本文章是整个系列文章的第一篇,在这里我就只讲一个大概,具体的实现细节会在接下来的文章中详细描述。

一个脚本引擎的结构是什么样子的呢?我们可以先从其工作流程看起。一开始就需要一些脚本代码(你可以把这些代码写在文件里),然后就用一个东西把这些代码读进去折腾一下,折腾出来的结果就送到另一个东西去运行。这个东西在运行的时候,碰到自己无法处理的事情,就把那些信息扔给你,你接着干,干完了让它继续工作。于是很明显,就是一个编译器和一个虚拟机。虚拟机里头还有一套跟宿主程序交流的机制。
到了这一步,就开始考察者俩兄弟需要的一些行为,然后就制定接口,然后就干吗干嘛……这些是读软件工程的人的事情,我现在就先不管了,我只管实现。至于人家怎么用,那是他们的事情。
想着想着,你会发现,咦?怎么需要编译器了?其实,编译器在这里充当的是一个整理代码的角色。如果你面对的是一些(语法上)比较复杂的脚本,这东西就可以当之无愧的叫做编译器啦。在我自己开发的那个脚本引擎里,编译器就负责把输入的脚本代码编译成自己设计的一套指令,看起来像汇编。然后虚拟机就根据这些指令和一些其它数据来构造整个指令的运行环境,最后就等待用户启动了。
假设你现在正在开发一个游戏,你需要一个脚本解释程序,你于是就把脚本里头的某些函数映射到你游戏的一些控制上。这个游戏开发完了,可是你还不过瘾,又来一个。新的游戏仍然需要脚本解释程序。如果上一个脚本引擎是依附在游戏上的,那就死定啦!那么多复杂的东西要重来一遍,多不爽啊。于是,现在需要做的就是把不同应用中脚本引擎做的相同的事情抽象出来,先搞成一个东西。以后用来干什么就在开发一些插件扔进去。
于是现在涉及到了脚本引擎跟宿主程序的交流了。这个交流需要干什么事情呢?其实很简单,就两个。第一个是让宿主程序执行制定的一个脚本,或许是脚本中的某一个函数。第二个就是当脚本需要宿主程序功能上的支持的时候,譬如一个MessageBox,这个时候,脚本就要跟脚本引擎说,我给你一些东西,你给我搞一个MessageBox出来。脚本引擎本身当然做不到啦,于是回过头又跟宿主程序说,我把脚本给我的这些东西给你,你帮我搞一个MessageBox出来。宿主程序一听,没问题!于是一个MessageBox就出来啦。

为了脚本引擎跟宿主程序交流的时候方便,我们就可以在脚本语言的语法中加入一些特定的东西,譬如指定一个函数在调用的时候就是让宿主程序替着干的,或者指定一个函数让脚本引擎开一个口子方便宿主程序调用。然后就想办法在设计出一套指令,让编译器好写一点,虚拟机跑起来也好跑一点。这就是我们在开始动手写脚本引擎之前需要干的事情。毕竟设计一个脚本引擎不仅仅要思考那些烦人的算法,事实上脚本的语法也是要自己设计的。不过有时候为了方便就可以参考一些常用的编程语言,然后拿去改造,也就差不多可以了。

吹水就吹到这里了,现在总结一下。
开发一个脚本引擎,必须先设计好脚本语言的语法和虚拟机所需要的数据(指令和其他东西),然后就考察一下编译器和虚拟机所需要的行为,接着就是设计接口,最后就是动手。在下一篇文章中,我将会跟大家聊聊设计语法会碰到的问题和需要注意的一些事情。这个湿很关键的一部哦,对你的编译器和虚拟机的影响是很大的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: