升C小调狂想曲

<递归的忧伤>
posts - 10, comments - 71, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2009年6月3日

JustType新命令translate~ 实时翻译! 废话不多说,截2个图先:(http://justtype.cloudapp.net 我前一篇博文有更详细地介绍这个JustType项目)

image

image

 

我们经常会有这种需求,就是翻译一小段看不太懂的外语。Google提供了翻译服务,但是如果每次都要打开Google那个翻译页面,倒也挺麻烦。于是我把翻译功能也做成了JustType的命令,现在在JustType中就可以通过translate命令来翻译任何语言的文字了。想体验的话:http://justtype.cloudapp.net

 

整个translate命令的脚本代码很简单,先用正则表达式分析了命令结构,然后向网页写入javascript代码,在javascript中引用google函数库,调用对应函数即可:

import System
import System.Text
import System.Text.RegularExpressions
import System.Web

from System.Text.RegularExpressions import *

def OnCommand(command):
    sourceLang = "en"
    targetLang = "zh"
    text = command
    chkAdvancedUsage = Regex("(?<text>(.|\n)+?)\\s+from (?<from>[a-zA-Z]+) to (?<to>[a-zA-Z]+)")
    m = chkAdvancedUsage.Match(command)
    if m.Success:
        sourceLang = m.Groups["from"].Value
        targetLang = m.Groups["to"].Value
        text = m.Groups["text"].Value
    render = "<div id=\"divTranslation\" style=\"background-color:#f0f8ff; border:dotted 1px gray; padding:5px; width:500px; \"></div>\n"
    render += "<script type=\"text/javascript\" src=\"http://www.google.com/jsapi\"></script>\n"
    render += "<script type=\"text/javascript\">\n"
    render += "google.load(\"language\", \"1\");\n"
    render += "function initializeTranslation() { google.language.translate(\"" + System.Web.HttpUtility.HtmlEncode(text.Replace("\n", " ").Replace("\r", "")) + "\",\"" + sourceLang + "\", \"" + targetLang + "\", function(result) {\n"
    render += "if (!result.error) { document.getElementById(\"divTranslation\").innerHTML = result.translation; } else { document.getElementById(\"divTranslation\").innerHTML = \"error!\" }\n"
    render += "}); }"
    render += "google.setOnLoadCallback(initializeTranslation);"
    render += "</script>"
    SetTipText(render)
    return True

 

在JustType中,一个命令对应一个执行脚本,我们可以自己写新脚本,同时可以允许其他人调用自己写的程序。大家互相分享自己智慧的同时,也在利用编程技术增加自己和他人的工作效率。更多的信息请到http://justtype.cloudapp.net 获取。 :)

posted @ 2009-06-03 21:00 陈坤 阅读(7351) | 评论 (5)编辑 收藏

2009年6月2日

每当我们打开电脑,我们可能经常会做一些习惯性的动作。例如查一下邮件啦,看看新闻啦,观察一下股票走向啦。仔细想一下就发现,这里面有很多动作是我们每天都会重复的。有没有可能更方便一点呢?

有。很简单,身为程序员的我们,为每种固定的操作写个小程序就好了。但这样一来会带来几个问题:

1. 小程序写多了,很难统一管理。而且有些带参数的程序(例如按照一定股票编号去查询价格的程序),使用起来并不一定方便。

2. 我们可能经常使用不同的电脑,那么要同步这些小程序会非常头疼。

3. 你也写,我也写,大家写了大量重复的小程序,很浪费资源。

为了应对这些问题,我提出了一个叫JustType的框架,我们可以在http://justtype.cloudapp.net 访问它。

JustType的界面就是一个文本框,一切都在这个文本框中进行。在JustType框架中,每个小程序都对应一个命令,命令可带参数。写好的小程序会保存在服务器,每一个人都可以选择是否要公开自己的小程序。这样大家可以很方便地共享自己的成果。

让我们来逐一看看JustType拥有的功能。

首先,最基本的,你可以在JustType中输入一个网址,一按回车就会访问该网址。

image

当然,仅仅是这样的话,很傻。因为浏览器的地址栏更好用多了。但是,JustType远远不止这点。

我们可以为一个命令设置一个别名,例如:

image

经过这样的设置后,下次我只要打cppblog就会自动进入http://www.cppblog.com 了。

还有很多时候,我们会遇到一些小小的计算问题。Windows那个计算器实在很不好用,让我们看看JustType:

image

image

这个calc命令会将后面的表达式求值并显示出来。实际上,这里这个表达式是Python的表达式,JustType中所有的小程序都运行在IronPython上,并且可以使用.net framework类库中的大多数功能。

当然,除了简单的表达式以外,我们还可以执行更复杂的脚本:

image

输入这个命令之后,界面就会变成下面的样子:

image

MultiLineTextMode是一个预定义函数,功能是将主界面上的文本框变成多行模式,这样我们就可以输入更复杂的脚本了。下面我们试试使用一些.net framework中的功能:

image

输出结果如下:

image

SetTextBoxText也是一个预定义函数,可以改变主界面中文本框内的文本。更多的预定义函数描述可以在http://justtype.cloudapp.net/Help.aspx 中看到。

除了临时执行脚本以外,我们也可以将脚本写成小程序保存起来。输入newcommand命令,就会进入创建命令的页面。我们将这个小程序命名为translate,然后输入以下代码:

import System
import System.Web

def OnCommand(command):
    GoToURL("http://dict.youdao.com/search?q=" + System.Web.HttpUtility.UrlEncode(command))
    return True

程序依然是用IronPython写,其实Python语法很简单。http://www.python.org 感兴趣的用户可以去看看。这个OnCommand函数就是用来接收消息的。当JustType收到命令后,会找到这个命令对应的脚本,并将参数传给脚本的OnCommand函数来执行。我们看到,这里程序调用了GoToURL函数,转向了有道词典的页面。在创建了这个程序后,我们就可以在JustType的文本框中输入下面的命令:

image

一按回车,就会转向翻译结果:

image

类似地,我们可以写出很多很多方便实用的小程序。在我们创建程序时,我们可以选择是否要公开。如果公开的话,别的用户就可以通过“你的用户名.程序名”来调用你的程序。例如我的用户名是ck,那么其他用户就可以输入ck.translate来调用我的程序,当然他喜欢的话也可以用setalias来设置一个方便的别名。如果所有公开的程序中,只有我这个程序叫做translate,那么其他用户不打ck.translate而直接打translate也可以成功调用。

另外,JustType提供一种简单的数据存储。每一个程序在一个用户的账户中会有一个独立的存储空间,可以存储1000行数据。例如我利用这个特性开发了一个叫做note的小程序,可以临时记录一些小笔记:

image

那么之后我就可以看到我的笔记:

image

所有的程序和数据,都存放在服务器端,用户不用担心不同机器的问题。无论你走到哪里,都可以像在一台机器上一样访问所有服务和数据。

新服务刚刚搭建好,欢迎大家试用和提供意见喔。网址是http://justtype.cloudapp.net

posted @ 2009-06-02 16:27 陈坤 阅读(1981) | 评论 (9)编辑 收藏

2008年10月9日

未读过本系列文章的,请先参考http://www.cppblog.com/ckyap/archive/2008/10/06/63287.html

BoxSharp 最新进展!

image

输入硬盘地址时的自动提示,另外还有按TAB键即可切换目录,行为与cmd命令行里面输入地址栏时类似

image 

Note功能,可以随时记下一下小事情。命令为/note something。输入/note会打开当前所有notes列表。

工具栏自定义按钮功能,输入/toolbutton add "button name" command即可自定义一个按钮,按下即会执行指定的command命令,效果与在文本框中输入command然后按回车一样。

之前一位朋友提到的/define功能,我觉得如果需要参数,就应该写成新插件,而不是定义成另外一个命令;如果不需要参数,那就可以通过现在这个toolbutton实现。所以暂时不做了。

全局热键在WPF下面貌似很有问题。。。至少我还没找到解决方案,这几天太忙了,有空我还要继续想办法。

最新版这里下载 http://code.google.com/p/boxsharp/downloads/list

posted @ 2008-10-09 22:29 陈坤 阅读(1437) | 评论 (11)编辑 收藏

2008年10月6日

这篇文章是继续上一篇《命令的缤纷》来阐述的。未阅读过前一篇的请参见这里:http://www.cppblog.com/ckyap/archive/2008/09/12/61641.html

功能可以看下面几个图:

 

image

总而言之,BoxSharp提供一种可扩展的方式让你在一个TextBox中干任何事情。

此项目已经正式作为开源项目放在Google Code上啦!大家可以在这里访问项目主页:http://boxsharp.googlecode.com/

那啥Subversion搞了我一个小时。。。真是感叹现在的高科技啊。

在这里可以下载最新的可执行文件,只能运行在Win32平台上,需要.net framework 3.5支持:

http://code.google.com/p/boxsharp/downloads/list

在这里可以查看最新的文档:

http://code.google.com/p/boxsharp/w/list

在这里可以查看源代码:(要有Subversion才能下载到代码)

http://code.google.com/p/boxsharp/source/checkout

posted @ 2008-10-06 00:13 陈坤 阅读(2064) | 评论 (11)编辑 收藏

2008年9月12日

这篇文章是继续上一篇《命令的痴狂》来阐述的。未阅读过前一篇的请参见这里:http://www.cppblog.com/ckyap/archive/2008/09/09/61427.html

这一次我做了一个可以自定RSS源的新闻滚动播放器插件,滚动新闻就放在TextBox的旁边,鼠标放过去有新闻简介,点击就可以打开浏览器浏览新闻。这样在工作之余,抬起头就能看看当时最新的新闻,不亦乐乎!

image 

 

除了新闻播放器,这两天主要做的就是一个智能提示框。就像Firefox那个“棒极了的地址栏”一样,我希望这个框框能智能的提示我一些操作和命令。大多数时候,我们想通过一些熟悉的名字来启动一些程序,比如输入QQ,就给我启动QQ,输入IE,就给我打开IE。有时候我们也希望通过一些简称来访问一些网站,比如输入baidu,就给我打开百度,输入google就给我打开google,而不需要输入完整的http://www.baidu.com 。当然,如果让我们手动添加所有的命令,比如我亲自告诉程序,“如果我输入baidu就给我打开http://www.baidu.com”,这当然很轻松,但是我很懒,我不想每次都亲自添加这种命令,我需要他自动帮我找出来。

第一个我能想到的地方,就是开始菜单的“程序”目录里了。遍历里面所有的快捷方式,把名字分析一下,加入待选列表,搞定。不过这个名字分析的过程比较麻烦,因为比如QQ他的快捷方式默认是叫“腾讯QQ2009”,但是我只想输入QQ就打开它。另外比如Microsoft Visual Studio 2008,我只想输入MVS这个简称来访问它。这个就是一些特征的提取了,也不会太难。

image

image

除了程序目录,Program Files也是一个好地方,里面的exe一般都是有用的程序,提取出来,一起放进来,它就能提示我更多东西了。

第二个主要地方,就是收藏夹和浏览器历史了。遍历里面所有的项目,分析一下,也加入待选列表。同样是分析过程比较重要,决定了能否得到正确的提示。

image

image

选到需要的项目上,按回车就行了。这里我准备对使用次数做排名,使用得多的项目会浮到最上面去,也就是直接按回车就会启动的位置。

 

OK,现在这个框框可以干的所有事情,总结一下:

1.可以输入/exit,退出。(别扔砖头。。。)

2.可以输入/baidu,/google等搜索引擎对一个词进行搜索。搜索引擎可以通过配置文件指定。

3.可以输入一个完整的路径名,或者一个完整的URL,打开访问。

4.可以输入C#代码,立即执行。(可以进行表达式运算等操作)可以保存代码段,以后通过一个名字来直接执行它。

5.可以随时看到最新的新闻滚动播放,点击即可在浏览器中打开。RSS新闻来源可以自定。

6.自动索引常用程序和网页,可以通过输入它们的简称,或任何你想得到的代表词语来运行它们。

 

下一步准备做的,桌面搜索~

posted @ 2008-09-12 00:29 陈坤 阅读(1504) | 评论 (6)编辑 收藏

2008年9月9日

朋友,可曾想过把所有的事情都放到一个TextBox里面去做?今天我就做了一个,理论上可以干任何事情的TextBox。嘿嘿。

实习的日子实在是挺忙,CNScript还停留在语法分析的阶段,一直没时间去打开那个大工程(其实是有时间的,可惜零碎的时间都被我拿来写这篇文章要讲的这些小东西了)。

我们在浏览网页时,或许会突然想打开某个程序,比如计算器,算点东西;又可能想打开Photoshop,处理一下网页上的某个图片;又可能想打开记事本,摘抄一些文字。这时我们不得不回到桌面,或者打开那个硕大的开始菜单,在程序里面去找我们想要的东西。

有的时候,我们还会重复做一些机械的动作,比如读一个文件,检查是否有变动,比如检查某个文件夹,看是否有新文件。当然,你可以写一个程序来完成这个操作,但是有时候这种操作你觉得最多就重复个两三次,你不会愿意去打开Visual Studio创建一个工程。

归结本质,我们就是想要一个随叫随到的,可以有一定能力帮我们做事情的东西。但是如果这个东西太大,会挡住我们正在浏览的网页或者正在处理的文档,那就不好了。所以我就想到了一个Topmost的TextBox,放在屏幕的顶端,也就是一般窗口的标题栏那里,这样子不会挡住你要做的事情,而且在需要的时候 只要鼠标一移过去就可以用了。

就是这样一个TextBox

OK,有了这样一个TextBox,“随叫随到”已经完成了。但是我们需要这个TextBox有一定能力,比如我想运行一个程序,它能帮我运行,我想搜索一个词语,他能帮我搜索,我想打开一个URL,他能帮我打开,我想计算一个表达式,他能帮我计算。但是人的需求是无限的,我们随时会有新的需要,他不可能拥有所有的功能,那么如何让他有能力做到任何事情呢?我们需要一种很强悍的可扩展性。玩过魔兽世界的朋友们一定知道,魔兽世界提供一个插件机制,玩家可以为游戏写插件,来丰富游戏的功能,现在已经有千千万万的魔兽世界插件在各大网站上提供下载了,正是因为如此,魔兽世界才拥有着这么强的可扩展性。所以,我们这个TextBox也要用插件机制来驱动。在C#的Microsoft.CSharp名字空间中有一个C#的编译器,可以将C#代码编译成托管组件,直接生成在内存中,以反射的方式来运行,这个机制为我们快速实现一个插件系统提供了可能。因此我选用了.net framework 3.5,用Windows Presentation Foundation来做界面,用C#来当我的脚本语言。

俗话说,一不做,二不休,既然提供了插件,那我主程序除了运行插件以外就什么都不做了。运行了插件之后,将界面所有控件的控制权都交给插件,插件爱干啥就干啥去。主程序就是一个Window,Window上是一个StackPanel,Panel里面是一个TextBox,仅此而已。当然,插件可以向StackPanel里面加东西,以丰富这个条条的外观内容。

 

可执行程序的环境如下所示:(BoxSharp是这个程序的名字)

image

其中BoxSharpCore,BoxSharpRunPath,BoxSharpScripting,BoxSharpSearch是我刚写好的几个插件。

BoxSharpCore插件提供了最基本的/exit命令,用于退出程序。此插件还控制了一些外观方面的细节,包括自动记住TextBox上次退出时的位置,大小,用于下次启动时恢复外观。当输入在文本框内的命令是一个正确命令时,会出现功能提示。

image

BoxSharpRunPath插件提供了打开文件夹,打开网址,运行命令的功能。

image image image

BoxSharpScripting插件提供了直接运行C#程序的功能。这个功能可以顺便当作表达式计算器用,有时候有些运算(尤其是带N个括号的复杂表达式)想立刻得出结果的,就不用打开计算器了。Print函数是用于将参数值直接写在TextBox里面的。

image

image

image

也可以直接用/script命令打开一个窗口进行复杂的编程。

image

BoxSharpSearch插件是提供Web搜索功能的,我们可以通过配置文件来配置搜索引擎,插件启动时会自动检测配置项的。

image

image

我有时间的话,完全可以写更多的插件,比如自动检测电子邮件,收发邮件,比如滚动播放新闻,比如自动搜新歌下载试听,比如日历,日程安排,约会提示,闹钟,这些都可以作为插件写到里面去。而且,如果,我是说如果,如果很多用户在用这个TextBox的话,他们可以共享他们自己写的插件,将彼此的BoxSharp功能丰富。

好吧,说到底了,.net framework 3.5能办到的,这个TextBox就能办到,但是你估计不会为了计算一个表达式而打开Visual Studio建工程的。这就是TextBox的魅力所在了,HOHO~

posted @ 2008-09-09 22:58 陈坤 阅读(2099) | 评论 (12)编辑 收藏

2008年8月9日

     摘要: 首先祝贺北京奥运会精彩开幕!!我亲眼见到了鸟巢的壮观景象,跟一堆外国人在一起看开幕式时我第一次感觉这么自豪!加油奥运,加油中国!今天把词法分析器写好了,一个巨大的switch。代码如下://CNScriptLex.h  1 #ifndef CNSCRIPTLEX_H 2 #define CNSCRIPTLEX_H 3 ...  阅读全文

posted @ 2008-08-09 01:27 陈坤 阅读(1939) | 评论 (8)编辑 收藏

2008年8月8日

上一篇我已经将各个词法标记都设计好了,现在我们需要写出一个程序,他读入一个字符串,并输出一系列Token,其中每个Token就是一个词法标记,例如Keyword,Identifier,Number,Operator。

假设我们输入int a=100;这样一个字符串作为代码,那么我们将如何分析呢?

首先读入i,“i”符合Identifier的规则,但是继续读下去还有个n,一共是“in”,“in”也符合Identifier的规则,再读,变成“int”,“int”符合Type的规则,继续读入后面的空格,变成“int ”,这个可不符合任何规则了,因此我们不能承认这一步,只好取上一步的可接受的结果Type:“int”。这样我们就生成了第一个Token,他的类型是Type,值是“int”。以此类推,我们可以读完整个程序,并完成整个词法分析的过程。

但是每一次都去判断整个已读入的字符串是否匹配某个规则,效率非常低,我们需要一种线性读入字符串,并实时掌握目前字符串匹配状况的办法。确定性有穷自动机(DFA)就是这样一种状态机。

下面是我为CNScript画出的状态图:




例如刚才读的int a=100;
我们一开始是在编号为0的状态,现在输入i,因为i属于a-zA-Z的范围,所以通过最后一幅图我们看到,我们将迈向编号为44的状态。再输入n,因为n属于a-zA-Z0-9_的范围,所以我们继续走在编号44的状态,t也如此,但是输入空格时,我们发现44号状态没有接受空格字符的出口,也就是无法继续走下去了,而且44号状态是一个可接受状态,所以我们接受已经输入了的“int”。
在这里我们的44号状态,接受意义是一个name,可以是Identifier,也可以是Keyword,也可以是Type,当我们取得name:“int”时,我们再判断发现这是一个Type,所以我们得出Token:Type:“int”。然后状态回到0号,继续输入刚才的空格。以此类推。

所以我们只要按这个状态图去遍历字符串,我们就会不断的在各个状态中辗转反复,并不断的得出Tokens。这就是我们词法分析的基本原理。
下一篇我会写出这个DFA的代码和具体使用方案。

posted @ 2008-08-08 00:15 陈坤 阅读(1516) | 评论 (3)编辑 收藏

2008年8月5日

要写一个脚本引擎,首先要明确脚本长什么样,具备哪些功能,需要有怎样的能力。
Since昨天我说第一版是面向过程,强类型,无闭包,无自定义结构,支持数组,那么我将脚本设计如下:

CNScript 0.1 Draft

 

Functionality:

Procedure Oriented, No Custom Data Structures, No Closures, Strong Typed, Array Supported.

 

Keywords:

int,double,char,string,bool,void,if,else,for,do,while,return

 

Statements:

Single Expression:

expression;

 

Chunk:

{

         Statement1

         Statement2

}

 

Array Declaration:

type name[size];

 

Variable Declaration:

type name [= expression];

 

Function definition:

type FunctionName(type paramName1, type paramName2)

Chunk

 

IF-ELSE:

if(expression)

Statement1

else

Statement2

 

FOR-LOOP:

for(statement1 expression2;expression3)

Statement

 

WHILE-LOOP:

while(expression)

Statement

 

DO-WHILE-LOOP:

do

Statement                                              

while(expression);

 

Expressions:

         Values:

                   true

                   false

                   number

                   string

                   char

                   Variable Name

                   Array Name[index]

 

         Assign:

         name = expression

 

         Function Call:

         name(expression1,expression2)

 

         Compares:

                   expression1 == expression2

                   expression1 != expression2

                   expression1 < expression2

                   expression1 > expression2

                   expression1 <= expression2

                   expression1 >= expression2

 

         Boolean Operations:

                   !expression

                   expression1 && expression2

                   expression1 || expression2

 

         Calculating:

                   expression++

                   expression

                   ++expression

                   --expression

                   expression1 + expression2

                   expression1expression2

                   expression1 * expression2

                   expression1 / expression2

                   expression1 % expression2

                   expression1 ^ expression2

                   (expression)

 

Lexical Tokens:

Spaces:

         Space:                         (space_bar+)|(\n+) (\r+)|(\t+)

TypeNames:

         Type:                           (int)|(double)|(char)|(string)|(bool)|(void)

Keywords:

         Keyword_if:               if

         Keyword_else:          else

         Keyword_for:            for

         Keyword_do:             do

         Keyword_while:       while

         Keyword_return:     return

Brackets:

         BigLeftBracket:        {

         BigRightBracket:     }

         MidLeftBracket:       [

         MidRightBracket:    ]

         SmallLeftBracket:    \(

         SmallRightBracket: \)

Identifier:

         Identifier:                  (_+[a-zA-Z0-9_]+)|([a-zA-Z][a-zA-Z0-9_]*)

Number Value:

         Integer:                      0|[1-9][0-9]*

         Double:                       (0|[1-9][0-9]*)\.[0-9]+

Bool Value:

         BoolValue:                 true|false

Char:

         CharValue:                 ‘(\\[^\r\n\t])|([^’\r\n\t])’

String:

         StringValue:               “((\\”)|[^\r\n])*”                                                                                       

Operators:

         Operator:                    =|\+|-|\*|/|%|^|(++)|(--)|(&&)|(\|\|)|(!)|<|>|(<=)|(>=)|(==)|(!=)

Seprators:

         Seprator:                    ;

 

以上就是脚本设计初稿,如果后面发现有错误,会去更正的。

按这个设计,写出来的程序大概是下面这样:

 1 int Foo(int value)
 2 {
 3    return value;
 4 }
 5 
 6 void main()
 7 {
 8    int a = 100;
 9    for(int i=0;i<100;i++)
10    {
11       --a;
12    }
13    if(a>0)
14    {
15       Foo(a);
16    }
17 }


基本上就是个没模板,没类,没指针的C++了。

设计就这样了,明天开始写词法分析喔!上面的Lexical Tokens就是给词法分析用的,因为代码是字符串,我们先要把整个字符串读成一个一个的Token,才方便进行语法分析和更深入的处理,比如
int a = 100;
要先拆成[type:int] [space] [identifier:a] [space] [operator:=] [space] [integer:100] [seperator:;]
这个过程就是词法分析了。

词法分析完了得出这些Tokens然后再匹配到

Variable Declaration:

type name [= expression];

才能建立起语法树来。
Lexical Tokens中是每种Token对应的正则表达式。

posted @ 2008-08-05 23:41 陈坤 阅读(1417) | 评论 (2)编辑 收藏

我早就想写一个脚本引擎了,真的。

事情可以追溯到大一的时候,很想做游戏(虽然后来发现美工成了最大的问题),于是自己写了一套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! 我会把我每个阶段的工作和工作原理都写在这篇日记中,有兴趣的朋友可以跟着一起玩玩喔!

posted @ 2008-08-05 08:46 陈坤 阅读(1962) | 评论 (5)编辑 收藏