154 lines
4.9 KiB
Plaintext
154 lines
4.9 KiB
Plaintext
<cfcomponent>
|
|
<cfset this.args = []/>
|
|
<cfproperty name="entity" type="string"/>
|
|
|
|
|
|
<cffunction name="init">
|
|
<cfargument name="entity" type="string" default="instance_operation_cfs_param"/>
|
|
<cfset this.entity=arguments.entity/>
|
|
<cfreturn this>
|
|
</cffunction>
|
|
|
|
<cffunction name="eval" returntype="any" access="public">
|
|
<cfargument name="expression" type="string"/>
|
|
<cfargument name="context" type="any"/>
|
|
|
|
<cfset var args=[]/>
|
|
<cfset parse(args, tokenize(arguments.expression),0)/>
|
|
<cfreturn computeExpression(args[1].function, args[1].args, arguments.context)/>
|
|
</cffunction>
|
|
|
|
<cffunction name="extractParams" returntype="any" access="public">
|
|
<cfargument name="expression" type="string"/>
|
|
|
|
<cfset var params=[]/>
|
|
<cfset parseForParams(params, tokenize(arguments.expression),0)/>
|
|
<cfreturn params/>
|
|
</cffunction>
|
|
|
|
<cffunction name="tokenize" returntype="array" access="private">
|
|
<cfargument name="expression" type="string"/>
|
|
|
|
<cfset var local={}/>
|
|
<cfset var pattern='"(.*?)"|\w+(\s*\.\s*\w+)*|\(|\)'/>
|
|
<cfset var res=rematch(pattern,expression)/>
|
|
<cfset var tokens = []/>
|
|
<cfloop array=#res# item="local.t">
|
|
<cfset tmp=trim(local.t)/>
|
|
<cfif len(tmp)>
|
|
<cfset arrayAppend(tokens,tmp)/>
|
|
</cfif>
|
|
</cfloop>
|
|
<cfreturn tokens/>
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="tokenType" output=false access="private">
|
|
<cfargument name="token"/>
|
|
|
|
<cfif token EQ "(">
|
|
<cfreturn "("/>
|
|
<cfelseif token EQ ")">
|
|
<cfreturn ")"/>
|
|
<cfelseif left(token,1) EQ '"'>
|
|
<cfreturn "string"/>
|
|
<cfelseif find(".",token)>
|
|
<cfreturn "variable"/>
|
|
<cfelse>
|
|
<cfreturn "function"/>
|
|
</cfif>
|
|
</cffunction>
|
|
|
|
|
|
|
|
<cffunction name="parse" returntype="numeric" access="private">
|
|
<cfargument name="args" type="array"/>
|
|
<cfargument name="tokens" type="array"/>
|
|
<cfargument name="positionBefore" type="numeric"/>
|
|
|
|
<cfset var i = arguments.positionBefore/>
|
|
<cfloop condition="++i LE arrayLen(arguments.tokens)">
|
|
<cfswitch expression=#tokenType(arguments.tokens[i])#>
|
|
<cfcase value="string">
|
|
<cfset arrayAppend(arguments.args,mid(arguments.tokens[i],2,len(arguments.tokens[i])-2))/>
|
|
</cfcase>
|
|
<cfcase value="variable">
|
|
<cfset arrayAppend( arguments.args, {"function"="getValue","args"=[tokens[i]]} )/>
|
|
</cfcase>
|
|
|
|
<cfcase value="function">
|
|
<cfset var f = {"function"=arguments.tokens[i],"args"=[]}/>
|
|
<cfif i GE arrayLen(arguments.tokens)>
|
|
<cfthrow message="unexpected end of expression"/>
|
|
</cfif>
|
|
<cfif #tokenType(arguments.tokens[++i])# NEQ "(">
|
|
<cfthrow message="function syntax incorrect" detail="function #arguments.tokens[i-1]#, token='#arguments.tokens[i]#' (#arrayToList(tokens,' ')#"/>
|
|
</cfif>
|
|
<cfset i = parse(f.args, arguments.tokens, i)/>
|
|
<cfset arrayAppend(arguments.args,f)/>
|
|
</cfcase>
|
|
<cfcase value=")">
|
|
<cfreturn i/>
|
|
</cfcase>
|
|
</cfswitch>
|
|
</cfloop>
|
|
</cffunction>
|
|
|
|
<cffunction name="parseForParams" returntype="numeric" access="private">
|
|
<cfargument name="args" type="array"/>
|
|
<cfargument name="tokens" type="array"/>
|
|
<cfargument name="positionBefore" type="numeric"/>
|
|
|
|
<cfset var i = arguments.positionBefore/>
|
|
<cfloop condition="++i LE arrayLen(arguments.tokens)">
|
|
<cfswitch expression=#tokenType(arguments.tokens[i])#>
|
|
<cfcase value="string">
|
|
</cfcase>
|
|
<cfcase value="variable">
|
|
<cfset arrayAppend( arguments.args, tokens[i] )/>
|
|
</cfcase>
|
|
<cfcase value="function">
|
|
<cfset var f = {"function"=arguments.tokens[i],"args"=[]}/>
|
|
<cfif i GE arrayLen(arguments.tokens)>
|
|
<cfthrow message="unexpected end of expression"/>
|
|
</cfif>
|
|
<cfif #tokenType(arguments.tokens[++i])# NEQ "(">
|
|
<cfthrow message="function syntax incorrect" detail="function #arguments.tokens[i-1]#, token='#arguments.tokens[i]#' (#arrayToList(tokens,' ')#"/>
|
|
</cfif>
|
|
<cfset i = parseForParams(f.args, arguments.tokens, i)/>
|
|
</cfcase>
|
|
<cfcase value=")">
|
|
<cfreturn i/>
|
|
</cfcase>
|
|
</cfswitch>
|
|
</cfloop>
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="computeExpression" returntype="any" access="private">
|
|
<cfargument name="function" type="string"/>
|
|
<cfargument name="args" type="array"/>
|
|
<cfargument name="context" type="any"/>
|
|
|
|
<cfloop index="i" from=1 to=#arrayLen(arguments.args)#>
|
|
<cfif isStruct(arguments.args[i]) AND structKeyExists(arguments.args[i],"function")>
|
|
<cfset arguments.args[i] = computeExpression(
|
|
arguments.args[i].function,
|
|
arguments.args[i].args,
|
|
arguments.context
|
|
) />
|
|
</cfif>
|
|
</cfloop>
|
|
<cfreturn executeFunction(arguments.function,arguments.args,arguments.context)/>
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="executeFunction" returntype="any" access="private">
|
|
<cfargument name="functionName"/>
|
|
<cfargument name="args" type="array"/>
|
|
<cfargument name="context" type="any"/>
|
|
<cfset var obj = createObject("component", arguments.context.component).init(arguments.context.keys, arguments.context.params)/>
|
|
<cfreturn invoke(obj, functionName, args)/>
|
|
</cffunction>
|
|
|
|
</cfcomponent> |