nodom2

Wesley13
• 阅读 666

nodom2 主要完成了常见js表达式处理包括 操作符 ()!|*/+-><=&%,以及操作符组合如>=、===、!== 等,值null undefined true false。

代码结构有了很大优化,字符串处理变得更简单,分为字符串、变量和函数。

代码如下:

class Expression{
    /**
     * @param exprStr    表达式串
     */
    constructor(exprStr){
        this.inited = true;
        //旧值
        this.oldVal = undefined;
        //新值
        this.newVal = undefined;
        this.stack = this.init(exprStr);
    }

    /**
     * 初始化,把表达式串转换成堆栈
     */
    init(exprStr){
        //字符串开始
        let startStr = undefined;
        let type = 0; // 1字符串 2变量 3函数
        //字符串开始结束符
        let strings = "'`\"";
        //运算符
        let operand = "()!|*/+-><=&%     ";
        //
        let values = ['null','undefined','true','false'];
        //堆栈
        let stack = new Array();
        let sTmp = '';
        for(let i=0;i<exprStr.length;i++){
            let c = exprStr[i];
            switch(type){
                case 1: //当前为字符串
                    //字符串标识
                    if(strings.indexOf(c) !== -1){
                        if(c === startStr){
                            this.addStr(sTmp + c,stack);
                            startStr = undefined;
                            sTmp = '';
                            type = 0;
                            continue;
                        }
                    }
                    break;
                case 2: //当前为变量
                    //操作符
                    if(operand.indexOf(c) !== -1){
                        //转为函数
                        if(c === '('){
                            type = 3;
                        }else{ //变量结束
                            this.addVar(sTmp,values,stack);
                            sTmp = '';
                            type = 0;
                        }
                    }
                    break;
                case 3:
                    if(c === ')'){
                        let a = sTmp.trim().split('(');
                        //函数名
                        let fn = a[0];
                        //参数
                        let pa = a[1].split(',');
                        for(let j=0;j<pa.length;j++){
                            pa[j] = pa[j].trim();
                        }
                        
                        //函数入栈
                        stack.push({
                            val:fn,
                            params:pa,
                            type:'function'
                        });
                        sTmp = '';
                        type = 0;
                        continue;
                    }
                    break;
                default:
                    //字符串开始
                    if(strings.indexOf(c) !== -1){
                        startStr = c;
                        type = 1;
                    }else if(operand.indexOf(c) === -1){ //变量开始
                        type = 2;
                        if(sTmp !== ''){
                            this.addStr(sTmp,stack);
                            sTmp = '';
                        }
                    }
            }
            sTmp += c;
        }
        if(type === 2){ //变量处理
            this.addVar(sTmp,values,stack);
        }else if(type === 0 && sTmp !== ''){  //字符串
            this.addStr(sTmp,stack);
        }else{
            //抛出表达式错误
            throw DD.Error.handle('invoke','expression',0,'Node');
        }
        return stack;
    }    



    /**
     * 表达式计算
     * @param module     模块
     * @param model     模型
     */
    val(module,model){
        if(this.stack === null){
            return '';
        }
        let retStr = '';
        this.stack.forEach((item)=>{
            let value='';
            switch(item.type){
                case 'string'://字符串
                    value = item.val;
                    break;
                case 'field'://变量
                    value = model.$get(item.val);
                    break;
                case 'function'://函数
                    let foo = module.methodFactory.get(item.val);
                    if(DD.isFunction(foo)){
                        let param = [];
                        if(item.params.length>0){
                            item.params.forEach((p)=>{
                                param.push(model.$get(p));    
                            });
                        }
                        value = foo.apply(module,param);
                    }
            }
            retStr += value;
        });

        if(retStr !== ''){
            retStr = eval(retStr) + '';
        }
        //设置新值
        this.newVal = retStr;
        return retStr;
    }

    /**
     * 添加变量
     */
     addVar(field,values,stack){
        let addFlag = false;
        //判断是否为值表达式 null undefined true false
        for(let j=0;j<values.length;j++){
            if(field === values[j]){
                addFlag = true;
                break;
            }
        }
        addFlag = addFlag || DD.isNumberString(field);
        //作为字符串处理   
        if(addFlag){
            this.addStr(field,stack);
        }else{
            stack.push({
                val:field.trim(),
                type:'field'
            });
        }
    }

