`
jindw
  • 浏览: 500780 次
  • 性别: Icon_minigender_1
  • 来自: 初到北京
社区版块
存档分类
最新评论

脚本全局变量探测程序

    博客分类:
  • JSI
阅读更多
为了支持JSI包定义中的模式匹配(方便某些懒人)。我需要一个查找脚本全局变量的脚本。

一直没有勇气编写JS的完整语法解析程序,所以,只能走一些旁门左道。

/*
 * JavaScript Integration Framework
 * License LGPL(您可以在任何地方免费使用,但请不要吝啬您对框架本身的改进)
 * http://www.xidea.org/project/jsi/
 * @author jindw
 * @version $Id: fn.js,v 1.5 2008/02/24 08:58:15 jindw Exp $
 */


/**
 *
 * @param <String> source 脚本源文件
 * @return <Array> 改脚本中的定层申明变量(包括函数)
 */
function findGlobals(source){
    source = replaceSpecialEntry(source.replace(/^\s*#.*/,''));
    //简单的实现,还以为考虑的问题很多很多:
    var varFlagMap = {};
    var scopePattern = /\b(function\b[^\(]*)[^{]+\{|\{|\}|\[|\]/mg;//|{\s*(?:[\$\w\d]+\s*\:\s*(?:for|while|do)\b|""\:)
    //找到办法不用判断了,省心了。。。。
    //var objectPattern = /\{\s*(?:[\$\w\d]+|"")\:/mg
    var varPattern = /\b(var|function|,)\b\s*([\w\$]+)\s*/mg;
    //var lineParrern = /([\$\w]+|[^\$\w])\s*[\r\n]+\s*([\$\w]+|[^\$\w])/g
    var buf = [];
    var fnDepth = 0;
    var arrayDepth = 0;
    var begin = 0;
    var match;
    while(match = scopePattern.exec(source)){
        switch(match[0] ){
        //array
        case '[':
            if(!fnDepth){
                if(!arrayDepth){
                    buf.push(source.substring(begin,match.index),'[]');
                }
                arrayDepth ++;
            }
            break;
        case ']':
            if(!fnDepth){
                arrayDepth --;
                if(!arrayDepth){
                    begin = match.index+1;
                }
            }
            break;
        //function
        case '{':
            if(!arrayDepth && fnDepth){//in function
                fnDepth++;
            }
            break;
        case '}':
            if(!arrayDepth && fnDepth){//in function
                fnDepth--;
                if(fnDepth == 0){
                    begin = match.index+1;
                }
            }
            break;
        default://function..
            if(!arrayDepth){
                if(!fnDepth){
                    buf.push(source.substring(begin,match.index),match[1],'}');
                }
                fnDepth++;
            }
            break;
        }
    }
    buf.push(source.substr(begin))
    source=buf.join('');
    source = source.replace(/([\w\$\]])\s*\([\w\$\d,]*\)/m,'$1()');
    begin = 0;
    while(match = varPattern.exec(source)){
        switch(match[1]){
        case 'var':
            begin = match.index;
        case 'function':
            varFlagMap[match[2]] = 1;
        default://,
            var next = source.charAt(match.index + match[0].length);
            if(next!=':'){
                var temp = source.indexOf(';',begin);
                if(temp>0 && temp<match.index){
                    continue;
                }
                try{
                    //不知道是不是还有什么问题
                    temp = source.substring(begin,match.index);
                    //if(/var|if|else/.test(temp)){continue;}
                    temp = temp.replace(/[\r\n]/g,' ');
                    new Function(temp+',a;')
                }catch(e){
                    continue;
                }
                varFlagMap[match[2]] = 1;
            }
        }
    }
    var result = [];
    for(match in varFlagMap){
        result.push(match)
    }
    return result;
}
/**
 * java 接口
 * @param <String>source 脚本源码
 * @return java.util.Collection 返回全局id集合
 */
function findGlobalsAsList(source){
    var result = findGlobals(source)
    var list = new java.util.ArrayList();
    for (var i = 0; i < result.length; i++) {
        list.add(result[i]);
    }
    return list;
}

var specialRegExp = new RegExp([
            //muti-comment
            '/\\*(?:[^\\*]|\\*[^/])*\\*/',
            //single-comment
            '//.*$',
            //string
            '"(?:\\\\(?:.|\\r|\\n|\\r\\n)|[^"\\n\\r])*"',
            "'(?:\\\\(?:.|\\r|\\n|\\r\\n)|[^'\\n\\r])*'",     
            '/.*/'
          ].join('|'),'m');

function replaceSpecialEntry(source){
    var head = '';
    var tail = source;
    var p1
    outer:
    while(p1 = specialRegExp.exec(tail)){
        var p2 = p1.index + p1[0].length;
        var p1 = p1.index;
        if(tail.charAt(p1) == '/'){
            switch(tail.charAt(p1 + 1)){
                case '/':
                case '*':
                    head += tail.substr(0,p1);
                    tail = tail.substr(p2+1);
                    continue outer;
            }
            try{//试探正则
                new Function(head+tail.replace(specialRegExp,"/\\$&"));
                //是正则
                p2 = p1;
                while((p2 = tail.indexOf('/',p2)+1)>p1){
                    //println([p1,p2]);//,tail.substring(p1,p2)
                    try{
                        var text = tail.substring(p1,p2);
                        if(/.*/.test(text)){//有效正则
                            new Function(text);
                        }
                        head += tail.substr(0,p1)+"/./";
                        tail = tail.substr(p2);
                        continue outer;
                    }catch(e){
                        //无效,继续探测
                    }
                }
                throw new Error("怎么可能??^_^");
            }catch(e){
                //只是一个除号:(
                head += tail.substr(0,p1+1);
                tail = tail.substr(p1+1);
                continue outer;
            }
        }else{
            head += tail.substr(0,p1)+'""';
            tail = tail.substr(p2+1);
            continue outer;
        }
    }
    return head + tail;
}


在自己机器上测试了 213个脚本文件。与Rhino的解析结果对比。测试通过。
应该比较可靠了。


这个脚本好早就写过了,一直没有满意的结果,现在算比较满意了。
分享到:
评论
1 楼 haitwin 2009-04-07  
不错,不过不知道有多大用处。。。

相关推荐

    vc++ 应用源码包_1

    MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的...

    vc++ 开发实例源码包

    MFCHtml 调用脚本 如题。 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信...

    vc++ 应用源码包_2

    MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的...

    vc++ 应用源码包_6

    MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的...

    vc++ 应用源码包_5

    MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的...

    vc++ 应用源码包_3

    MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的...

    入门学习Linux常用必会60个命令实例详解doc/txt

    虚拟控制台最有用的是,当一个程序出错造成系统死锁时,可以切换到其它虚拟控制台工作,关闭这个程序。 shutdown 1.作用 shutdown命令的作用是关闭计算机,它的使用权限是超级用户。 2.格式 shutdown [-h][-i...

    Oracle9i的init.ora参数中文说明

    ), interpreted (然后 PL/SQL 模块将被编译为 PL/SQL 字节代码格式), debug (PL/SQL 模块将用探测调试符号来编译), non_debug。 默认值: " interpreted, non_debug " plsql_native_linker: 说明: 此参数指定链接...

    uboott移植实验手册及技术文档

    实验三 移植U-Boot-1.3.1 实验 【实验目的】 了解 U-Boot-1.3.1 的代码结构,掌握其移植方法。 【实验环境】 1、Ubuntu 7.0.4发行版 2、u-boot-1.3.1 3、FS2410平台 4、交叉编译器 arm-softfloat-linux-gnu-...

    QTP_8_用户手册中文版

    浏览QuickTest Professional 程序文件夹..............................................24 第=ff=部分:=使用测试对象 第=P=章:=了解测试对象模型.................................................................

    Spring 2.0 开发参考手册

    17.6. 对远程接口不提供自动探测 17.7. 在选择这些技术时的一些考虑 18. Enterprise Java Bean(EJB)集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问...

    spring chm文档

    17.6. 对远程接口不提供自动探测 17.7. 在选择这些技术时的一些考虑 18. Enterprise Java Bean(EJB)集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问...

    Spring-Reference_zh_CN(Spring中文参考手册)

    7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.1.1. ...

Global site tag (gtag.js) - Google Analytics