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;
}
}