`
hax
  • 浏览: 949900 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JS解析测试代码片段

    博客分类:
  • JS
阅读更多
前一日与jindw聊天,谈到了正在研究的JS代码转换。譬如JSA所作的,其实就是一种代码转换。

PIES为了实现namespace(package)的管理,对JavaScript源代码也进行了处理。为了保证效率,所以想方设法只做了最最简单的预处理,也就是对代码段加头加尾,这样只是简单的字符串串接,对于效率是没有影响的。

但是最近在考虑是否有可能支持一些JS2(ES4)的特性,譬如支持let。这就必然需要将let转换为ES3所支持的某种结构(简单的说,在let语句开始的时候,把let的scope之外的同名变量先压栈,然后到了let的scope之外再恢复出来)。

总之这里就涉及到一种代码的transform或preprocessing。所以我在寻找某种轻型的代码解析方式。为此我先要写一些测试用例。

如果要进行JS代码的parse、transform、预处理、代码生成甚或compile等等,就需要考虑到JS的语法。以下是个很不完整的代码片段,parser、lint、preprocessor、transformer等等都需要能正确处理它,才具有实用价值。

function f(test) {
	
	return (test/*
	/* //
	' "
	{ ;
	\*/ && // /* // " ' { ; \
	test &&
	" /* // \
	\" ' \
	{ ;" &&
	' /* // \
	" \' \
	{ ;' &&
	test);
	
}

这个代码包含了多行注释、单行注释、字符串、多行字符串(非ES3标准,但各种引擎都支持)、转义字符等等。

这个代码没有包含的,包括正则和e4x。正则literal(如/^r(eg)ex["'\/].*?$/ig)是个很麻烦的事情,比如考虑除法!所以暂时没有放入测试用例中。e4x也是一个麻烦事情,因为涉及了内插XML,暂时不予考虑。

BTW,代码syntax highlight其实也会用到类似的处置,显然JavaEye的syntax highlight还是存在小小的地方不能辨识的,呵呵。

下面是一个正则表达式,可以匹配最常见的造成解析困难的嵌套结构,包括注释和字符串,但是没有包括前面所说的正则和e4x的xml结构。
/[/][*]([\S\s]*?)(?:[*][/]|$)|[/][/](.*)|"((?:\\"|[^"])*)"|'((?:\\'|[^'])*)'/g;


注:如果你看到上面的代码里存在奇怪的东西,那是JavaEye的bbcode解析错误。

通过这个正则,我们可以过滤一般的JS代码(当然正则和e4x除外)。比如可以把注释都删除,把字符串里的特殊字符替换掉等等。我测试了上面那段人造的代码。然后我拿dojo 0.4.3的314KB的源代码做了测试,完成整个过滤在我的T60笔记本上大概需要0.5秒。

不过因为还没有处理正则,所以这个方法还不能用于实用。
10
2
分享到:
评论
7 楼 Army 2008-04-13  
唔……发现不少问题呢,以前都没想到过……受教了~慢慢想想去~
6 楼 hax 2008-04-12  
To Army:
jssc2对于引号内的/*会识别为注释,所以我正文中的代码jssc2似乎尚无法正确高亮。jindw应该不会告诉你要分别处理,因为交叉问题是无法分别处理的,必须一揽子解决,或者采用Token解析方式。但是对于高亮这种用途来说,用Tokenizer代价过高,没有必要,恰好适合用我这里所描述的解决方案。代价是,对于少数极端情况会有高亮错误。
5 楼 Army 2008-04-11  
这个jindw曾和我说起过,交叉语法时会有问题,正则、字符串和注释中任意两个相互交叉的话有可能出现高亮错误。

jindw告诉我的是先将它们分开再进行着色,所以我写jssc2的时候就是受到他的启发的~
4 楼 hax 2008-04-11  
narcissus是一个完整的parser。所以它要用Tokenizer。这样开销还是相当大的。我其实想找一个用正则来做一种折衷处置的方式。

不过经过仔细研究,我发现正则literal是一个理论上难以解决的困境。因为是正则literal还是除法,要根据当时所处的语境(syntactic
grammar contexts)来决定,而不是只依据syntax的。考虑这样一个代码:

a = 1
b = 2
g = 1
c = a
/*

*/
/b/g


注意这里c实际为a/b/g(除法)。如果我检测到/b/g时,要回溯到之前的语境(包括跳过之前的注释)才能决定到底这是一个除法还是正则。这相当困难,因为JS中的正则不支持向前回溯。

不过在实践当中,几乎没有人会写出这样的语句:
- 跨行的除法
- 孤立的正则

所以可以考虑一种稍微严格的做法。目前正在思考中。
3 楼 trydofor 2008-04-11  
http://lxr.mozilla.org/mozilla/source/js/narcissus/
Brendan Eich's narcissus, a JavaScript parser written in JavaScript for the Mozilla project.
2 楼 hax 2008-04-10  
注,列表符号(以及正文中的<li>)应该是“[ * ]”(不包含空格)
1 楼 hax 2008-04-10  
BTW,在贴这个代码的时候发现一个小bug,即

/[/][*]([\S\s]*?)(?:[*][/]|$)|[/][/](.*)|"((?:\\\\|\\"|[^"])*)"|'((?:\\\\|\\'|[^'])*)'/


存在某种模式的代码,会匹配错误。不知有人能看出来么,呵呵。

相关推荐

Global site tag (gtag.js) - Google Analytics