formulaStringToArray.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. function isFormulaItem(ele){
  2. return ele.type == 'Element' || ele.type == 'ParamData'
  3. }
  4. function parseFormula(arr,resultFormula,processFormula,isAllFun){
  5. let tmpArr = [];//放置这一层的数组
  6. for (let i = 0; i < arr.length; i++) {
  7. tmpArr.push(arr[i]);
  8. if(arr[i].type != "Function"){
  9. isAllFun = false;
  10. }
  11. }
  12. if(isAllFun){
  13. for (let i = 0; i < tmpArr.length; i++) {
  14. parseArguments(resultFormula[0],tmpArr[i]);
  15. parseFormula(arr[i].children,resultFormula,processFormula,isAllFun);
  16. }
  17. }else{
  18. for (let i = 0; i < tmpArr.length; i++) {
  19. if(tmpArr[i].type == 'Function'){
  20. let obj = {
  21. children:[],
  22. name:"临时占位",
  23. selected:false,
  24. type:"Element",
  25. }
  26. parseProcessFormula(arr[i],obj);
  27. processFormula.push(Object.assign({},obj))
  28. delete obj.children;
  29. }else if(tmpArr[i].name){
  30. processFormula.push(tmpArr[i]);
  31. }
  32. }
  33. }
  34. }
  35. //解析方法里面的参数
  36. function parseArguments(ele,funObj){
  37. let fcReg = /(FC\.\S+\()(.+)\)/;
  38. let fun = {
  39. example:funObj.example,
  40. name:funObj.name,
  41. template:funObj.template,
  42. };
  43. //console.log(funObj)
  44. //特殊公式需要number
  45. if(funObj.number){
  46. fun.number = funObj.number;
  47. }
  48. let argTextArr = funObj.children;//放参数文本的数组
  49. //根据逗号位置分割参数
  50. let index = 0;
  51. let argSpliceArr = [[]];
  52. while (index < argTextArr.length) {
  53. if(argTextArr[index].type =='Comma'){
  54. argSpliceArr.push([]);
  55. }else{
  56. argSpliceArr[argSpliceArr.length-1].push(argTextArr[index])
  57. }
  58. index++
  59. }
  60. fun.arguments = [];
  61. let tmpArr = fcReg.exec(funObj.template.ft);
  62. let argList = tmpArr[2].split(",");//括号里面参数部分#1,#2..
  63. argList.forEach((argText,index)=>{
  64. //只用动态的
  65. if(argText.indexOf('#')>-1){
  66. if(argSpliceArr[index].length>1){
  67. if(fun.name == '判断'){
  68. fun.arguments.push(ifFunArgumentsHandle(argSpliceArr[index]))
  69. }else{
  70. //是前面的计算结果
  71. fun.arguments.push(ele)
  72. }
  73. }else{
  74. let arg = argSpliceArr[index][0];
  75. if(!arg){
  76. fun.arguments.push(undefined)
  77. }else if( arg.type == 'Element'){
  78. fun.arguments.push(arg)
  79. }else if( arg.type == 'ParamData'){
  80. fun.arguments.push(arg)
  81. }else if(arg.type == 'Function'){
  82. fun.arguments.push(ele)
  83. }else if(arg.type == 'Text'){
  84. fun.arguments.push(arg.tag)
  85. }else{
  86. fun.arguments.push(undefined)
  87. }
  88. }
  89. }
  90. })
  91. ele.children.push(fun);
  92. }
  93. function parseProcessFormula(funObj,ele){
  94. parseArguments(ele,funObj);
  95. let inFun = false;//是不是有Function
  96. let endEle = null;//认为最下面一层第一个元素是显示的元素
  97. for (let i = 0; i < funObj.children.length; i++) {
  98. if(funObj.children[i].type == 'Function'){
  99. parseProcessFormula(funObj.children[i],ele);
  100. inFun = true;
  101. }else if(isFormulaItem(funObj.children[i]) && !endEle){
  102. endEle = funObj.children[i];
  103. }
  104. }
  105. if(!inFun){
  106. //console.log(endEle)
  107. //把临时的属性改为最终找到的
  108. if(endEle.type == 'Element'){
  109. ele.id = endEle.id;
  110. ele.name = endEle.name;
  111. ele.tableElementKey = endEle.tableElementKey;
  112. }else if(endEle.type == 'ParamData'){
  113. ele.id = endEle.id;
  114. ele.name = endEle.name;
  115. ele.v = endEle.v;
  116. ele.k = endEle.k;
  117. ele.type = "ParamData";
  118. }
  119. }
  120. }
  121. //处理if方法的参数
  122. function ifFunArgumentsHandle(argArr){
  123. let arr = [];
  124. argArr.forEach((Element)=>{
  125. if(Element.type == 'Text' || Element.type == 'Logical'){
  126. arr.push(Element.tag)
  127. }else{
  128. if(Element.type == 'Function'){
  129. let rootObj = {root:null};
  130. getRootElement(Element.children,rootObj)
  131. arr.push(rootObj.root)
  132. }else{
  133. arr.push(Element);
  134. }
  135. }
  136. })
  137. return arr;
  138. }
  139. //获取嵌套里面根节点元素,认为是if显示的元素
  140. function getRootElement(children,rootObj){
  141. let inFun = false;//是不是有Function
  142. let endEle = null;//认为最下面一层第一个元素是显示的元素
  143. children.forEach((Element)=>{
  144. if(Element.type == 'Function'){
  145. getRootElement(Element.children,rootObj);
  146. inFun = true;
  147. }else if(isFormulaItem(Element) && !endEle){
  148. endEle = Element;
  149. }
  150. })
  151. if(!inFun){
  152. //把临时的属性改为最终找到的
  153. rootObj.root = Object.assign({},endEle);
  154. }
  155. }
  156. export const formulaStringToArray = (text,elemap,formulaMap) => {
  157. // 匹配开始的FC.xxx(
  158. const startFCRegExp = /^FC\.([a-zA-Z0-9]+)\(/;
  159. const startBracketsReg = /^\(/;//左括号
  160. const endBracketsReg = /^\)/;//右括号
  161. const elementReg = /^E\[(.[^\]]+_.[^\]]+)\]/;//元素
  162. const paramReg = /^WP\[(.[^\]]+)\]/;//节点参数
  163. const commaReg = /^,/;//逗号
  164. const operatorReg = /^ (\+|-|\*|%|\/) /;//加减乘除
  165. const wordReg = /^[\u4e00-\u9fa5\w0-9'"-]+/;//文本
  166. const logicalReg = /^(>=|<=|>|<|=|&&)/;//逻辑符号
  167. let elementMap = JSON.parse(elemap);//元素字典
  168. //console.log(formulaMap)
  169. let resArr = [];//结果数组
  170. let strIndex = 0;//位置索引
  171. let nuText = text;//未处理的字符串
  172. //let startStack = [];//方法体开始部分和左括号 放进来的栈
  173. let contentStack = [];//内容放进来的栈
  174. while (strIndex < text.length) {
  175. nuText = text.substring(strIndex);
  176. if(startFCRegExp.test(nuText)){
  177. //console.log('匹配FC开始部分')
  178. //匹配FC开始部分FC.xxx(
  179. let regRes = nuText.match(startFCRegExp);
  180. let startText = regRes[0];//匹配到的文本
  181. let obj = {};
  182. if(formulaMap[startText]){
  183. Object.assign(obj,formulaMap[startText]);
  184. Object.assign(obj,{
  185. type:'Function',
  186. children:[],
  187. tag:startText
  188. });
  189. }else{
  190. obj = {
  191. type:'Function',
  192. children:[],
  193. tag:startText
  194. }
  195. }
  196. //startStack.push(startText);
  197. contentStack.push(obj);
  198. strIndex += startText.length;//索引移动
  199. }else if(endBracketsReg.test(nuText)){
  200. //console.log('匹配右括号')
  201. //匹配右括号
  202. let endBrackets = nuText.match(endBracketsReg)[0];
  203. let popObj = contentStack.pop();
  204. let arrType = [];
  205. if(contentStack.length > 0){
  206. let content =contentStack[contentStack.length - 1];
  207. content.children.push(popObj);
  208. arrType = content.children;
  209. }else{
  210. //匹配完成最顶层的一整个方法体,或括号
  211. resArr.push(popObj);
  212. arrType = resArr;
  213. }
  214. if(popObj.type =='Brackets'){
  215. let brackArr = [];
  216. //如果是括号,把括号里面的提出一层
  217. popObj.children.forEach((ele)=>{
  218. brackArr.push(ele);
  219. })
  220. //补个右括号
  221. brackArr.push({
  222. type:'Brackets',
  223. selected:false,
  224. name:')',
  225. });
  226. arrType.push(...brackArr);
  227. delete popObj.children
  228. }
  229. //console.log(popObj,'pop')
  230. strIndex += endBrackets.length;//索引移动
  231. }else if(startBracketsReg.test(nuText)){
  232. //console.log('匹配左括号')
  233. //匹配左括号
  234. let startBrackets = nuText.match(startBracketsReg)[0];
  235. contentStack.push({
  236. type:'Brackets',
  237. children:[],
  238. selected:false,
  239. name:startBrackets,
  240. tag:startBrackets
  241. });
  242. strIndex += startBrackets.length;//索引移动
  243. }else if(elementReg.test(nuText)){
  244. //console.log('匹配元素')
  245. //匹配元素
  246. let eleArr = nuText.match(elementReg);
  247. let obj = {};
  248. if(elementMap[eleArr[1]]){
  249. Object.assign(obj,elementMap[eleArr[1]]);
  250. Object.assign(obj,{
  251. selected:false,
  252. children:[],
  253. tag:eleArr[0]
  254. });
  255. }else{
  256. obj = {
  257. type:'Element',
  258. name:eleArr[1].split('_')[1],
  259. tableElementKey:eleArr[1],
  260. children:[],
  261. selected:false,
  262. tag:eleArr[0]
  263. }
  264. }
  265. let content =contentStack[contentStack.length - 1];
  266. if(content){
  267. content.children.push(obj);
  268. }else{
  269. //如果没有,那就是在最上层
  270. resArr.push(obj);
  271. }
  272. strIndex += eleArr[0].length;//索引移动
  273. }else if(paramReg.test(nuText)){
  274. //console.log('匹配节点参数')
  275. //匹配节点参数
  276. let eleArr = nuText.match(paramReg);
  277. let obj = {};
  278. if(elementMap[eleArr[1]]){
  279. Object.assign(obj,elementMap[eleArr[1]]);
  280. Object.assign(obj,{
  281. selected:false,
  282. children:[],
  283. tag:"paramData"
  284. });
  285. }else{
  286. obj = {
  287. type:'ParamData',
  288. name:elementMap[eleArr[1]].name,
  289. v:elementMap[eleArr[1]].v,
  290. k:elementMap[eleArr[1]].k,
  291. children:[],
  292. selected:false,
  293. tag:"paramData"
  294. }
  295. }
  296. let content =contentStack[contentStack.length - 1];
  297. if(content){
  298. content.children.push(obj);
  299. }else{
  300. //如果没有,那就是在最上层
  301. resArr.push(obj);
  302. }
  303. strIndex += eleArr[0].length;//索引移动
  304. }else if(commaReg.test(nuText)){
  305. //console.log('匹配逗号')
  306. //匹配逗号
  307. let comma = nuText.match(commaReg)[0];
  308. contentStack[contentStack.length - 1].children.push({
  309. type:'Comma',
  310. tag:comma
  311. });
  312. strIndex += comma.length;//索引移动
  313. }else if(logicalReg.test(nuText)){
  314. //console.log('逻辑符号')
  315. let logical = nuText.match(logicalReg)[0];
  316. contentStack[contentStack.length - 1].children.push({
  317. type:'Logical',
  318. tag:logical
  319. });
  320. strIndex += logical.length;//索引移动
  321. }else if(operatorReg.test(nuText)){
  322. //console.log('匹配加减乘除')
  323. //匹配加减乘除
  324. let operator = nuText.match(operatorReg)[0];
  325. let obj = {
  326. type:'Operator',
  327. name:operator,
  328. selected:false,
  329. tag:operator,
  330. };
  331. if(formulaMap[operator]){
  332. obj.example = formulaMap[operator].example;
  333. obj.template = formulaMap[operator].template;
  334. }
  335. if(contentStack.length > 0){
  336. //不然就在方法体或括号里面
  337. contentStack[contentStack.length - 1].children.push(obj);
  338. }else{
  339. //如果没有,那就是在最上层
  340. resArr.push(obj);
  341. }
  342. strIndex += operator.length;//索引移动
  343. //console.log(operator.length)
  344. }else if(wordReg.test(nuText)){
  345. //匹配文本
  346. let word = nuText.match(wordReg)[0];
  347. console.log('匹配文本',word)
  348. if(word == "''"){
  349. word = "";
  350. }
  351. let obj = {
  352. type:'Text',
  353. tag:word
  354. };
  355. let content =contentStack[contentStack.length - 1];
  356. if(content){
  357. content.children.push(obj);
  358. }else{
  359. //如果没有,那就是在最上层
  360. obj.name = word;
  361. obj.selected = false;
  362. resArr.push(obj);
  363. }
  364. strIndex += word.length?word.length:2;//索引移动
  365. }
  366. else{
  367. console.log('匹配不到:',nuText)
  368. //匹配不到
  369. strIndex++
  370. }
  371. }
  372. let resultFormula = [{
  373. children:[],
  374. name:"临时占位",
  375. selected:false,
  376. type:"Element",
  377. }]
  378. let processFormula = []
  379. let isAllFun = true;//一层全是方法,有其他说明到了显示层
  380. //从顶层开始
  381. parseFormula(resArr,resultFormula,processFormula,isAllFun);
  382. //console.log(contentStack)
  383. console.log(resArr);
  384. console.log(resultFormula);
  385. console.log(processFormula);
  386. return {
  387. processFormula:processFormula,
  388. resultFormula:resultFormula,
  389. };
  390. }