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