    /**
     * 添加字符串
     */
    addStr(str,stack){
        //如果前一个类型为字符串,则追加到前一个
        if(stack.length > 0 && stack[stack.length-1].type === "string"){ 
            stack[stack.length-1].val += str;
        }else{
            stack.push({
                val:str,
                type:'string'
            });
        }
    }

    /**
     * 提交,旧值换为新值,新值undefined
     */
    commit(){
        this.oldVal = this.newVal;
        this.newVal = undefined;
    }


    /**
     * 判断是否做了更改
     */
    isChanged(){
        return this.oldVal === this.newVal;
    }


}
点赞
收藏
评论区
推荐文章
Souleigh ✨ Souleigh ✨
3年前
JS - typeof 与 instanceof
一、typeoftypeof操作符返回一个字符串,表示未经计算的操作数的类型使用方法如下:typeof operandtypeof(operand)operand表示对象或原始值的表达式,其类型将被返回举个例子typeof 1 // 'number'typeof '1' // 'string'
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
JavaScript预解析处理过程原来是这回事
讲解一般来说,Javascript代码的执行包括两个过程:预解析处理过程和逐行解读过程。在代码逐行解读前,Javasript引擎需要进行代码的预处理过程。预解析处理的工作主要是变量提升和给变量分配内存,具体过程是在每个作用域中查找var声明的变量、函数定义和命名函数(函数参数),找到它们后,在当前作用域中给他们分配内存,并给他们设置初始值。预解析设置的初
Wesley13 Wesley13
3年前
MYSQL正则表达式
MySQL中使用REGEXP操作符来进行正则表达式匹配。下表中的正则模式可应用于REGEXP操作符中。模式描述^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配'\\n'或'\\r'之后的位置。$匹配输入字符串的结束位置。如果设置了RegExp对象的Mul
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
Python中re(正则表达式)模块学习
今天学习了Python中有关正则表达式的知识。关于正则表达式的语法,不作过多解释,网上有许多学习的资料。这里主要介绍Python中常用的正则表达式处理函数。re.matchre.match尝试从字符串的开始匹配一个模式,如:下面的例子匹配第一个单词。!复制代码(http://static.oschina.net
Wesley13 Wesley13
3年前
Oracle存储过程常用技巧
存储过程的结构是非常简单的,我们在这里除了学习存储过程的结构外,还会学习编写存储过程时相关的一些实用的知识。如:游标的处理,异常的处理,集合的选择等等1.存储过程结构1.1第一个存储过程createorreplaceprocedureproc1(p_para1varchar2,p_para
Stella981 Stella981
3年前
Python字符串运算符
下表实例变量a值为字符串"Hello",b变量值为"Python":操作符描述实例字符串连接\ab'HelloPython'\重复输出字符串\a\2'HelloHello'\\通过索引获取字符串中字符\a\1\'e'\:\截取字符串中的一
子桓 子桓
1年前
GO语言集成开发工具环境 GoLand 2023中文安装教程
1.智能代码补全:GoLand能够根据上下文自动补全代码,包括函数名、变量名、包名等。它还能够识别代码中的错误和警告,快速修复和优化代码。2.强大的调试功能:GoLand提供了强大的调试功能,包括设置断点、单步调试、查看变量值、跟踪Goroutine等。它
小万哥 小万哥
4个月前
Kotlin 循环与函数详解:高效编程指南
Kotlin中的循环结构让你能轻松遍历数组或范围内的元素。使用for循环结合in操作符,可以简洁地访问数组中的每个项,如字符串数组或整数数组。对于范围,可以用..来定义一系列连续的值并进行迭代。此外,Kotlin支持通过break和continue控制循环流程。函数则允许封装可复用的代码块,你可以定义接受参数并返回值的函数,利用简写语法使代码更加紧凑。例如,myFunction(x:Int,y:Int)xy简洁地定义了一个计算两数之和的函数。