最近我同事的朋友替公司做题目,这个题目是网上的,好像是一个什么Symbol公司出的题,是Symbol认证。因为这些题目都是关于.NET方面的,所以我同事让我帮她的朋友做。可是这些题目实在是太难了,我给一个比较经典的吧:
What’s true about types in C#?
|
|
|
a. |
The CTS only appropriate operations can be performed on a particular type |
|
|
|
|
b. |
The program will not compile |
|
|
|
|
c. |
The program will cause run-time error |
|
|
|
|
d. |
Every type in CTS is controlled |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
可惜我是丈二金刚摸不着头脑,types in C# 和 The program will not compile 有什么关系呢?注意这里没有任何的上下文,types in C# 不知道具体指的是哪一个范畴的,program也不知道是什么东西。更可怕的是,我觉得这里夹杂着一大堆的语法错误,我根本就看不懂。就像这里所说的program will not compile,感觉program是主语,也就是说program应该是指cs.exe这个compiler。那么宾语又是什么?
还没有看完这一份卷子,我就已经晕掉了。还有类似什么:
Which of the following is not a Boxing and unboxing rule?
|
|
|
a. |
An object can only be accessed in C# by its interface. |
|
|
|
|
b. |
The interface defines the rules how it can be accessed. |
|
|
|
|
c. |
The System.Object base class interface only accepts reference types. |
|
|
|
|
d. |
The System.Object base class interface accepts all available types of the CTS. |
|
|
|
|
e. |
Any variable of type value has to be converted to type reference. This process is called BOXING. |
|
|
|
|
f. |
Boxing happens automatically |
|
大家说说什么是System.Object base class interface?四个名词连在一起的效果就像我说“飞机花朵骨头云只能够看”一样,不知道是什么意思。难道应该有逗号在这几个词当中?也不像啊?也许这里的base是形容词,可还是看不懂什么叫做class interface。谁看得懂的教教我,说不定是我太长时间没有接触英语退化了。
还有下面这个题目也让我觉得很模棱两可:
Which of the following languages support objects?
a. C++
b. Microsoft Visual Basic
c. C#
d. A&B
e. A&B&C
f. A&C
g. No answer is correct
严格的说VB不支持OO,那是否supports objects就值得商酌了。大家觉得应该选择 e 还是 f 呢?
今天有一位MVP朋友问我是否想做MVP,我想了半天,还是觉得有机会就要尝试,失败了也没什么大不了的。所以最后决定要参加这么一次活动,虽然是自不量力,也要搏一搏啦!
如果说大家都能够来推荐我一下多好啊,可惜只能够由MVP来推荐。目前有两位MVP朋友推荐我,我已经感到非常的高兴了,但是我这个人不容易满足,所以特地来做一下广告,推销一下自己,看看会不会有其他MVP也来推荐我呢?
先来一个三句话的简短介绍:
1、我叫郑毅帆。
2、我之所以有勇气参选MVP,是因为我在.NET CF方面有一定的经验。
3、我参选MVP的目的是推销自己,如果当选了我一定发扬乐于助人的精神。
下面是我在MVP申请表格里面填写的自我简介:
大家好,我是郑毅帆,英文代号sumtec。无论在哪里看到sumtec,那么多半就是我本人了,尤其在中文网站里面。"Sum" for summary and "tec" for technology. Sumtec是我在初二的时候给自己命名的“代号”,为什么说是代号呢?因为这不是一个英文的人名,没有人叫这样奇怪的名字,不过我个人很喜欢这个代号。
在过去的一年多时间里面,由于公司开发一个PDA上面的行业应用,而我在这一家处于创业阶段的公司里面任研发部主管,因此该任务由我来负责。在进行一轮比较之后,操作系统决定选用PPC系列,并且用.NET CF进行开发。该方案的好处是,在PPC2k2到PPC2k3之间能够进行完全无缝的“升级”,有利于日后选择不同厂家的硬件,使得我们在选择上游厂家的时候,处于更有利的地位。在几个月之前该项目的开发已经完成,目前已经转入市场销售阶段。在整个开发过程当中,对于.NET CF的不少细节问题都有了比较深入的了解。例如在SP2之前,应用程序启动速度比较慢,这是由于.NET CF设计疏漏造成的效率问题。而这个问题可以通过将部分源代码修改成另外一种等价形式来解决,但是手动修改任务非常繁重,为此我还专门开发了一个自动修改源代码的工具,用于专门解决这一个问题。
当然,我在接触.NET CF之前,对于.NET也已经非常的熟悉了。跟.NET的接触可以说是从VS2k2的Alpha版就开始了,当时由于国外黑客泄露了一份Alpha版,有幸接触到这个产品。但正是接触是在Beta1开始的,甚至在这个版本上面已经写了不少个人的应用(非商业的),因此当年在CSDN上面解答其他人问题的时候,经常能够判断出别人使用的书籍是根据Beta1版本来编写的,标志就是某些命名空间有区别,例如Winform这个命名空间。
而更早之前则是使用的QB/VB系列,这些工具时常能勾起我往事的回忆。我总难以忘怀用QBX开发一个“淡入淡出”效果的库,更难以忘记当年试图在QB上面模拟消息机制以及Windows那样的UI。不过我这个人对于不常使用的东西忘记得也特别快,以便于记住最新的知识。因此如果你现在问我VB的问题,那么恐怕我已经不能够给你很精确的答案了。VB至少有四五年没有使用了,QB就更不要提了。
大家也许发现了,我从很早之前就已经开始学习编写计算机程序了。确切的说,我是从小学4年级下学期的时候就开始了这个漫长的计算机学习历程。并且在中学的时候参加了NOI,也就是全国奥林匹克信息学竞赛,除了第一次拿了市三等奖之外,每次都拿到市一等奖,甚至有省一等以及全国一等。不过这些都是分区联赛的成绩,而说到竞选省队参加全国决赛则一次都没有,每次都是差一名进不去。我对这个感到些许遗憾,但是并不后悔,因为那是我的性格使然——我对于不解决实际问题的东西非常不感兴趣,竞选之前不愿意做充分的准备也就是一件必然的事情了。
上面提到了CSDN,这个社区什么时候加入的我都很模糊了,大概是在2000年左右吧。后来还申请当上了VB.NET的版主,为很多朋友解答过不少问题。到目前为止我在CSDN上面已经累积到15112分的专家分,其中14486分都是属于.NET板块的记分。当然这个分数并不高,想比许多高手,我这个分数也许只有几分之一到几十分之一,但至少表明我也帮助过不少的朋友们。更何况我对于分数这样的东西并不在意,能帮助别人才是最重要的。不过最近到CSDN上面的次数已经比较少了,因为我最近有一些私人事务需要处理,此外还着迷于另外一种媒体——Blog。现在维护着两个个人的Blog——http://blog.joycode.com/sumtec以及http://www.cnblogs.com/sumtec。这两个Blog实际上内容基本上一致,因为有幸受到双方的邀请,所以两边都留下来了。
说到Blog,其实这也是一个能够帮助别人的地方。把自己的心得体会写下来,供他人参考,有时候比回答别人的问题更加有效果,因为回答问题的方式也许只有提问的人才能够得到答案,但是在Blog上面所有对他感兴趣的人都能够获得满意的答案。我个人就在blog上面得到了很多帮助,同时现在我也在尽量利用Blog记录下个人的一些经验知识以及成果,希望能够帮助其他人。欢迎大家经常光顾我个人的Blog,并提出您宝贵的建议。对于我个人来说,是否能够当上MVP并不重要,我更希望能够通过这次活动展现自我。当然,如果能够当选,我会感到无限荣幸。谢谢大家对我的支持!
Ninputer问我这个是干什么的。实际上很多人都问过我这个问题,甚至dudu也问过,甚至还有人因此对这个东西有误会。这个怪我,没有说清楚。今天我就来给大家说明白这个事情。
这个NfaGen2是用来产生复杂正则表达式的,比如如果我在NfaGen2里面这么写:
ws:\s
#_SemiColon:;
#_IdHead:a-zA-Z_
#_IdTail:0-9<IdHead>
_Id:<IdHead><IdTail:any>
Type:<Id>
Name:<Id>
SimpleDefine:<Type><ws:many><Name><SemiColon>
那么SimpleDefine就会生成:
(?<SimpleDefine>(?<Type>[a-zA-Z_][0-9a-zA-Z]*)\s+(?<Name>[a-zA-Z_][0-9a-zA-Z]*))
你觉得是上面那种写法(NfaGen2)比较清晰呢,还是下面这种写法(Regex)清晰?我觉得如果我看到
SimpleDefine:<Type><ws:many><Name><SemiColon>
我就知道SimpleDefine匹配的是一个类似
类型 名称;
这样的字符串,至于类型(Type)是什么东西,我再找Type的定义好了。现在给出的这个例子已经足够简单了,如果我们需要产生比较复杂的正则表达式的时候,区别就更大了。
如果让你直接看或者写标准的正则表达式,估计光是括号对齐就已经让你头痛不已,甚至有时候你需要搞清楚某一个“捕获组”到底捕获了一些什么,这个时候会非常头痛。如果这个表达式本身需要匹配各种括号,那就更加麻烦了,比如我要匹配类似(a+(a+a)+(a))这样的表达式,你觉得用Regex要怎么写呢?
(?>(?<=\(|[+]|\A)(?<left>\()(?=[a-zA-Z_]|\()|(?<=[0-9a-zA-Z_]|\))(?<right-left>\))(?=[+]|\)|\z)|(?<=\(|[+]|\A)(?<var>(?<id>[a-zA-Z_](?:[0-9a-zA-Z_])*))(?=\)|[+]|\z)|(?<=\)|[0-9a-zA-Z_])(?<operator>[+])(?=\(|[a-zA-Z_]))+
如果我不告诉你这个正则表达式就是用来匹配这样的字符串的,你自己能够看得懂这个表达式的作用吗?如果你声称能够看得懂,我再来问你,你说说看捕获组left捕获的内容是什么?var组呢?还有它能够接受那些运算符呢?上述这个式子你如果自己来写的话,要花多少时间才能够写正确呢?如果我现在给你这么一个正则表达式,我要求你修改成能够接受加减乘除这四个运算符,你要花多少时间来修改这样一个表达式呢?
大家再来看看,下面这些就是我用于产生上面那个正则表达式的NfaGen1的源代码(NfaGen2的格式跟这个差不多):
_root:(?><_leftPart>|<_rightPart>|<_varPart>|<_operatorPart>)+
_leftPart:<_left_start><left><_left_end>
_rightPart:<_right_start><right-left><_right_end>
_varPart:<_var_start><var><_var_end>
_operatorPart:<_operator_start><operator><_operator_end>
_left_start:(?<=<_left>|<_operator>|\A)
left:<_left>
_left_end:(?=<_id_head>|<_left>)
_right_start:(?<=<_id_tail>|<_right>)
right-left:<_right>
_right_end:(?=<_operator>|<_right>|\z)
_var_start:(?<=<_left>|<_operator>|\A)
var:<id>
_var_end:(?=<_right>|<_operator>|\z)
_operator_start:(?<=<_right>|<_id_tail>)
operator:<_operator>
_operator_end:(?=<_left>|<_id_head>)
id:<_id_head><_id_tail>*
_id_head:[a-zA-Z_]
_id_tail:[0-9a-zA-Z_]
_left:\(
_right:\)
_operator:[+]
虽然长了一点,不过看完第一行已经知道大概是什么样的了,而要接受加减乘除四个运算符,只需要修改最下面那一个_operator,变成[-+*/]就可以了。如果你直接修改正则表达式,你可能就会漏掉了检测左括号前面的合法字符的那部分,以及其它的你没有注意到的地方,结果没有办法完全正确的匹配,甚至你不知道问题出在什么地方。
用上述方法定义的时候还有一个好处,就是你可以进行局部的匹配测试,看看局部的正则表达式是否书写正确。例如你可以测试_leftPart,测试的内容包括:
(
(a
a(a
a(+
+(a
+(+
+()
((a
)(a
看看对于左括号的匹配是否正确。如果你直接从标准的正则表达式上面进行类似的提取,是非常困难的一件事情,你必须数一下有多少个"("以及")",中间还得提防"\("和"\)"这样的被转义了的字符。
上面这个表达式还是很简单的,如果你看看NfaGen2用于进行语法加亮的表达式,你会剧烈的头痛得,像那种几K级别的正则表达式,要对某一个局部提取,进行上面那种局部测试,简直就是异想天开!
好了,说到这里不知道大家是否明白了NfaGen2的作用了呢?如果还是不明白,那表明我表达得不够清晰,或者漏了什么内容,我会再找时间来给大家解释的。谢谢大家的支持。
点击这里下载(请首先看完下面的说明后再继续使用)
预览画面:

说明:这个只是一个概念演示版本,仅仅演示“自动着色”功能,目前没有任何的存盘功能和智能提示等功能。并且还有一部分的着色没有完成,没有完成的部分将在下一个版本里面看到。目前大家可以做的是,看看这个自动着色器的速度和效果。关于速度,日后会有一定的优化,不过可能并不会比目前快超过一个数量级。
在这个压缩文件包当中有一个后缀为NGARPT的文件,这个文件是必须的,不能够删除,并且必须和EXE文件放在同一个目录下面。该文件的内容就是对上面那个文本框内部输入的字符进行分析的正则表达式内容,其中第一行(不包括自动换行)的内容是语法分析,第二行是用于找出“语句”的分隔点,以便进行局部分析(而不是耗费时间的全局分析)。
上图中,右边的方框用于演示如何“暂停”RichTextBox的刷新,点击Begin之后将会暂停(用其它窗口覆盖在这个文本框上面再拿开就可以看到效果了),点击End的次数等于点击Begin的次数将会恢复刷新。下面这部分是计划当中的“头文件”,有兴趣可以看一下:
/ File name:?? Version2.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
/ This file defines the version of the TXN file to version 2.
/ This will enable the version 2 syntax.
/ These lines defines the version.
@ifdef version
@warning "Version is already defined in file {1} at line {2} as Version \"{0}\"." version version.File version.Line
@endif /version
@version 2.0
/ File name:?? Version.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
/ This file defines the version of the TXN file to version 1.
/ \ will turns into
@ifdef version
@ifdef version
@warning "Version is already defined in file {1} at line {2} as Version \"{0}\"." version version.File version.Line
@endif /version
@version 1.0
/ File name:?? Options.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
@option trace >
@option capture ?
@option regex "is-x" / This is incorrect!
/ File name:?? Symbols.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
@ifndef _Symbols_Defined
@define _Symbols_Defined
@sealcapture begin
#_cBacklash:\
#_cRegexEscape:
#_cLeftRoundBracket:(
#_cRightRoundBracket:)
#_cLeftSquareBracket:[
#_cRightSquareBracket:]
#_cLeftPointBracket:<
#_cRightPointBracket:>
#_cLeftCurlyBracket:{
#_cRightCurlyBracket:}
#_cPipeline:|
#_cColon::
#_cSemiColon:;
#_cComma:,
#_cDot:.
#_cExcalmatoryMark:!
#_cQuestionMark:?
#_cAsterisk:*
#_cPlus:+
#_cMinus:-
#_cEqual:=
#_cUnderline:_
#_cEmailAt:@
#_cSharp:#
#_cDollar:$
#_cPercentage:%
#_cUpPoint:^
#_cAndMark:&
#_cSlash:/
#_cDoubleQuote:"
#_cSingleQuote:'
@sealcapture end
@endif / _Symbols_Defined
/ File name:?? Operators.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
@ifndef _Operators_Defined
@define _Operators_Defined
@include Symbols.txn
@sealcapture begin
_m_cStart:
_m_cEnd:
_m_cInverse:
_m_gStart:
_m_gEnd:
_m_gOr:
_m_dStart:
_m_dDefine:
_m_dEnd:
_m_rFrom:
_m_rTo:
_m_Repeat:
_m_somethingLazy:
_m_lazyRepeat:<_m_Repeat><_m_somethingLazy>
_m_any:
_m_many:
_m_one:
_m_lazyAny:<_m_any><_m_somethingLazy>
_m_lazyMany:<_m_many><_m_somethingLazy>
_m_lazyOne:<_m_one><_m_somethingLazy>
@sealcapture end
@endif / _Operators_Defined
/ File name:?? Escapes.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
#_escape_Operator:
#_escape.Char:<_escape_Operator><_escape_Operator>
@ifndef _Escapes_Defined
@define _Escapes_Defined
@include Symbols.txn
@sealcapture begin
#_Escape:
#_EscapeMark:<_Escape><_Escape>
#_lrBracket:<_Escape>
#_rrBracket:<_Escape>
#_lsBracket:<_Escape>
#_rsBracket:<_Escape>
#_lpBracket:<_Escape>
#_rpBracket:<_Escape>
#_Dot:<_Escape><_cDot>
#_Asterisk:<_Escape><_cAsterisk>
#_PlusSign:<_Escape><_cPlus>
#_Question:<_Escape><_cQuestion>
#_Pipeline:<_Escape><_cPipeline>
#_MinusSign:<_Escape><_cMinus>
#_UpPoint:<_Escape><_cUpPoint>
@sealcapture end
@endif
/ File name:?? Base.txn
/ Create time: 2004-07-23
/ Creator:???? sumtec
@include Version2.txn
@include options.txn
@include operators.txn
@include escapes.txn
@include spaces.txn
这个Post只是预告一下“吊胃口V”可能发布的内容,是一个预告。
首先发扬一下吊胃口的精神,给大家看看目前NfaGen的工作成果:

上面这个图是NfaGen2的雏形,上面的代码着色是程序自动完成的。不过目前着色也没有完全昨晚,比如定义后面部分的字符就没有进行着色。目前NfaGen2的语法分析用的正则表达式基本上已经稳定下来了,一般来说错误已经很少了,但是还有一些已知的错误存在,也有一些不足的地方需要调整。这个正则表达式的长度目前已经达到了惊人的5,009个字符了,估计还要继续增加一点。
那么我准备在“吊胃口V”里面给大家说些什么呢?就讲讲我是怎么进行这个着色工作的。其时不要小看这个着色步骤,如果你用RichTextBox就会发现有各种各样的问题:
1、要对某部分的颜色字体进行改变,就需要设置SelectionStart、SelectionLength,然后修改SelectionColor、SelectionFont。但是在此过程当中,你会发现编辑框会闪烁——你选中的部分会变蓝然后再变回来。
2、如果你打算使用一个RichTextBox作为后台着色的工具,那么你会发现如果文本内容太多,也会出现闪烁——首先闪现最开始部分的内容,然后再显示你正在编辑的部分。
3、你还会发现,如果你输入的速度太快了,就可能出现错误,比如你输入"asdf",结果却显示"asfd",并且光标停留在f和d之间,或者出现其他类型的错误(尤其是你打算用多线程的话)
4、你打算怎么进行代码分析着色呢?把文本框里面的所有内容都重新分析并着色一遍?如果是这样的话,你会发现内容多到一定程度的时候就会非常的迟钝了。假如你采取只分析最近修改的那一两行的办法,那么如果你Paste一段文字进去的话,你打算怎么处理呢?
大家觉得“吊胃口V”说这个内容OK不OK啊?我希望在正式发布“吊胃口V”之前先把大部分的Bug修正了,并且能够完全着色。好,不多说了,继续改Bug,早改完早发布。
[abc] 表示匹配abc这三个字符当中的任意一个;
[^abc] 表示匹配abc这三个字符之外的其它字符;
a|b 表示匹配a或者b;
我来请教大家:
[^a]|[b]
应该会匹配什么呢?
[d]|[^d]
又应该匹配些什么呢?
请大家先不要测试,直接写出答案,然后再把测试之后的结果也写出来。大家分析一下,这是不是一个Bug呢?
其实我这个问题是因为,我想匹配除了“符号”和“空白字符”之外的所有字符,但是同时允许匹配下划线"_"(这个也属于字符),因此我不得不这么写:
[_]|[^\s\p{S}\p{P}]
结果却发现完全不是这么一回事,我觉得这个实际的匹配情况不符合逻辑,好像是一个Bug。当然,上面那一个例子也许应该写成:
[_\S\P{S}\P{P}]
这样更加正确。
(顺便透露一下,上次那个1725字符的表达式,先经过几次缩减变成14xx,然后再经过几次迅速膨胀,现在变成3xxx了,估计还要稍微小胀一点点。这个用于分析词法的正则表达式已经差不多构造好了,虽然似乎没有人用正则表达式匹配来分析词法的(基本上用DFA的比较多),不过我觉得用Regex也不是完全不可能的,就让我来证明一下吧。)
如果可能的话:
1、页面上应该显示阅读次数,好跟别人比较一下,看看自己的差距在哪里。
2、那个自动转变表情的功能是不是可以关掉?感觉有点不方便,经常在贴代码的时候会被自动转换成一个笑脸,一瓶啤酒,只好到Html里面修改,非常不方便。
3、管理页面的“随笔”、“文章”和“反馈”等,应该能够点击标题,直接进入该页面,例如:
这样发布/修改好了,可以直接点击进去看看效果,或者直接从“反馈”那个页面,点击想要回应的回复标题,就可以进入相应的Post直接回复,等等。
4、是不是可以增加一个限制文章长度的功能,太长了部显示在首页,只显示一个“详情点击查看”的超链接,大多数的超长Post都不会写摘要的,懒惰是Developer的天性。
5、登录的时候,可不可以直接按回车进去啊。现在的方法要多按一下TAB或者用鼠标,不太符合习惯。
6、管理页面最上面那个.TEXT的图标是不是可以换成博客堂的?链接也接到博客堂的首页吧!不然从管理界面想要到博客堂首页,中间要经过一个自己的首页才能到达(或者手动在地址栏里面填写),哎呀,没办法,懒是我们的天性啊。
我也是随便说说的,老大抽空升个级已经不容易了,上面那些简直就是奢求啊,忙的话就算了。本来我想回复到开心的那个提问题的Post里面去的,可是那里面似乎都是类似Bug之类的东西,好像有点不搭界……
不好意思啊各位,不是存心给大家卖关子的。因为我的确还没有完成,只是阶段性的成果,所以只能够一点一点给大家挤牙膏了。
我记得第一次最后给大家看了一个图片,左边那部分可以从大量的“单词”当中,找出符合前面已经输入的那一部分的那些单词。这个是一个自己写的类(从头到脚都是自己写的,除了书组和基本的类型,没有用其它的集合类型),在上一次已经初步完成了,但是今天不准备给大家放出来(还得继续吊着
),因为:1、还没有完成(测试);2、功能还有待调整。其实很明显,第二次吊胃口所放出来的代码,就是为了解决将搜索到的单词,以“智能提示”下拉框的方式显示出来并允许选择的问题。
那么这一切又一切的工作又是为了什么呢?呵呵,为了写一个超强的正则表达式构造器!嗯,大家一定记得上一次我给大家提供过一个alpha版的正则表达式构造器吧?虽然说挺好用的,但是里面有一些隐藏得我都不知道在哪里的Bug存在,还有一些结构不合理的地方(包括代码),以及还是不是非常顺手。所以我决定推倒重来,做一个全新的,非常好用的正则表达式构造器!
目前这个东西还处于非常核心的地方,没有任何可以看得见的效果存在,但是我可以给大家模拟一下主编辑区的效果,主要是给大家看一下我设计的语法:
/ Comment: This is a sample code acceptable by NfaGen2
/ Attn: This is only a SAMPLE, might not be acceptable in final release version.
/ Sample create: 2004-07-21
/ Creator: Sumtec
/ Option Syntax:
/ @OPTIONNAME OPTIONAME...
/
/ The following option means (?>...|...)
/ The opposite option should be: (which means (?:...|...) )
/ @option trace on
/ This option might not be supported
@option trace off
/ Define Syntax:
/ (>|:)?#?(\?|_)?NAME\.ALIAS:CONTEXT
/ >|: means (?>CONTEXT) or (?:CONTEXT), it will ignore the @option trace.
/ # means the definition here is a character set, or we say it's “[CONTEXT]”
/ ?|_ means it is a “captured replace” or “pure replace”, or we say:
/ (?<NAME>CONTEXT) or CONTEXT
/ If (?|_) is omitted, it will determine by @option capture which defaults to “caputure replace”
/ .ALIAS is not a part of capture name in RegEx, but a part of definition name in NfaGen2
/ Some times we need to capture different context by the same capture groupname, .ALIAS provide
/ a way to get two or more different captures a same name.
/ Here gives you a full sample:
/ This sample will match the following text:
/ ABCD 0123 0123
_ws:\s
_EndString:\Z
#_word:a-zA-Z
#_number:\d
#Invalid.Word:^<_word>
#Invalid.Number:^<_number>
Word:(?><_word>|<Invalid.Word>)+
Number:(?><_number>|<Invalid.Number>)+
_Root:<Word>(?><_ws:many><Number@FirstNumber>(?><_ws:many><Number>)*)?
/ NfaGen2 will compile _Root into the following RegEx expression:
/ (?<Word>(?>[a-zA-Z]|(?<Invalid>[^a-zA-Z]))+)(?>\s+(?<FirstNumber>(?>\d|(?<Invalid>[^\d])))
/ (?>\s+(?<Number>(?>\d|(?<Invalid>[^\d])))*)?
/
/ I inserted line break for reading more easier.
/ There should not be any line breaks in the NfaGen2 generated expressions.
/ You might find optimization, for example: [\d] is optimized into \d
/ And you can see that <Number@FirstNumber> is redirected to (?<FirstNumber>...).
/ It is an example of the @ operator which can only be used in Context part.
呵呵!是不是比较酷呢?如果对格式有什么疑问或者建议,大家尽可以回复,谢谢支持!(看在我这么辛苦的进行手动着色,没有功劳也有苦劳的份上,多多支持哦!)
最后还是忍不住要说一下,上一次的Post里面提到我用那个alpha版的正则表达式构造器所产生的最长的表达式有七百多个字符,今天早上被我打破了,而且仅仅是一个上午的时间!这一次为了进行上面那个语法分析,目前已经有1,725个字符了,而且很可能要继续变长,因为目前对于CONTEXT部分还没有任何的分析。
我把这个正则表达式给大家,大家可以试一下匹配上面的Example,看看是否能够正确匹配:
(?>(?<Comment>/(?<CommentText>[^\n]*))|(?<Option>@(?<OptionName>(?>(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n]))|(?<OptionNameHead>[^0-9\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<OptionNameReject>[^>:\.@\r\n\s]))(?:[^\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<OptionNameReject>[^>:\.@\r\n\s]))*(?:(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n])))?))(?>[\f\t\v\x85\p{Z}]+(?<OptionName>(?>(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n]))|(?<OptionNameHead>[^0-9\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<OptionNameReject>[^>:\.@\r\n\s]))(?:[^\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<OptionNameReject>[^>:\.@\r\n\s]))*(?:(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n])))?))?)*[\f\t\v\x85\p{Z}]*)|(?<Define>(?<DefineGroupName>(?<TraceSelect>(?<ForceTrace>:)|(?<ForceNotTrace>>)race>)?(?<Char>#)?(?<GroupCapturePrefix>(?<ForceCapture>\?)|(?<ForceNotCapture>_))?(?<Groupname>(?>(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n]))|(?<NameHead>[^0-9\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<NameReject>[^>:\.@\r\n]))(?:[^\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<NameReject>[^>:\.@\r\n]))*(?:(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n])))?))(?:\.(?<Alias>(?>(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n]))|(?<NameHead>[^0-9\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<NameReject>[^>:\.@\r\n]))(?:[^\s\p{S}\p{Pe}\p{Pd}\p{Pf}\p{Pi}\p{Ps}\p{Po}]|(?<NameReject>[^>:\.@\r\n]))*(?:(?<![\f\t\v\x85\p{Z}])[>:\.@](?<InComplete>(?=[>:\.@\r\n])))?)))?(?<RejectDefineName>>[^:\r\n]*)?)(?>(?<DefineInComplete>(?<!\G)(?=[\f\t\v\x85\p{Z}]*[\r\n]|\Z))|:(?<DefineLine>[^\n]*)))|(?<RejectLine>[^\n]+)|)[\f\t\v\x85\p{Z}]*(?>[\r\n]|\Z)
注意:中间没有任何的空格和回车!最后也没有回车(这个千万注意)!
我想大家用VS.NET的时候一定对那个智能提示印象深刻,如果你仔细看看,你就会发现那个智能提示的下拉框实际上是在整个VS.NET IDE的外面的。比如说,如果你把VS.NET IDE变成不是最大/小化的时候,在编辑区的最下方调出只能提示下拉框,并且在屏幕下方留有足够的空间,你就会发现那个下拉框竟然申到VS.NET IDE的外面了!
第一印象你一定会觉得那个是一个FormBorderStyle为None的一个Form上面放了一个ListBox所实现的效果,可是如果你自己来试一下,就会发现有一个大问题:
就是当你选中ListBox上面的内容的时候,主窗口就会失去焦点,标题就会灰化!感觉很不爽吧!
你可以尝试SetTopLevel、Owner、Parent……结果都不行吧!呵呵,不要说上面那几个公开的东西了,甚至我用Reflection手动设置state,并且使得Owner和Parent同时指向主窗口,都无济于事(主窗口甚至变成无效的)。
然后大概你会想到,菜单好像也可以延伸到所属窗口的外边,可是很不幸的是,至少我没有找到可以把一个控件放到菜单上面的方法。我甚至考虑过自己去OwnerDraw,但是有一点让我放弃了:
如果你在VS.NET IDE探出智能提示下拉框的时候,移动主窗口,就会发现那个下拉框也会跟着移动。可是菜单,对不起,点击非菜单部分就会使菜单消失,跟不要说去移动它了。
最后,千辛万苦(也就半天时间),终于给我搞定了,看图:

哈哈!我要卖关子喽,怎么做的现在先不说,回复的人多了我再说(其实是现在还不是做得很通用,我想做的通用了再发布出来)。呵呵!
不过我可以透露一点点:实际上确实是用FormBorderStyle为None的Form来实现的,不过需要主窗口截获一个WM_NCACTIVATE消息,进行一定的处理,就能够得到这个效果了。
(不知道有没有人注意到左边的ListBox显示的是什么呢?还要卖一个关子……)
贝利战绩: 90年,他看好南斯拉夫队当黑马,第一场就被德国干了1:4。 92年,他继续看好南斯拉夫队,结果南被禁赛。 94年,他看好哥伦比亚当黑马,结果哥伦比亚小组被淘汰,后卫被枪杀。 96年, 说过土耳其看好,结果土耳其立马就被淘汰。 98年,决赛前他看好巴西队,巴西队以历史最大惨败输了世界杯。 98年,小组赛结束狂看好尼日利亚, 结果好好的尼日利亚,淘汰赛第一轮就回家了。 98年,贝利看好西班牙成为黑马,结果西班牙小组都没出线。 02年,他看好阿根廷和法国队,结果双双小组毙命。 02年,英格兰3:0干掉丹麦之后,贝利预言英格兰拿冠军,结果下一场被巴西干掉。 04年,他在葡英赛前极力看好鲁尼和英格兰,结果鲁尼立刻受伤下场,英格兰点球落败。 最狠的是,20多年前,贝利访问中国,说你们很快就能进入世界杯,结果中国队苦苦挣扎了20年。
不知道大家有没有想过这一个弱弱的问题?反正我想过了,并且在一段时间里面百思不得其解。
那些成对的运算符,为什么非要成对的进行定义呢?eg:
A>B 难道不应该等于 !(A<=B)吗?A==B难道不应该等于!(A!=B)吗?
也就是说,为什么不能够简单的只定义<、= 两个符号就能够得到其他几个符号的定义呢?
> -> !(< || ==)
>= -> !(<

<= -> < || ==
!= -> !(==)
如果觉得要引入||不好,顶多再定义一个<=就够了。也许多了一个非操作,影响效率。但是一个非操作在普通情况下并不会造成多大的性能影响,至少如果我只定义了<和==没有定义>和!=,编译器也应该能够自动产生相应的函数啊。产生一个编译错误是在让人头痛,因为不得不做一些重复性的劳动。
最后我在float.IsNaN函数里面找到答案了:原来判断a是不是NaN的办法是通过 a<0 || a>=0 来得到的,如果这个式子为真,那么就不是NaN,否则就是NaN,真是非常让我感到意外。也就是说,a>=0 并不等价于 !(a<0) ,对于NaN来说,a<0是false,a>=0也应该是false,但是!(a<0)却得到true了,而不是a>=0的false。
不过再怎么说,我还是认为如果我没有成对的定义某些运算符,系统应该尽可能帮我自动生成,然后给出一个警告。比如定义了<、==两个符号,就应该可以得到其他的>、>=、!=、<=了,然后给出一个警告,这样比编译错误要舒服许多,有时候根本不想追求性能,只想尽快完成的时候,就可以偷个小懒了,何况一个“非”运算根本就不是什么大问题,甚至很可能被优化掉。
先问大家一个问题:objA == objB 和 objA.Equals(objB) 是否等价?答案显然是要看具体情况,或者说很可能是不等价的。
可是如果我这么问呢?
对于定义float A, B;
A == B 是否应该和 A.Equals
完全等价呢?应该是的吧?也许大家的答案有下列几个之一:
1、Equals通常用于在==运算符重载的时候,比较引用是否相等。
2、Equals通常用于比较引用类型的引用是否相等。
float没有运算符重载,也不是一个引用类型,甚至我也看不出有什么必要让Equals和==表现得不一样。然而我却发现这两个方法是不完全等价的!注意,我这里讨论的是A、B都是float的情况下。那么什么情况下不一样呢?当A和B都是float.NaN的情况下,==会得出false的结论,Equals会得出是true的结论。
这下子我就懵了,为什么要这样呢?按照数学定义来说,NaN之间的比较应该是false才对,因为“非数字”之间的比较是无意义的,更不可能相等啊。也许Equals想要表达的是,他们从二进制的角度上来说是相等的——两者都是非数字。