yyel-engine
Version:
369 lines (314 loc) • 11.3 kB
JavaScript
function str2Object(commonStr) {
let oper1 = ['+', '-', '*', '/', '!=', '==', '(', ')', '<', '>', '<=', '>='];
let oper2 = ['7', '8', '9', '0', '4', '5', '6', '.', '1', '2', '3', '00'];
let regOper1 = oper1.concat(oper2).filter(v => v.length > 1);
let regOper2 = oper1.concat(oper2).filter(v => v.length <= 1);
let reg = regOper => {
let specialCharList = "[]-\\^";
let simpleOperArray = regOper.filter(v => v.length == 1);
let complexOperArray = regOper.filter(v => v.length > 1);
let simpleReg = simpleOperArray.length > 0 ? `[${simpleOperArray.map((v, k) => /[0-9]/.test(v) ? `${v}` : `\\${v}`).join('')}]` : '';
let complexReg = complexOperArray.map((v, k) => {
return k == complexOperArray.length - 1 ? `(?:${v})` : `(?:${v})|`;
}).join('');
return new RegExp(simpleReg.length > 0 && complexReg.length > 0 ? simpleReg + '|' + complexReg : simpleReg.length > 0 ? simpleReg : complexReg.length > 0 ? complexReg : "");
};
function getNumber(str) {
var arr = [];
for (let i = 0; i < str.length; i++) {
if (parseInt(str[i]).toString() == 'NaN') {
arr.push({
type: 'oper',
value: str[i]
});
} else {
let newV = str.substring(i).replace(/[<>+-]/g, '*').split('*').concat();
for (let j = 0; j < newV.length; j++) {
if (parseInt(str[i]).toString() != 'NaN') {
arr.push({
type: 'number',
value: newV[j]
});
i += newV[j].length - 1;
break;
}
}
}
}
return arr;
}
let isString = commonStr.match(/[\"\“\'\’]/);
if (!isString) {
return getNumber(commonStr);
} else {
function divideStr(str) {
let divideList = [];
let divideReg = /(?:(\"(.*?)\")|(\“(.*?)\”)|(\'(.*?)\')|(\‘(.*?)\’))/;
for (let i = 0; i < str.length; i++) {
let tempStr = str.slice(i);
let hasChar = tempStr.match(divideReg);
if (!hasChar) {
divideList.push(tempStr);
break;
} else {
let startIndex = hasChar.index || 0;
let length = hasChar[0].length;
if (startIndex >= 0) {
if (startIndex != 0) {
divideList.push(tempStr.slice(0, startIndex));
}
divideList.push({
type: 'string',
code: hasChar[0] || ''
});
i = i + startIndex + length - 1;
}
}
}
return divideList;
}
return divideStr(commonStr).reduce((prev, v) => {
if (typeof v == 'string') {
prev = prev.concat(getNumber(v));
return prev;
} else {
prev.push(v);
return prev;
}
}, []);
}
}
export function parseFormulaExpression(formulaExpression, isParamStr) {
let formulaArray = [];
if (isParamStr) {
if (formulaExpression.length === 0) {
return [];
}
let dotIndex = [],
degree = 0;
for (let i in formulaExpression) {
if (degree == 0 && formulaExpression[i] == ',') {
dotIndex.push(parseInt(i));
}
if (formulaExpression[i] == '(') {
degree++;
}
if (formulaExpression[i] == ')') {
degree--;
}
}
if (dotIndex.length > 0) {
let paramList = dotIndex.reduce((prev, v, k) => {
let item = null,
item2 = null;
if (k == 0) {
item = formulaExpression.slice(0, v);
prev.push(item);
if (k == dotIndex.length - 1) {
prev.push(formulaExpression.slice(v + 1));
}
return prev;
} else if (k < dotIndex.length - 1) {
item = formulaExpression.slice(dotIndex[k - 1] + 1, v);
prev.push(item);
return prev;
} else {
item = formulaExpression.slice(dotIndex[k - 1] + 1, v);
item2 = formulaExpression.slice(v + 1);
prev.push(item, item2);
return prev;
}
}, []);
return paramList.map(v => v.length >= 1 ? parseFormulaExpression(v) : null);
} else {
return [parseFormulaExpression(formulaExpression)];
}
}
let inUriReg = /(\".*?#.*?\")|(\“.*?#.*?\”)/;
let firstIndex = -1;
for (let i = 0; i < formulaExpression.length; i++) {
let tempStr = formulaExpression.slice(i);
let charPosition = tempStr.indexOf('#');
let hasChar = tempStr.match(inUriReg);
if (!hasChar) {
firstIndex = charPosition;
break;
} else {
let startIndex = hasChar.index || 0;
let length = hasChar[0].length;
if (charPosition > startIndex && charPosition < startIndex + length) {
i = i + startIndex + length - 1;
} else {
firstIndex = charPosition;
break;
}
}
}
if (firstIndex == -1) {
return str2Object(formulaExpression);
}
let firstSubstr = formulaExpression.slice(0, firstIndex);
if (firstSubstr.length > 0) {
formulaArray = formulaArray.concat(parseFormulaExpression(firstSubstr));
}
let regVerify = formulaExpression.slice(firstIndex).match(/[\(\@\$]/);
if (!regVerify) {
return str2Object(formulaExpression);
}
let type = regVerify ? regVerify[0] == '(' ? 'func' : regVerify[0] == '@' ? 'variable' : regVerify[0] == '$' ? 'uri' : '' : '';
let endIndex = regVerify && regVerify.index || -1;
let paramEndIndex = -1;
if (type == 'func') {
let count = 1;
let countStr = formulaExpression.slice(firstIndex + endIndex + 1);
for (let i in countStr) {
if (countStr[i] == '(') {
count++;
}
if (countStr[i] == ')') {
count--;
if (count == 0) {
paramEndIndex = parseInt(i) + firstIndex + endIndex + 1;
break;
}
}
}
if (paramEndIndex == -1) {
formulaArray.push({
type: 'func',
code: formulaExpression.slice(firstIndex + 1, firstIndex + endIndex),
params: parseFormulaExpression(formulaExpression.slice(firstIndex + endIndex + 1), true)
});
} else {
formulaArray.push({
type: 'func',
code: formulaExpression.slice(firstIndex + 1, firstIndex + endIndex),
params: parseFormulaExpression(formulaExpression.slice(firstIndex + endIndex + 1, paramEndIndex), true)
});
}
} else if (type == 'variable') {
paramEndIndex = firstIndex + endIndex;
formulaArray.push({
type: 'variable',
code: formulaExpression.slice(firstIndex + 1, paramEndIndex)
});
} else if (type == 'uri') {
if (formulaExpression.slice(firstIndex + 1, firstIndex + endIndex).match(/^\{[^\}]*\}$/)) {
paramEndIndex = firstIndex + endIndex;
formulaArray.push({
type: 'const',
code: formulaExpression.slice(firstIndex + 2, paramEndIndex - 1).replace(/"/g, '')
});
} else {
paramEndIndex = firstIndex + endIndex;
formulaArray.push({
type: 'uri',
code: formulaExpression.slice(firstIndex + 1, paramEndIndex).replace(/"/g, '')
});
}
}
let tailSubstr = paramEndIndex == -1 ? "" : formulaExpression.slice(paramEndIndex + 1);
if (tailSubstr.length > 0) {
formulaArray = formulaArray.concat(parseFormulaExpression(tailSubstr));
}
return formulaArray;
}
export function createMathExpressWithError(formulaList, paramList) {
let _mathExpress = '';
try {
_mathExpress = createMathExpress(formulaList, paramList);
} catch (err) {
throw Error('公式自动计算错误:' + err);
}
return _mathExpress;
}
function createMathExpress(formulaList, paramList) {
const OPER_LIST = new Set(['-', '+', '/', '*', '(', ')', '>', '<', '&&', '||', '>=', '<=', '==', '%']);
const MATH_LIST = new Set(['sin', 'cos', 'exp', 'sqrt', 'log', 'tan', 'cot', 'asin', 'acos', 'atan', 'max', 'min', 'abs', 'ln', 'PI', 'E']);
const MATH_LIST_EXP = new Set(['PI', 'E']);
const STRING_LIST = new Set(['contains', 'endsWith', 'startsWith', 'indexOf', 'lastIndexOf', 'length', 'lowerCase', 'upperCase', 'equalsIgnoreCase', 'left', 'right']);
const STRING_LIST_OBJ = {
contains: (s1, s2) => s1.includes(s2),
endsWith: (s1, s2) => s1.endsWith(s2),
startsWith: (s1, s2) => s1.startsWith(s2),
indexOf: (s1, s2) => s1.indexOf(s2),
lastIndexOf: (s1, s2) => s1.lastIndexOf(s2),
length: s1 => s1.length,
lowerCase: s1 => s1.toLowerCase(),
upperCase: s1 => s1.toUpperCase(),
equalsIgnoreCase: (s1, s2) => s1.toLowerCase() === s2.toLowerCase(),
left: (s1, num) => s1.slice(0, num),
right: (s1, num) => s1.slice(-num)
};
let express = "",
calcExpress = true;
function handleFactory(record) {
if (record.type == 'func') {
if (STRING_LIST.has(record.functionName || record.code)) {
let strParamList = [];
let params = "paramCount" in record ? record.params.slice(0, record.paramCount) : record.params;
params.forEach(v => {
strParamList.push(createMathExpress(v, paramList));
});
let returnType = typeof STRING_LIST_OBJ[record.code](...strParamList);
if (returnType == 'string' && isNaN(STRING_LIST_OBJ[record.code](...strParamList))) {
calcExpress = false;
}
if (!express) {
express = STRING_LIST_OBJ[record.code](...strParamList);
} else {
express += STRING_LIST_OBJ[record.code](...strParamList);
}
}
if (MATH_LIST.has(record.functionName || record.code)) {
let _funcExpress = '';
if (MATH_LIST_EXP.has(record.functionName || record.code)) {
_funcExpress += `${record.functionName}`;
} else {
_funcExpress += `${record.functionName}(`;
let params = "paramCount" in record ? record.params.slice(0, record.paramCount) : record.params;
_funcExpress += params && params.map((v, index) => {
return createMathExpress(v, paramList) + (index < params.length - 1 ? ',' : '');
}).join('') || '';
_funcExpress += ")";
}
express += eval(_funcExpress);
}
}
if (record.type == 'variable') {
if (record.code && record.code in paramList) {
if (paramList[record.code] === '') {
if (record.paramType) {
express += ['DOUBLE', 'FLOAT', 'INT'].includes(record.paramType) ? 0 : '';
} else {
express += '';
}
} else {
express += paramList[record.code];
}
} else {
express += record.code;
throw Error('选中变量不在当前提供变量列表中!');
}
}
if (record.type == 'oper' || record.type == 'number') {
calcExpress = isNaN(record.value) && !OPER_LIST.has(record.value) ? false : calcExpress;
express += record.value;
}
if (record.type == 'uri' || record.type == 'string') {
calcExpress = isNaN(record.code) ? false : calcExpress;
express += record.code;
}
}
if (formulaList) {
if (Array.isArray(formulaList) && formulaList.length > 0) {
for (let record of formulaList) {
handleFactory(record);
}
} else if (typeof formulaList == "object") {
handleFactory(formulaList);
}
}
return calcExpress ? eval(express) : express;
}
//# sourceMappingURL=index.js.map