学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解。
那么我们来分析下两位大神 次碳酸钴 和 Barret Lee 语法高亮实现。
先说 Barret Lee 的这篇 《几个小例子教你如何实现正则表达式highlight高亮》
之前看的时候只觉的神奇,特别是下面那个一步一步分开匹配的例子,更是霸气测漏,不过作者也说了,分开只是为了演示方便,可以很直观的看到这一步匹配了什么,不然一步到位匹配完成,你都不知道发生了什么就处理完毕了。
来看下他的正则
先来看一下大体的逻辑吧。
原文对最后一个 [\\S\\s] 的描述:我们必须匹配到每一个字符。因为它们都需要做一次HTML转义。
然后下面有详细的代码。
这是一篇非常不错的文章,我前前后后至少看了不下10次了,前两天才差不多完全明白。
不过这个代码还有一些小小的瑕疵,比如字符串不能匹配折行那种,字符串匹配优化。
还有数字匹配不够全面只能匹配 0xff, 12.34, 1e3 这几类,如 .123 12.3e+3 等格式都无法匹配到。
还有关键词顺序我觉得可以稍微优化下。
因为 传统型NFA 引擎的只是从左往右匹配,匹配到了就停止下一个分支的操作。
所以把最常出现的关键词放前面,可以提升一部分性能。
最后,最好是 new RegExp 这样对于代码量大的代码性能上会有所提升。
下面就给出我的正则和简单的demo吧。(其实只是对 次碳酸钴 源码的优化而已。。)
先来看正则部分:
合并了布尔和空值一个分组,然后优化了正则分组,所以比他减少了2个分组。
他 2,3 是字符串分组,因为 ([\"\']) 捕获了前面的引号,而我的正则没这么做。
这个 (true|false|null|undefined|NaN) 如果你不喜欢放在一个分组了,分开也行、
是不是同一个分组,只是为了区分着色而已。
sublime text 下 true|false|null|undefined|NaN 都是一个颜色,而 notepad++ 则只着色了 true|false ,我只想说 呵呵。
好了,差不多该给例子了。
我相信,不少人在看到这之前已经关掉了,或者只是拉了下滚动条然后关掉了。
不过我写这个就是为了给这些认真看下来的朋友,只要有一个人看,我觉得就不会白写了。
例子:
var num = 123;
var arr = [12, 12.34, .12, 1e3, 1e+3, 1e-3, 12.34e3, 12.34e+3, 12.34e-3, .1234e3];
var arr = [\"12\", \"12.34\", \'.12, 1e3\', \'1e+3, 1e-3\', \'12.34e3, 12.34e+3, 12.34e-3\', \".1234e3\"];
var arr = [/12\", \"12.34/, /\"12\\/34\"/];
for (var i=0; i<1e3; i++) {
var node = document.getElementById(\"a\"+i);
arr.push(node);
}
function test () {
return true;
}
test();
(function(window, undefined) {
var _re_js = new RegExp(\'(\\\\/\\\\/.*|\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/)|(\"(?:[^\"\\\\\\\\]|\\\\\\\\[\\\\s\\\\S])*\"|\\\'(?:[^\\\'\\\\\\\\]|\\\\\\\\[\\\\s\\\\S])*\\\')|\\\\b(true|false|null|undefined|NaN)\\\\b|\\\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\\\b|\\\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\\\b|(?:[^\\\\W\\\\d]|\\\\$)[\\\\$\\\\w]*|(0[xX][0-9a-fA-F]+|\\\\d+(?:\\\\.\\\\d+)?(?:[eE][+-]?\\\\d+)?|\\\\.\\\\d+(?:[eE][+-]?\\\\d+)?)|(?:^|[^\\\\)\\\\]\\\\}])(\\\\/(?!\\\\*)(?:\\\\\\\\.|[^\\\\\\\\\\\\/\\\\n])+?\\\\/[gim]*)|[\\\\s\\\\S]\', \'g\');
function prettify(node) {
var code = node.innerHTML.replace(/\\r\\n|[\\r\\n]/g, \"\\n\").replace(/^\\s+|\\s+$/g, \"\");
code = code.replace(_re_js, function() {
var s, a = arguments;
for (var i = 1; i <= 7; i++) {
if (s = a[i]) {
s = htmlEncode(s);
switch (i) {
case 1: //注释 com
return \'<span class=\"com\">\' + s + \'</span>\';
case 2: //字符串 str
return \'<span class=\"str\">\' + s + \'</span>\';
case 3: //true|false|null|undefined|NaN val
return \'<span class=\"val\">\' + s + \'</span>\';
case 4: //关键词 kwd
return \'<span class=\"kwd\">\' + s + \'</span>\';
case 5: //内置对象 obj
return \'<span class=\"obj\">\' + s + \'</span>\';
case 6: //数字 num
return \'<span class=\"num\">\' + s + \'</span>\';
case 7: //正则 reg
return htmlEncode(a[0]).replace(s, \'<span class=\"reg\">\' + s + \'</span>\');
}
}
}
return htmlEncode(a[0]);
});
code = code.replace(/(?:\\s*\\*\\s*|(?: )*\\*(?: )*)(@\\w+)\\b/g, \' * <span class=\"comkey\">$1</span>\') // 匹配注释中的标记
.replace(/(\\w+)(\\s*\\(|(?: )*\\()|(\\w+)(\\s*=\\s*function|(?: )*=(?: )*function)/g, \'<span class=\"func\">$1</span>$2\') // 匹配函数
return code;
}
function htmlEncode(str) {
var i, s = {
//\"&\": /&/g,
\"\"\": /\"/g,
\"\'\": /\'/g,
\"<\": //g,
\"<br>\": /\\n/g,
\" \": / /g,
\" \": /\\t/g
};
for (i in s) {
str = str.replace(s[i], i);
}
return str;
}
window.prettify = prettify;
})(window);
本文地址:https://www.stayed.cn/item/24557
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我