⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.js

📁 在线ExeclCopyright (c) iRows.com. All rights reserved. Do not copy
💻 JS
📖 第 1 页 / 共 3 页
字号:
// Copyright (c) iRows.com. All rights reserved. Do not copy.var FP_VAR_CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$!"var FP_COL_IDS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"var OP_Unari=1var OP_DoLeft=2var OP_Op=3var OP_Pct=4var OP_GetCell=5var OP_Call=6var OP_GetDyn=7var OPC_E=0var OPC_L=1var OPC_LE=2var OPC_G=3var OPC_GE=4var OPC_NE=5var FP_rules=new Array(new Array("NumberToExp",new Array("number")),new Array("TextToExp",new Array("text")),new Array("CallNoParm",new Array("name","(",")")),new Array("CallStart",new Array("name","(")),new Array("CallParm",new Array("call","exp",",")),new Array("CallParm",new Array("call","range",",")),new Array("CallLast",new Array("call","exp",")")),new Array("CallLast",new Array("call","range",")")),new Array("NameRange",new Array("name",":","name")),new Array("NameToExp",new Array("name")),new Array("Op",new Array("exp","op1","exp")),new Array("Unari",new Array("start","op3","exp")),new Array("Unari",new Array("(","op3","exp")),new Array("Unari",new Array("call","op3","exp")),new Array("Unari",new Array("op1","op3","exp")),new Array("Unari",new Array("op2","op3","exp")),new Array("Unari",new Array("op3","op3","exp")),new Array("Unari",new Array("logop","op3","exp")),new Array("BrExpBr",new Array("(","exp",")")),new Array("BrExpOpExpBr",new Array("(","exp","op1","exp",")")),new Array("BrExpOpExpBr",new Array("(","exp","op2","exp",")")),new Array("BrExpOpExpBr",new Array("(","exp","op3","exp",")")),new Array("BrExpOpExpBr",new Array("(","exp","logop","exp",")")),new Array("Op",new Array("exp","op2","exp")),new Array("Pct",new Array("exp","%")),new Array("Op",new Array("exp","op3","exp")),new Array("Op",new Array("exp","logop","exp")),new Array("last",new Array("?")))function FormulaParser(model){var P={M:model}P.evaluate=function(formula,execCode){var errors=[]var res={errors:[]}if(execCode==null){var te=P.tokenize(formula)if(te.errors.length>0)res.errors=te.errorselse{var root=P.parse(te.tokens,errors)if(errors.length>0)res.errors=errorselse{res.requires=H8(te.tokens)res.execCode=rootexecCode=root}}}if(execCode!=null){res.value=res.type=res.pattern=nullP.J3(execCode,errors)if(errors.length>0)res.errors=errorselse{res.value=execCode.valueres.type=execCode.valueTyperes.pattern=execCode.patternres.requiresDyns=execCode.dyns}}return res}P.parse=function(tokens,errors){var root=P.applyAllRules(tokens,errors)return root}P.J3=function(root,errors){P.J4(root,root,errors)if(errors.length==0){if(root.valueType=="number"){root.value=J1(root.value)}elseif(root.valueType=="boolean")root.value=root.value?"true":"false"elseif(root.valueType=="null")root.value=""}}P.J4=function(root,node,errors){if(node.op==null||node.op==0)returnvar op=node.opif(op==OP_Unari){var oper=node.leftvar nval=node.rightP.J4(root,nval,errors)if(errors.length>0)returnvar v=0var vt="number"if(nval.valueType=="number")v=nval.valueelseif(nval.valueType=="null")v=0elseif(nval.valueType=="pending")vt="pending"elseif(nval.valueType=="text"||nval.valueType=="boolean")P.H9(errors,"value","Unari operator (minus or plus) is allowed only on numeric values",oper.start,1)if(oper.text=="-")v=-vnode.value=vnode.valueType=vt}elseif(op==OP_DoLeft){var n=node.leftP.J4(root,n,errors)node.value=n.valuenode.valueType=n.valueTypenode.pattern=n.pattern}elseif(op==OP_Op){var n1=node.leftvar n2=node.rightP.J4(root,n1,errors)P.J4(root,n2,errors)if(errors.length>0)returnif(n1.valueType=="pending"||n2.valueType=="pending"){node.valueType="pending"}else{if(node.type=="logop")P.evaluateLogicalOperator(node,n1,n2,errors)elseP.evaluateOperator(node,n1,n2,errors)}}elseif(op==OP_Pct){var nval=node.leftP.J4(root,nval,errors)if(errors.length>0)returnif(nval.valueType=="pending")node.valueType="pending"else{var v=0if(nval.valueType=="number")v=nval.valueelseif(nval.valueType=="null")v=0if(nval.valueType=="text"||nval.valueType=="boolean")P.H9(errors,"value","Percentage (%) is allowed only on numeric values",node.right.start,1)v=v / 100node.value=vnode.valueType="number"}}elseif(op==OP_GetCell){var cellId=node.cellReferencevar cell=model.getCell(cellId.row,cellId.col)if(cell!=null){var cv=H7(cell)if(cv.valueType=="error"){P.H9(errors,"value","["+node.text+"] does not have a valid value.",node.start,node.text.length)}else{node.value=cv.valuenode.valueType=cv.valueTypenode.pattern=cv.pattern}}else{node.value=""node.valueType="null"}}elseif(op==OP_Call){P.processCall(root,node,errors)}elseif(op==OP_GetDyn){P.getDynVal(node.dynid,root,node,errors)}}P.getDynVal=function(dynid,root,node,errors){if(root.dyns==null)root.dyns=[]root.dyns[dynid]=1var v=model.getDyn(dynid)if(v.error==null){node.valueType=v.typenode.value=v.valuenode.pattern=v.pattern}else{P.H9(errors,"syntax",v.error,node.start,node.text?node.text.length:1)node.value=0node.valueType="number"}}P.getReferencedCells=function(formula){var res=[]var te=P.tokenize(formula)var tokens=te.tokensfor(var i=0;i<tokens.length;i++){var token=tokens[i]if(token.type=='name'){var cellRef=H6(token.text)if(cellRef){var fr=cellRef.rowvar tr=frvar fc=cellRef.colvar tc=fcif(i<tokens.length-2&&tokens[i+1].type==':'&&tokens[i+2].type=='name'){cellRef=H6(tokens[i+2].text)if(cellRef){fr=Math.min(fr,cellRef.row)tr=Math.max(tr,cellRef.row)fc=Math.min(fc,cellRef.col)tc=Math.max(tc,cellRef.col)i+=2}}res[res.length]={startRow:fr,endRow:tr,startCol:fc,endCol:tc}}elseif(i<tokens.length-2&&tokens[i+1].type==':'&&tokens[i+2].type=='name')i+=2}}if(res.length==0)res=nullreturn res}P.getChartDataRange=function(range){var res=nullvar te=P.tokenize(range)if(te.errors.length>0)return nullvar tokens=te.tokensif(tokens.length!=3)return nullif(tokens[0].type!='name'||tokens[1].type!=':'||tokens[2].type!='name')return nullvar token=tokens[0]var cellRef=H6(token.text)if(!cellRef)return nullvar fr=cellRef.rowvar tr=frvar fc=cellRef.colvar tc=fctoken=tokens[2]cellRef=H6(token.text)if(!cellRef)return nullfr=Math.min(fr,cellRef.row)tr=Math.max(tr,cellRef.row)fc=Math.min(fc,cellRef.col)tc=Math.max(tc,cellRef.col)res={fromRow:fr,fromCol:fc,toRow:tr,toCol:tc}return res}P.tokenize=function(exp){var tokens=new Array()var errors=new Array()res={tokens:tokens,errors:errors}var inBrName=falsevar currTokenfor(var i=0;i<exp.length;i++){var c=exp.charAt(i)if(inBrName){currToken.text+=cif(c==']')inBrName=false}elseif(currToken&&currToken.type=='text'&&c!='"'){currToken.text+=c}elseif(" \t".indexOf(c)>=0){if(currToken){tokens[tokens.length]=currTokencurrToken=null}}elseif(c==','){if(currToken)tokens[tokens.length]=currTokencurrToken=new Object()currToken.type=','currToken.start=icurrToken.text=ctokens[tokens.length]=currTokencurrToken=null}elseif("*/%^():".indexOf(c)>=0){if(currToken)tokens[tokens.length]=currTokencurrToken=new Object()if("*/".indexOf(c)>=0)currToken.type='op2'elseif("%:()".indexOf(c)>=0)currToken.type=celseif("^".indexOf(c)>=0)currToken.type='op1'currToken.start=icurrToken.text=ctokens[tokens.length]=currTokencurrToken=null}elseif(c=='"'){var openString=falseif(currToken){if(currToken.type=='text'){var isEnd=trueif(i<exp.length-1){var c2=exp.charAt(i+1)if(c2=='"'){currToken.text+='"'i++isEnd=false}}if(isEnd){tokens[tokens.length]=currTokencurrToken=null}}else{tokens[tokens.length]=currTokenopenString=true}}elseopenString=trueif(openString){currToken=new Object()currToken.type='text'currToken.text=''currToken.start=i}}elseif("<>=".indexOf(c)>=0){if(currToken)tokens[tokens.length]=currTokencurrToken=new Object()currToken.type='logop'currToken.text=cif(i<exp.length-1){var c2=exp.charAt(i+1)if((c=='>'&&c2=='=')||(c=='<'&&c2=='=')||(c=='<'&&c2=='>')){i++currToken.text+=c2}}tokens[tokens.length]=currTokencurrToken=null}elseif(currToken&&currToken.type=='number'){if("0123456789".indexOf(c)>=0)currToken.text+=celseif(c=='.'){if(currToken.text.indexOf('.')>=0){P.H9(errors,'syntax','More than one decimal point in a number',i,1)c='0'}elseif(currToken.text.indexOf('e')>=0||currToken.text.indexOf('x')>=0||currToken.text.indexOf('b')>=0){P.H9(errors,'syntax','Invalid position of decimal point',i,1)c='0'}currToken.text+=c}elseif(c=='x'||c=='X'){if(currToken.text!='0'){P.H9(errors,'syntax','Invalid number. For hexadecimal constants use 0x1f',i,1)c='0'}else c='x'currToken.text+=c}elseif((c=='b'||c=='B')&&!(currToken.text.length>=2&&currToken.text.charAt(0)=='0'&&currToken.text.charAt(1)=='x')){if(currToken.text!='0'){P.H9(errors,'syntax','Invalid number. For binary constants use 0b0010',i,1)c='0'}else c='b'currToken.text+=c}elseif("abcdefABCDEF".indexOf(c)>=0&&currToken.text.length>=2&&currToken.text.charAt(0)=='0'&&currToken.text.charAt(1)=='x'){currToken.text+=c.toLowerCase()}elseif(c=='e'||c=='E'){if(currToken.text.indexOf('x')>=0||currToken.text.indexOf('e')>=0){P.H9(errors,'syntax','Invalid number. For exponents use 12e4, 12e+4 or 12e-4',i,1)c='0'}else c='e'currToken.text+=c}elseif("+-".indexOf(c)>=0){if(currToken.text.charAt(currToken.text.length-1)!='e'){tokens[tokens.length]=currTokencurrToken=new Object()currToken.type='op3'currToken.start=icurrToken.text=ctokens[tokens.length]=currTokencurrToken=null}else currToken.text+=c}else{tokens[tokens.length]=currTokencurrToken=nullP.H9(errors,'syntax','Invalid character within a number. valid numbers are in the form 123, 123.45, 12e3, 0x1f, 0b1101',i,1)}}elseif(c=='['){if(currToken)tokens[tokens.length]=currTokencurrToken={type:"name",start:i,text:c}inBrName=true}elseif(currToken&&currToken.type=='name'){if("0123456789.".indexOf(c)>=0||FP_VAR_CHARS.indexOf(c)>=0)currToken.text+=celseif("+-".indexOf(c)>=0){tokens[tokens.length]=currTokencurrToken=new Object()currToken.type='op3'currToken.start=icurrToken.text=ctokens[tokens.length]=currTokencurrToken=null}else{tokens[tokens.length]=currTokencurrToken=nullP.H9(errors,'syntax','Invalid character. Function names can have only English letters or underscores',i,1)}}elseif("+-".indexOf(c)>=0){if(currToken)tokens[tokens.length]=currTokencurrToken=new Object()currToken.type='op3'currToken.start=icurrToken.text=ctokens[tokens.length]=currTokencurrToken=null}elseif(!currToken){currToken=new Object()currToken.text=ccurrToken.start=iif("0123456789.".indexOf(c)>=0)currToken.type='number'elseif(FP_VAR_CHARS.indexOf(c)>=0)currToken.type='name'else{P.H9(errors,'syntax','This character is not supported',i,1)currToken=null}}}if(currToken){tokens[tokens.length]=currTokenif(currToken.type=="text")P.H9(errors,'syntax','Undelimited text string',currToken.start,1)elseif(currToken.type=="name"&&inBrName)P.H9(errors,'syntax','Undelimited reference name',currToken.start,1)}return res}P.H9=function(errors,type,message,start,length){var error=new Object()error.type=typeerror.message=messageerror.start=starterror.length=lengthif(errors.length>0&&errors[0].type=='value'){var t=errors[0]errors[0]=errorerror=t}errors[errors.length]=error}P.applyAllRules=function(tokens,errors){var startToken=new Object()startToken.type='start'var t=new Array()t[0]=startTokenP.append(tokens,t,0,tokens.length-1)tokens=tvar hasMatchingRule=truewhile(hasMatchingRule&&errors.length==0){var foundMatchingRule=falsefor(var r in FP_rules){var rule=FP_rules[r]var handler=rule[0]var types=rule[1]var matchedPos=-1for(var i=0;matchedPos<0&&i<=tokens.length-types.length;i++){var matched=truefor(var j=0;matched&&j<types.length;j++)matched=(types[j]==tokens[i+j].type)if(matched){matchedPos=itokens=eval("P.rule"+handler+"(tokens, i, errors)")}}if(matchedPos>=0){foundMatchingRule=truebreak}}hasMatchingRule=foundMatchingRule}if(errors.length==0&&(tokens.length!=2||tokens[1].type!='exp'))P.analyzeFinalSyntaxErrors(tokens,errors)return tokens[1]}P.analyzeFinalSyntaxErrors=function(tokens,errors){var tokenvar messagefor(var i=0;i<tokens.length-1;i++){if(tokens[i].type=='exp'&&tokens[i+1].type=='exp'){token=tokens[i+1]message="Expecting an operation before value"break}if(tokens[i].type.indexOf('op')==0&&tokens[i+1].type.indexOf('op')==0){token=tokens[i+1]message="Wrong position of operator"if(tokens[i].text=='*'&&tokens[i+1].text=='*')message+=". To computer power, use 2^3"break}}if(!token){var brstack=new Array()var brpos=-1for(var i=0;!token&&i<tokens.length;i++){if(tokens[i].type=='('||tokens[i].type=='call')brstack[++brpos]=ielseif(tokens[i].type==')'){if(brpos--<0){token=tokens[i]message="Close parenthesis does not have a matching open"}}}if(!token&&brpos>=0){token=tokens[brstack[brpos]]if(token.type=='(')message="Missing close of parenthesis"elsemessage="Missing close of function call"}}if(!token&&tokens[tokens.length-1].type.indexOf('op')==0){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -