A hard challenge anyone?
David Bovill
david at openpartnership.net
Sat Feb 3 10:09:47 EST 2007
This is an example of a general nesting problem. take a line of Revolution
code which contains a few nested functions:
put aFunction(bFunction(1)) + cFunction(dFunction(eFunction(fFunction(2))))
The function I would like to write ("extractFunctionCallsOfLine") is one
which takes a line or Rev code like the one above and returns the names of
the four function calls:
aFunction
bFunction
cFunction
dFunction
eFunction
fFunction
I have come across this "design pattern" a few times and never been able to
successfully deal with it - which is strange as it is fairly common / basic?
It is the basic situation where you need to "parse" a nested piece of marked
up text. It comes up with XML - but we can use Revs externals to help - but
it also comes up in other situations.
The problems is that the script has to figure out if what an actual node is
- that is it needs to ignore and nested nodes and grab till the end of the
node. In the past I have written functions which use offset to count
forwards for opening and closing brackets - while they start simple these
functions grow to monsters that never quite work 100% Then I tried regular
expressions, but not quite got the hang of greedy - non-greedy etc and any
way i am not sure they are able to figure out exactly what a "node" is and
extract it by themselves.
Well here is an the function that I have at the moment:
on script_ExtractFunctionCallOfLine scriptLine, @fName, @bracketedStuff
-- could test recursively for nested functions here
put word 2 to -1 of scriptLine into scriptLine
put "(.+)[^\(]*(\(.*\)).*" into regularExpression
if matchText(scriptLine, regularExpression, fName, bracketedStuff) is
true then
put word -1 of fName into fName # there is a space bug in regex
if script_DictionaryTerm(fName) is true then
return false
else if fName is "(" then
return false
else
return true
end if
else
put empty into fName
put empty into bracketedStuff
return false
end if
end script_ExtractFunctionCallOfLine
The idea is to look for a function call in a script - and if so extract the
name of the function and the stuff inside the brackets. It seems that
providing we have already stripped out any comments and quoted text - see
function below:
on script_CleanForCalls @someScript
script_ExtractAndStripMultiLineComments someScript, mulitLineComment
put text_Strip(someScript, "\", space) into someScript
put text_StripQuoted(someScript, "•••") into someScript
replace "(" with " ( " in someScript
replace ")" with " ) " in someScript
end script_CleanForCalls
... we can know there is a function by looking for "(....)" and getting the
word before the brackets as the function name. This seems to work with a few
other checks on the function name returned.
The problem is when the Rev gurus start writing nested function calls like:
put someFunction(anotherFunction("Test"))
So how do i extract one "node" - that is everything inside the first
topLevel brakets - this technique would then allow the construction of a
recursive function to extract all the function names however many nested
levels there were - perhaps there is another way?
More information about the use-livecode
mailing list