cleanup: trim helper parser commentary
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<cfcomponent>
|
||||
<!--- разбирает и вычисляет выражения из вложенных функций для зависимых CFS параметров --->
|
||||
<cfset this.args = []/>
|
||||
<cfproperty name="entity" type="string"/>
|
||||
|
||||
@@ -12,25 +11,7 @@
|
||||
|
||||
<cffunction name="eval" returntype="any" access="public">
|
||||
<cfargument name="expression" type="string"/>
|
||||
<cfargument name="context" type="any"/><!--- {component,key,params} --->
|
||||
<!--- Если параметр сохранен, то вся нужная информация может быть получена по его ключу. Просто и изящно, но.
|
||||
Но если параметр, операция, инстанс не сохранены в базе - то нам придется предоставить с контекстом все, что может понадобиться
|
||||
При этом контекст кажется вывернутым наизнанку: не инстанс / содержащий операции /содержащие параметры, а параметр, что-то знающий про операцию и инстанс
|
||||
А бывают нужны
|
||||
- параметры-зависимости (мы их специально перечисляем в отдельном поле)
|
||||
- псевдопараметр resourceRealm, может наследоваться от предка (предок определен как раз параметром, инстансу существовать не обязательно) (нужно ли декларировать параметр-ссылку на предка в зависимостях?)
|
||||
- стейт (есть только у созданного инстанса и вычисляется по ключу instance_uid)
|
||||
Еще имя компонента
|
||||
Например, контекст может содержать инстанс компонента, имя компонента и дополнительные параметры
|
||||
По имени компонента мы можем сразу создать пустой (неинициализированный инстанс)
|
||||
Ну и как ему передать параметры? У инстанса есть массив параметров. Точнее, map<any> (удобнее адресоваться именами). Так и передать. А дальше ресолвить по мере сил (это работа самого компонента)
|
||||
Контекст сам выглядит компонентом, но поскольку его использование кажется локальным, мы можем взять произвольную структуру
|
||||
Если компонент-параметр инстанциирован, мы можем получить из БД значения всех соседних параметров.
|
||||
Но даже если компонент инстанциирован, непосредственно переданные значения параметров должны иметь приоритет перед сохраненными (мы сначала редактируем зависимые параметры, и только потом одним чохом записываем коллекцию параметров в БД
|
||||
Логично использовать ленивую инициализацию
|
||||
В этом рассуждении я упустил такой момент. Конкретно для параметра (хотя я хотел абстрагироваться от сущности) есть родительские сущности Операция и Инстанс,
|
||||
и какая-то из них может быть задана. Это не так же точно, как собственный ключ, но несет некоторую полезную информацию. Может быть, передавать массив или map ключей?
|
||||
--->
|
||||
<cfargument name="context" type="any"/>
|
||||
|
||||
<cfset var args=[]/>
|
||||
<cfset parse(args, tokenize(arguments.expression),0)/>
|
||||
@@ -44,17 +25,6 @@
|
||||
<cfset parseForParams(params, tokenize(arguments.expression),0)/>
|
||||
<cfreturn params/>
|
||||
</cffunction>
|
||||
|
||||
<!---
|
||||
expression parse-evaluate
|
||||
для навигации по стейтам и конфигурациям платформ
|
||||
*** размещаем здесь временно. скорее всего, парсер надо оформить компонентом
|
||||
Отдельный вопрос, как адресоваться к аргументам. Или парсер может возвращать функцию, которая будет работать в адресном пространстве параметра? Тогда ему никакой доступ не нужен.
|
||||
Было бы интересно сериализовывать скомпилированное выражение
|
||||
Но сейчас все вычисления происходят в самом парсере
|
||||
*** сначала мы хотим отработать генерацию зависимых списков в deck-tool
|
||||
*** нужно обрабатывать исключения разбора
|
||||
--->
|
||||
|
||||
<cffunction name="tokenize" returntype="array" access="private">
|
||||
<cfargument name="expression" type="string"/>
|
||||
@@ -80,20 +50,21 @@ expression parse-evaluate
|
||||
<cfreturn "("/>
|
||||
<cfelseif token EQ ")">
|
||||
<cfreturn ")"/>
|
||||
<cfelseif left(token,1) EQ '"'><!--- не вдаваясь в лишние подробности... внятнее было парсить строку посимвольно --->
|
||||
<cfelseif left(token,1) EQ '"'>
|
||||
<cfreturn "string"/>
|
||||
<cfelseif find(".",token)>
|
||||
<cfreturn "variable"/>
|
||||
<cfelse>
|
||||
<cfreturn "function"/><!--- будем проще: если дальше не найдем аргументов - бросим исключение --->
|
||||
<cfreturn "function"/>
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction name="parse" returntype="numeric" access="private"><!--- returns last token position --->
|
||||
<cfargument name="args" type="array"/><!--- puts here parsed tree with nested functions --->
|
||||
|
||||
<cffunction name="parse" returntype="numeric" access="private">
|
||||
<cfargument name="args" type="array"/>
|
||||
<cfargument name="tokens" type="array"/>
|
||||
<cfargument name="positionBefore" type="numeric"/><!--- before first processed token, initially 0 --->
|
||||
<cfargument name="positionBefore" type="numeric"/>
|
||||
|
||||
<cfset var i = arguments.positionBefore/>
|
||||
<cfloop condition="++i LE arrayLen(arguments.tokens)">
|
||||
@@ -110,29 +81,28 @@ expression parse-evaluate
|
||||
<cfif i GE arrayLen(arguments.tokens)>
|
||||
<cfthrow message="unexpected end of expression"/>
|
||||
</cfif>
|
||||
<cfif #tokenType(arguments.tokens[++i])# NEQ "("><!--- skip opening parenthesis ---><!--- *** possible out of range --->
|
||||
<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/><!--- returns last token position --->
|
||||
<cfreturn i/>
|
||||
</cfcase>
|
||||
</cfswitch>
|
||||
</cfloop>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="parseForParams" returntype="numeric" access="private"><!--- returns last token position --->
|
||||
<cfargument name="args" type="array"/><!--- puts here parsed params --->
|
||||
<cffunction name="parseForParams" returntype="numeric" access="private">
|
||||
<cfargument name="args" type="array"/>
|
||||
<cfargument name="tokens" type="array"/>
|
||||
<cfargument name="positionBefore" type="numeric"/><!--- before first processed token, initially 0 --->
|
||||
<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">
|
||||
<!--- skip ---><!--- <cfset arrayAppend(arguments.args,mid(arguments.tokens[i],2,len(arguments.tokens[i])-2))/>--->
|
||||
<cfcase value="string">
|
||||
</cfcase>
|
||||
<cfcase value="variable">
|
||||
<cfset arrayAppend( arguments.args, tokens[i] )/>
|
||||
@@ -142,27 +112,26 @@ expression parse-evaluate
|
||||
<cfif i GE arrayLen(arguments.tokens)>
|
||||
<cfthrow message="unexpected end of expression"/>
|
||||
</cfif>
|
||||
<cfif #tokenType(arguments.tokens[++i])# NEQ "("><!--- skip opening parenthesis ---><!--- *** possible out of range --->
|
||||
<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)/>
|
||||
<!--- <cfset arrayAppend(arguments.args,f)/> --->
|
||||
</cfcase>
|
||||
<cfcase value=")">
|
||||
<cfreturn i/><!--- returns last token position --->
|
||||
<cfreturn i/>
|
||||
</cfcase>
|
||||
</cfswitch>
|
||||
</cfloop>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction name="computeExpression" returntype="any" access="private"><!--- вычисление выражения снаружи внутрь --->
|
||||
<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)#><!--- тонкость: цикл item по массиву копирует элемент, а нам нужно его менять по ссылке --->
|
||||
<cfif isStruct(arguments.args[i]) AND structKeyExists(arguments.args[i],"function")> <!--- и все равно это ненадежный способ отличать функцию от простого значения --->
|
||||
<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,
|
||||
@@ -174,13 +143,11 @@ expression parse-evaluate
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction name="executeFunction" returntype="any" access="private"><!--- эта функция обращается к прикладным функциям, должна их видеть --->
|
||||
<cfargument name="functionName"/><!--- а ссылку на функцию передать не получится? (замыкание даже наверно не нужно) --->
|
||||
<cffunction name="executeFunction" returntype="any" access="private">
|
||||
<cfargument name="functionName"/>
|
||||
<cfargument name="args" type="array"/>
|
||||
<cfargument name="context" type="any"/>
|
||||
<!--- <cfdump var=#arguments#/> --->
|
||||
<cfset var obj = createObject("component", arguments.context.component).init(arguments.context.keys, arguments.context.params)/>
|
||||
<!--- <cfdump var=#obj# abort=true/> --->
|
||||
<cfreturn invoke(obj, functionName, args)/>
|
||||
</cffunction>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user