我早就想寫一個腳本引擎了,真的。
事情可以追溯到大一的時候,很想做游戲(雖然后來發現美工成了最大的問題),于是自己寫了一套GUI,用起來還挺爽,但是就是一直覺得缺了個腳本引擎。
于是,奉天承運,我開始著手腳本引擎的計劃了。
話說起碼得先跟字符串培養培養感情,而且也是為了以后寫腳本引擎時能省些苦力,還有很多其他因素影響,我決定先寫一個正則表達式引擎。為了方便,我又得封一個性格良好,功能頑強的String類,要真的實現功能頑強,又得搞好Encoding方面的事情,要方便調試程序,又得把Console和IO方面的東西封好。于是我干脆就跟他拼了,封了一個類.Net的小類庫出來。為了好看,名字空間搞得跟.Net的一模一樣,用起來也挺順溜的。
1 #include "System.h"
2
3 using namespace System;
4 using namespace System::Text::RegularExpressions;
5 using namespace System::Windows::Forms;
6
7 int Program(const String& arg)
8 {
9 Application::RunConsoleApplication();
10
11 Regex exampleExp("(+\\w+):(+\\z+)");
12 String exampleString = "hello:哈嘍!!!";
13
14 Int64 startTime = GetTickCount();
15 Match* m = exampleExp.Match(exampleString);
16 Int64 endTime = GetTickCount();
17
18 Console::WriteLine("---------KSystem Example Program---------");
19 Console::WriteLine("Example Regex:\t" + exampleExp.Pattern());
20 Console::WriteLine("Example String:\t" + exampleString);
21 Console::WriteLine("Matched Value:\t" + m->Value());
22 Console::WriteLine(m->Captures[0] + ":" + m->Captures[1]);
23 Console::WriteLine("Time Cost:\t" + String::ToString(endTime - startTime) + " ms");
24 Console::WriteLine("-----------------------------------------");
25
26 return 0;
27 }
不要問我為什么字符串前面不加L,也不要問我為什么沒有delete那個m,我的庫會干這些事情的。表達式中那個\z是匹配中文字的意思
運行結果:

做這么個正則表達式,還輸掉了我一餐pizza。當時跟vczh同學打賭,他說我寫完肯定有bug,我說我肯定沒bug。結果不出意料地有bug,于是一餐華麗的pizza被送進了我們肚子。重要經驗:是個程序必然有bug,恩恩。
這個正則表達式引擎剛寫出來時性能奇差無比,主要時間耗在了內存分配上。經過一系列優化,vczh也跟著我一起優化了他那個正則表達式引擎,到最后某次性能測試時,我的花了13秒,vczh同學的花了12秒,也有時候是我的更快,視表達式寫法不同而略有差別,基本上平均下來是一樣的。(boost和greta花了40+N秒)
有了正則表達式引擎,也有了跟字符串幾個月的感情,現在終于開始計劃腳本引擎了。由于還是第一次,總有點畏首畏尾的,我決定先寫一個非常菜的版本。強類型,無閉包,面向過程,支持數組,不支持自定義結構。這是我計劃的CNScript的第一版本,也稱CaiNiaoScript。
其實我真的想實現的是CNScript的第二個版本,ChinaScript。這會是一個類自然語言寫法的中文腳本引擎。寫起來變量和函數命名絕對會很不習慣,但是寫完之后卻會像一篇文章一樣流利。
例如:現在用C++,模擬一個人使用某個交通工具去某個地方的行為。
Class TrafficTool;
Class Car : public TrafficTool;
Class Man
{
void TravelTo(Point destination, TrafficTool* trafficTool);
};
用起來就是
Man Peter;
TrafficTool* BMW = new Car();
Point beijing;
Peter.TravelTo(beijing, BMW);
雖然程序員一看就能理解個大概,但是非程序員很難使用或維護它。在將來的CNScript中,也許會是這樣(估計最后不會這么羅嗦):
有一種東西叫交通工具,汽車就是一種交通工具。
有一種東西叫人。 //我承認這句話有點怪,語法細節問題需要仔細琢磨,誰有好的建議可以留言給我喔,感激萬分
有一種東西叫做目的地。
有一種行為:一個人乘坐一個交通工具去往一個目的地。
//以上是聲明,以下是使用這幾個類的代碼
有一個人叫Peter。
有一個汽車叫寶馬。
有一個目的地叫北京。
Peter乘坐寶馬去往北京。
這樣的代碼,雖然在函數和變量命名時要仔細考慮,但是寫出來的代碼即使是不懂程序的人也能看明白,為的是兼顧游戲開發的各個環節的人員。
好了,想法到此為止,今晚開始動工CNScript的第一版,CaiNiaoScript! 我會把我每個階段的工作和工作原理都寫在這篇日記中,有興趣的朋友可以跟著一起玩玩喔!