# ToC of functionList_pkg.py
#  by D@CC on 2022CMar28   Use cmd -md to create ToC, suffix . to defs 
# 30 m posNxFnUsed.py
# 32   def. posNxFnUsed(inStr,posIn0) :
# 35   def. posNxFnUsed_v1(inStr,posIn0,v="v03") :
# 128 m functionList.py
# 129   def. functionList(testStr) :
# 132   def. functionList_v1(testStr) :
# 196 m posNxFnUsed.py
# 199   def. posNxFnUsed(inStr,posIn0) :
# 202   def. posNxFnUsed_v2(inStr,posIn0) :
# 342 m posNxFnUsed_test.py
# 343   def. t2() :
# 425 m functionList.py
# 427   def. functionList(testStr="#:::",v="v02") :
# 431   def. functionList_v02(testStr,v) :
# 474 m functionList_test.py
# 475   def. mainroutine() :
# 504 m posNxFnUsed.py
# 506   def. posNxFnUsed(inStr,posIn0,v=3) :
# 510   def. posNxFnUsed_v3(inStr,posIn0,v) :
# 616 m t03.py
# 617   def. mainroutine() :
# 669 m t16.py
# 683   def. mainroutine() :
# 702 eof

#::: end of list by n.py v03

#::::::::::textpak=>posNxFnUsed.py

def posNxFnUsed(inStr,posIn0) :
    return posNxFnUsed_v1(inStr,posIn0)

def posNxFnUsed_v1(inStr,posIn0,v="v03") :

    # by D@CC on 2022CMar15

    print("posNxFnUsed_v02 on line 24 in ...._pkg.py")

    # beginning of def. posNxFnUsed() definition
    import re
    #print("into posNFU")
    #print("posIn0:",posIn0)

    # globals: uses globals List, bList
    # import re
    # parameters
    # arg1: statement to be anayzed
    # arg2: position of previous function name -1 (or 0 to initialize)

    # find the pos of the first char ( less 1) of the next function used in the inStr
    # returns the pos of the next function name (less 1) in the inStr statement
    # WARNING: does NOT find any function name beginning in first char of the statement
    # FIX:     call it by preceding the statement with a space.

    # start searching at position
    # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()  should return 15 pos of "str4("
    #      012345678901234567890123
    #      +0+(0+$$$+0+00+$$0$0(
    #                           00+++$0$$(00+$++00$(+
    #         (          +$$0$0(    +$0$$(         (
    #  valid regular pattern is "+$" any "0"  ????????????????

    # globals: uses globals List, bList
    # import re
    #
    if posIn0==0 :
        v1Patt="[_a-zA-Z]"       #"!" # valid first letter of a variable
        v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
        vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "("
        #       the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"       # matches all char except those listed, I think
        vFPatt=";\$[0\$]\("    #print("                           ;!!0!0(    ;!0!!(           ;!( ")
        
        #print("inStr  :  "+inStr)
        pattStr=inStr    
        pattStr=re.sub(v1Patt,"!",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(v2Patt,"0",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(vxPatt,";",pattStr)
        #print("pattStr:  "+pattStr)

        #print("             -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()")
        #print("                        ;!!0!0(    ;!0!!(           ;!( ")

        #print("             0123456789012345678901234567890123456789012345")
        #print("                       1         2         3         4")
        findPatt=";!{1}[!0]*\("  # find +$s  where s is any number of 0 or $ followed by (
        iter=re.finditer(findPatt,pattStr)
        global List
        List=[m.start(0) for m in iter]
        #print("List: ", List)
        global bList
        bList=[]
    #if end
    #print("b4 List")
    #print("List:",List)
    for n in List :
        #print("n:",n)
        item=testStr[n:].find("(") + n
        bList.append( item )
        #for end
        #print("bList:",bList)
        #print("posIn0:",posIn0)
        #  OK to here
    #for end                  --------------------------------
    for n in List :
        #print("n:",n)
        thisPos=n
        if posIn0==0:
            return thisPos   #returns and re-enters here
        else:
            if thisPos>posIn0:
                return thisPos
            else:
                continueDoh=True
                #keep looping
            #if end
        #if end
    #for end
    thisPos=-1
    #print("thisPos:",thisPos)
    return thisPos
#end def posNxFnUsed_v2
#                              #######################################

#::::::::::textpak=>functionList.py
def functionList(testStr) :
    return functionList_v1(testStr)

def functionList_v1(testStr) :
    # by D@CC on 2022CMar14

    # beginning of def. functionList.py definition in posNxFnUsed_test.py

    print("functionList on line 119 in ...._pkg.py")

    # or "$" "("  which is '+$[0$](' 
    # Use List=re.findall("+$[0functionList_test.py
    # Use List=re.search("+$[0$](", pattStr).start()
    #   will search for each matching pattern in the pattStr
    #     and return a list of the def. posNxFnUsed starting positions
    #procedure

    # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv
    # replace "_a-ZA-Z" with "_"  wher  e "_" is in "_a-ZA-Z"    ie valid first char equiv
    # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    # discard all to the right of "("
    # R-L find pos of first "_"
    # discard all to the left of "_"
    # fin what remains (it begins with a "_" first char equiv and ends with a "("
    # return the pos of what is found

    # beginning of def. functionList() definition

    # returns the next function name in an iteration list
    # of function calls in the given statment in arg1: testStr
    # calls posNxFnUsed()
    functionList=[]
    nPos=0

    many0s="000000000000000000000000000000"
    while nPos>=0 :
        #print("in main while")
        v="unknown"
        nex = posNxFnUsed(testStr, nPos,v)
        nextPos=int(nex)             #convert list element to string
        #print("in main af nextPos:",nextPos)
        if nextPos==-1 :
            # no more fNames found
            continueDoh=True
            break   #out of while loop
        else :
            textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #print("          0123456789012345678901234567890123456789012345")
            nextFnPos =nextPos
            # ok   to here                          --------------------------
            #print("nextFnPos: ",nextFnPos)
            nextParPos = testStr[nextFnPos:].find("(")+nextFnPos
            #print("nextParPos: posNxFnUsed_test.py",nextParPos)
            fName=testStr[nextFnPos+1:nextParPos]
            functionList.append(fName)
            #print("fName:"+fName)
            nPos= nextParPos
            yield(fName)
        #if end
        #keep looping
    #while end
#def end functionList_v1
#                                          ###########################################

#::::::::::textpak=>posNxFnUsed.py
# originally was included in posNxFnUsed_test.py

def posNxFnUsed(inStr,posIn0) :
    return posNxFnUsed_v2(inStr,posIn0)

def posNxFnUsed_v2(inStr,posIn0) :

    import re

    print("posNxFnUsed_v2 on line 179 in ...._pkg.py")

    # by D@CC on 2022CMar15
    # find the pos of the first char of the next function used in the inStr
    # start searching at position
    # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()  should return 15 pos of "str4("
    #      012345678901234567890123
    #      +0+(0+$$$+0+00+$$0$0(
    #                           00+++$0$$(00+$++00$(+
    #         (          +$$0$0(    +$0$$(         (
    #  valid regular pattern is "+$" any "0"  ????????????????
    v1Patt="[_a-zA-Z]"       #"$" # valid first letter of a variable
    v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
    vxPatt="[^_a-zA-Z0-9($]" #";" # invalid char. of a function name incl. "("
    #       the above vxPatt       # matches all char except those listed, I think
    vFPatt=";\$[0\$]*\("  
    # or "$" "("  which is '+$[0$](' 
    # Use List=re.findall("+$[0$](")
    # Use List=re.search("+$[0$](", pattStr).start()
    #   will search for each matching pattern in the pattStr
    #     and return a list of the starting positions
    #procedure

    # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv
    # replace "_a-ZA-Z" with "_"  wher  e "_" is in "_a-ZA-Z"    ie valid first char equiv
    # L-R find pos of first "0("
    # discard all to the right of "("
    # R-L find pos of first "_"
    # discard all to the left of "_"
    # fin what remains (it begins with a "_" first char equiv and ends with a "("
    # return the pos of what is found



    #                               
    #    ( 2022CMar22 D@CC needs to test the above pattern matches. ) 

    outPos=-1
    pos0=posIn0

    if pos0>len(inStr): return outPos
    tStr=inStr[pos0:]
    print("tStr:"+tStr)
    if tStr.find('(')>-1 :
        print("found another (")
        isFn=True
        parPos=inStr[pos0:].find("(")    #parenthesis Position
        print("parPos:",parPos)
        while parPos > -1 :
            print("into while")
            isFn=False
            if parPos==-1 :
                print("no (")

                print("returning outPos:",outPos)
                return outPos
            else:
                #do the work
                pattStr=inStr[pos0:pos0+parPos+1]
                #::::::::::textpak=>functionList.py
                print("b4  pattStr:"+pattStr)
                pattStr=re.sub(v1Patt,"$",pattStr)
                print("md1 pattStr:"+pattStr)
                pattStr=re.sub(v2Patt,"0",pattStr)
                print("md2 pattStr:"+pattStr)
                pattStr=re.sub(vxPatt,";",pattStr)
                print("af  pattStr:"+pattStr)
                findPatt=";\$[0\$]*\("
                print("findPatt:"+findPatt)
                try:                                            #fix DC
                    #List=re.findall(findPatt, pattStr)         #fix DC
                    List=re.search(findPatt, pattStr).start()   #fix DC
                except:                                         #fix DC
                    print("exception occurred during .search") #fix DC
                    List=None                                   #fix DC
                finally:  
                    continueDoh=True                    #fix DC
                #try end
                if List==None : 
                    print("parPos: ",parPos) #parPos is parentheses Position
                    print("List=None")
                    print("breaking out of while loop")
                    break    # out of while loop
                print("List:", List)
                posFromList=List
                smallStr=pattStr[posFromList:]
                print("smallStr: "+smallStr)
                pInSmallPos= smallStr.find("(")
                print("pInSmallPos: ",pInSmallPos)
                zparPos= posFromList+pInSmallPos
                print("zparPos: ",zparPos)
                if zparPos >-1 :
                    #                          #working here
                    #              was ("0$")
                    findNonRePatt=";\$[0\$]*\("
                    print("in nonPosNx.... zparPos>-1")
                    print("findNonRePatt: "+findNonRePatt)
                    v1Pos =pattStr.find("0$")  #finds leftmost but
                    #                          need to search R-L
                    print("v1Pos:",v1Pos)
                    if v1Pos> -1 :
                        isFn=True
                        print ("Fn found ")
                        outPos=pos0+parPos-zparPos+v1Pos+1
                        FnStr=inStr[outPos:outPos+2]
                        print("FnStr:"+FnStr)
                        return outPos
                    #if end
                else:
                    print("zparPos:",zparPos)
                    isFn=False
                #if end
                if isFn==False :     # still not found, loop to try again
                    print("checked FN:"+pattStr[0:parPos+1])
                    print("of inStr  :"+inStr[pos0:pos0+parPos+1])
                    # new parPos will be
                    parPos=pos0+parPos
                    deltaparPos=inStr[pos0+parPos+1:].find("(")    #parenthesis Position
                    if deltaparPos>-1:     # keep looping
                        newparPos=pos0+parPos+1+deltaparPos
                        print("inStr[parPos:]:"+inStr[0:newparPos+1])
                        parPos=newparPos
                        print("parPos:",parPos)
                    else:
                        parPos=-1
                        # stop the while loop
                #if end
            #if end
            print("while end loop to try again")
        #while end
    else:
        return outPos
    #if end
#def end posNxFnUsed_v2
#                                         ##############################

#::::::::::textpak=>posNxFnUsed_test.py
def t2() :
    # beginning of actual posNxFnUsed_test.py
    # this is t2.py
    import re

    # body of t2 is missing doh!

    n=0
    testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    v1Patt="[_a-zA-Z]"       #"$" # valid first letter of a variable
    v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
    vxPatt="[^_a-zA-Z0-9($!]" #";" # invalid char. of a function name incl. "("
    #       the above vxPatt       # matches all char except those listed, I think
    vFPatt=";\$[0\$]\("   
    #        012345678901234567890123
    while n>-1 :
        if False :
            # start with string pos 0
            m=posNxFnUsed(testStr,n)
            print ("m:",m)
            if m>-1 :
                bracPos=testStr[m:].find("(")
                print("bracPos:",bracPos)
                FnStr=testStr[m:m+bracPos]
                print("FnStr:"+FnStr+":")
                n=bracPos
            #if end
        #if end
        pattStr=testStr    
        print("b4  pattStr: "+pattStr)
        pattStr=re.sub(v1Patt,"!",pattStr)
        print("md1 pattStr: "+pattStr)
        pattStr=re.sub(v2Patt,"0",pattStr)
        print("md2 pattStr: "+pattStr)
        pattStr=re.sub(vxPatt,";",pattStr)
        print("af  pattStr: af"+pattStr)
        print("                           ;!!0!0(    ;!0!!(           ;!( ")
        print("             0123456789012345678901234567890123456789012345")
        print("                       1         2         3         4")
        #findPatt="+$[0$]("
        findPatt="\+[0\$]\("
        findPatt="0.0"           #finds 0c0 #::::::::::textpak=>posNxFnUsed.py
# originally was included in posNxFnUsed_test.py

def posNxFnUsedZZ(inStr,posIn0) :
    return posNxFnUsed_v2(inStr,posIn0)

def posNxFnUsed_v2(inStr,posIn0) :

    import re

    print("posNxFnUsed_v2 on line 179 in ...._pkg.py")

    # by D@CC on 2022CMar15
    # find the pos of the first char of the next function used in the inStr
    # start searching at position
    # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()  should return 15 pos of "str4("
    #      012345678901234567890123
    #      +0+(0+$$$+0+00+$$0$0(
    #                           00+++$0$$(00+$++00$(+
    #         (          +$$0$0(    +$0$$(         (
    #  valid regular pattern is "+$" any "0"  ????????????????
    v1Patt="[_a-zA-Z]"       #"$" # valid first letter of a variable
    v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
    vxPatt="[^_a-zA-Z0-9($]" #";" # invalid char. of a function name incl. "("
    #       the above vxPatt       # matches all char except those listed, I think
    vFPatt=";\$[0\$]*\("  
    # or "$" "("  which is '+$[0$](' 
    # Use List=re.findall("+$[0$](")
    # Use List=re.search("+$[0$](", pattStr).start()
    #   will search for each matching pattern in the pattStr
    #     and return a list of the starting positions
    #procedure

    # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv
    # replace "_a-ZA-Z" with "_"  wher  e "_" is in "_a-ZA-Z"    ie valid first char equiv
    # L-R find pos of first "0("
    # discard all to the right of "("
    # R-L find pos of first "_"
    # discard all to the left of "_"
    # fin what remains (it begins with a "_" first char equiv and ends with a "("
    # return the pos of what is found



    #                               
    #    ( 2022CMar22 D@CC needs to test the above pattern matches. ) 

    outPos=-1
    pos0=posIn0

    if pos0>len(inStr): return outPos
    tStr=inStr[pos0:]
    print("tStr:"+tStr)
    if tStr.find('(')>-1 :
        print("found another (")
        isFn=True
        parPos=inStr[pos0:].find("(")    #parenthesis Position
        print("parPos:",parPos)
        while parPos > -1 :
            print("into while")
            isFn=False
            if parPos==-1 :
                print("no (")

                print("returning outPos:",outPos)
                return outPos
            else:
                #do the work
                pattStr=inStr[pos0:pos0+parPos+1]
                #::::::::::textpak=>functionList.py
                print("b4  pattStr:"+pattStr)
                pattStr=re.sub(v1Patt,"$",pattStr)
                print("md1 pattStr:"+pattStr)
                pattStr=re.sub(v2Patt,"0",pattStr)
                print("md2 pattStr:"+pattStr)
                pattStr=re.sub(vxPatt,";",pattStr)
                print("af  pattStr:"+pattStr)
                findPatt=";\$[0\$]*\("
                print("findPatt:"+findPatt)
                try:                                            #fix DC
                    #List=re.findall(findPatt, pattStr)         #fix DC
                    List=re.search(findPatt, pattStr).start()   #fix DC
                except:                                         #fix DC
                    print("exception occurred during .search") #fix DC
                    List=None                                   #fix DC
                finally:  
                    continueDoh=True                    #fix DC
                #try end
                if List==None : 
                    print("parPos: ",parPos) #parPos is parentheses Position
                    print("List=None")
                    print("breaking out of while loop")
                    break    # out of while loop
                print("List:", List)
                posFromList=List
                smallStr=pattStr[posFromList:]
                print("smallStr: "+smallStr)
                pInSmallPos= smallStr.find("(")
                print("pInSmallPos: ",pInSmallPos)
                zparPos= posFromList+pInSmallPos
                print("zparPos: ",zparPos)
                if zparPos >-1 :
                    #                          #working here
                    #              was ("0$")
                    findNonRePatt=";\$[0\$]*\("
                    print("in nonPosNx.... zparPos>-1")
                    print("findNonRePatt: "+findNonRePatt)
                    v1Pos =pattStr.find("0$")  #finds leftmost but
                    #                          need to search R-L
                    print("v1Pos:",v1Pos)
                    if v1Pos> -1 :
                        isFn=True
                        print ("Fn found ")
                        outPos=pos0+parPos-zparPos+v1Pos+1
                        FnStr=inStr[outPos:outPos+2]
                        print("FnStr:"+FnStr)
                        return outPos
                    #if end
                else:
                    print("zparPos:",zparPos)
                    isFn=False
                #if end
                if isFn==False :     # still not found, loop to try again
                    print("checked FN:"+pattStr[0:parPos+1])
                    print("of inStr  :"+inStr[pos0:pos0+parPos+1])
                    # new parPos will be
                    parPos=pos0+parPos
                    deltaparPos=inStr[pos0+parPos+1:].find("(")    #parenthesis Position
                    if deltaparPos>-1:     # keep looping
                        newparPos=pos0+parPos+1+deltaparPos
                        print("inStr[parPos:]:"+inStr[0:newparPos+1])
                        parPos=newparPos
                        print("parPos:",parPos)
                    else:
                        parPos=-1
                        # stop the while loop
                #if end
            #if end
            print("while end loop to try again")
        #while end
    else:
        return outPos
    #if end
#def end posNxFnUsed_v2


#::::::::::textpak=>t2.py
def t2() :
    while False :
        #where c is any character
        findPatt="\+\$\$0\$0\("  # finds +$$0$0(
        findPatt="\+[\$]"        # finds +$  +$$ etc
        findPatt="\+[\$]\+"      # finds +$+
        findPatt="\+[0\$]\+"     # finds +c+ where c must be either 0 or $
        findPatt="\+\$[\$0][\$0][\$0][\$0]\("   # finds +$ssss( where s must be either $ or 0  
        findPatt="\+\$+\+"       # finds +$+ where s must be any number(>0) of $
        findPatt="\+[\$0]+\+"    # finds +$+ where s must be any number(>0) of $ or 0
        #                                               #  but not a mixture of $ and 0
        findPatt="\+\${1}"      # find +$  where there is only 1$
        findPatt=";!{1}[!0]*\("  # find +$s  where s is any number of 0 or $ followed by (
        #                          \+ is "+"   ! is "!"  [\!0] is either ! or 0
        #                   af        [\!0]* is any number (0 or >0) of "!" or "0" in any order
        #                          \( is "("
        #                          So this matches "+!sssss("  where s is ! or 0 in any order
        # 
        #List=re.search(findPatt, pattStr).start()
        #findPatt=""
        # can find 0 but not $ nor (  returns len+1
        #pattStr="This was this is"
        iter=re.finditer(findPatt,pattStr)
        indices=[m.start(0) for m in iter]
        print("List: ", indices)
        bList=[]
        for n in indices :
            #print("n:",n)
            item=testStr[n:].find("(")+n
            bList.append( item )
        #for end
        print("bList:",bList)        
        break
    #while end
    print("done")
    # end of t2.py
#def end t2

if __name__ == '__main__' : t2( )

# end of actual posNxFnUsed_test.py

#                                 --------------------------------
#::::::::::textpak=>functionList.py
# beginning of def. functionList.py definition from functionList_test.py
def functionList(testStr="#:::",v="v02") :
    if v=="?" : return "v02"
    return functionList_v02(testStr,v="v02")

def functionList_v02(testStr,v) :
    # by D@CC on 2022CMar28
    # returns a list of function calls in the input statment: inStr

    #print("functionList on line 416 in ...._pkg.py")

    functionList=[]
    nPos=0
    many0s="000000000000000000000000000000"
    while nPos>=0 :
        #print("in main while")
        nex = posNxFnUsed(testStr, nPos)
        nextPos=nex             #convert list element to string
        #print("in fList af nextPos:",nextPos)
        isNextPosGood=True
        if nextPos==-1 :   isNextPosGood=False
        if nextPos==None : isNextPosGood=False
        if isNextPosGood==False :
            # no more fNames found
            continueDoh=True
            break   #out of while loop
        else :
            textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #print("          0123456789012345678901234567890123456789012345")
            nextFnPos =nextPos
            # ok   to here                          --------------------------
            #print("nextFnPos: ",nextFnPos)
            nextParPos = testStr[nextFnPos:].find("(")+nextFnPos
            #print("nextParPos: ",nextParPos)
            fName=testStr[nextFnPos+1:nextParPos]
            functionList.append(fName)
            #print("fName:"+fName)
            nPos= nextParPos
            yield(fName)
        #if end
        #keep looping
    #while end

#def end functionList_v02.py definition

#::::::::::textpak=>functionList_test.py
def mainroutine() :
    # by D@CC on 2022CMar26
    # functionList_test.py
    from functionList_pkg import functionList, functionList_v
    from functionList_pkg import posNxFnUsed,  posNxFnUsed_v

    progName="functionList_test.py"
    #main program starts here
    #  calls:functionList.(
    # imports both functionList and posNxFnUsed from functionList_pkg.py

    print(" fL v:  "+functionList_v() )
    print(" pos v: "+posNxFnUsed_v()  )

    testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    print("testStr1:",testStr)
    for fName in functionList(testStr) :
        print("fName: "+fName)
    #for end
    #print("          012345678901234567890123456789012345678901234") #
    print("end of functionList_test.py v4")
    return
#def end mainroutine()
if __name__ == '__main__' : mainroutine( )



# end of functionList_test.py

#::::::::::textpak=>posNxFnUsed.py

def posNxFnUsed(inStr,posIn0,v=3) :
    if v=="?" :  return 3
    return posNxFnUsed_v3(inStr,posIn0,v=3)

def posNxFnUsed_v3(inStr,posIn0,v) :

    import re

    #if v=="?" : return 3

    # by D@CC on 2022CMar25
    #print("posNxFnUsed_v03 on line 501 in ...._pkg.py  v03")

    #print("into posNFU v03")
    #print("posIn0:",posIn0)
    # find the pos of the first char of the next function used in the inStr
    # start searching at position
    # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()  should return 15 pos of "str4("
    #      012345678901234567890123
    #      +0+(0+$$$+0+00+$$0$0(
    #                           00+++$0$$(00+$++00$(+
    #         (          +$$0$0(    +$0$$(         (
    #  valid regular pattern is "+$" any "0"  ????????????????
    if posIn0==0 :
        v1Patt="[_a-zA-Z]"       #"!" # valid first letter of a variable
        v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
        vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "("
        #       the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"       # matches all char except those listed, I think
        vFPatt="+$[0$]("    #print("                           ;!!0!0(    ;!0!!(           ;!( ")
        
        #print("inStr  :  "+inStr)
        pattStr=inStr    
        pattStr=re.sub(v1Patt,"!",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(v2Patt,"0",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(vxPatt,";",pattStr)
        #print("pattStr:  "+pattStr)

        #print("             -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()")
        #print("                        ;!!0!0(    ;!0!!(           ;!( ")

        #print("             0123456789012345678901234567890123456789012345")
        #print("                       1         2         3         4")
        findPatt=";!{1}[!0]*\("  # find +$s  where s is any number of 0 or $ followed by (
        iter=re.finditer(findPatt,pattStr)
        global List
        List=[m.start(0) for m in iter]
        #print("List: ", List)
        global bList
        bList=[]
        #print("bList before gen")
        for n in List :
            #print("n:",n)
            #item=testStr[n:].find("(") + n                 # BAD
            item=inStr[n:].find("(") + n
            bList.append( item )
            #for end

            #print("posIn0:",posIn0)
            #  OK to here
        #for end
        #print("bList:",bList)


    #if end


    #print("b4 List")
    #print("List:",List)

    for n in List :
        #print("n:",n)
        thisPos=n
        if posIn0==0:
            return thisPos   #returns and re-enters here
        else:
            if thisPos>posIn0:
                return thisPos
            else:
                continueDoh=True
                #keep looping
            #if end
        #if end
    #for end
    thisPos=-1
    #print("thisPos:",thisPos)
    return thisPos



    # or "$" "("  which is '+$[0$](' 
    # Use List=re.findall("+$[0$](")
    # Use List=re.search("+$[0$](", pattStr).start()
    #   will search for each matching pattern in the pattStr
    #     and return a list of the starting positions
    #procedure

    # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv
    # replace "_a-ZA-Z" with "_"  wher  e "_" is in "_a-ZA-Z"    ie valid first char equiv
    # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    # discard all to the right of "("
    # R-L find pos of first "_"
    # discard all to the left of "_"
    # fin what remains (it begins with a "_" first char equiv and ends with a "("
    # return the pos of what is found

#def end posNxFnUsed_v03()


#::::::::::textpak=>t03.py
def mainroutine() :
    from functionList_pkg import posNxFnUsed

    #Purpose to test posNxFnUsed.py v04
    #Then I created functionList.py 
    #             (which contains all this code and calls posNxFnUsed() )

    # by D@CC on 2022CMar25

    #main program t03.py starts here
    testStr="-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    print("testStr1:",testStr)
    print("          012345678901234567890123456789012345678901234") #
    print("                    1         2         3         4    ")
    nPos=0
    many0s="000000000000000000000000000000"
    while nPos>=0 :
        #print("in main while")
        nex = posNxFnUsed(testStr, nPos)
        nextPos=int(nex)             #convert list element to string
        #print("in main af nextPos:",nextPos)
        if nextPos==-1 :
            continueDoh=True
            break   #out of while loop
        else :
            textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #textStr=testStr[0:]
            #print("textStr:  "+textStr)

            nextFnPos =nextPos
            # ok   to here                          --------------------------
            #print("nextFnPos: ",nextFnPos)
            nextParPos = testStr[nextFnPos:].find("(")+nextFnPos
            #print("nextParPos: ",nextParPos)
            fName=testStr[nextFnPos+1:nextParPos]
            print("fName:"+fName)
            nPos= nextParPos
        #if end
        #keep looping
    #while end
    print("end of t3.py")

    print("done")
    # end of t3
#end def mainroutine()

if __name__ == '__main__' : mainroutine( )

#end def t03.py
#end of pkg on 2022CMar25    

#::::::::::textpak=>t16.py
#def functionList(testStr="",v="v02") :
    #if v=="?" : return "v02"
    #return functionList_v02(testStr,v)
#def end

#def functionList_v02(testStr, v) :
    # by D@CC on 2022CMar26
    #. . . .
    #. . . . function definition statements go here
    # . . . .
    #return anyValue
#def end functionList

def mainroutine() :
    #main program used to test the functionList function

    from functionList_pkg import functionList, posNxFnUsed

    line="abc = aStr(1000*unixTime() ) + bigI(333)"
    print("line:"+line+":")
    fList=functionList(line)
    for x in fList : 
        print(x, end=" " )
    #for end
    print()
    vsnStr=str( functionList("","?") )
    print( "vsn of functionList:  "+ vsnStr )
    vsnStr=str( posNxFnUsed("",0,"?") )
    print( "vsn of posNxFnUsed:  "+ vsnStr )
    return
#def end
if __name__ == '__main__'  : mainroutine()
#end of t.py v16

#::::::::::textpak=>posNxFnUsed.py

def posNxFnUsed(inStr,posIn0,v=4) :
    pass;                   vv=4
    returnValue = posNxFnUsed_v4(inStr,posIn0)
    # only need to edit the vsn # in 4 places (& at the end if desired)
    if v=="?" : return returnValue,vv
    else :      return returnValue
    #if end

def posNxFnUsed_v4(inStr,posIn0) :

    import re

    # by D@CC on 2022DApr02
    #print("posNxFnUsed_v04 on line 867 in ...._pkg.py  v04")

    #print("into posNFU v04")
    #print("posIn0:",posIn0)
    # find the pos of the first char of the next function used in the inStr
    # start searching at position
    # e.g. -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()  should return 15 pos of "str4("
    #      012345678901234567890123
    #      +0+(0+$$$+0+00+$$0$0(
    #                           00+++$0$$(00+$++00$(+
    #         (          +$$0$0(    +$0$$(         (
    #  valid regular pattern is "+$" any "0"  ????????????????
    if posIn0==0 :
        v1Patt="[_a-zA-Z]"       #"!" # valid first letter of a variable
        v2Patt="[_a-zA-Z0-9]"    #"0" # valid subseq. letter of a variable
        vxPatt="[^_a-zA-Z0-9(!]" #";" # invalid char. of a function name incl. "("
        #       the above vxPatt"-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"       # matches all char except those listed, I think
        vFPatt="+$[0$]("    #print("                           ;!!0!0(    ;!0!!(           ;!( ")
        
        #print("inStr  :  "+inStr)
        pattStr=inStr    
        pattStr=re.sub(v1Patt,"!",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(v2Patt,"0",pattStr)
        #print("pattStr:  "+pattStr)
        pattStr=re.sub(vxPatt,";",pattStr)
        #print("pattStr:  "+pattStr)

        #print("             -3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()")
        #print("                        ;!!0!0(    ;!0!!(           ;!( ")

        #print("             0123456789012345678901234567890123456789012345")
        #print("                       1         2         3         4")
        findPatt=";!{1}[!0]*\("  # find +$s  where s is any number of 0 or $ followed by (
        iter=re.finditer(findPatt,pattStr)
        global List
        List=[m.start(0) for m in iter]
        #print("List: ", List)
        global bList
        bList=[]
        #print("bList before gen")
        for n in List :
            #print("n:",n)
            #item=testStr[n:].find("(") + n                 # BAD
            item=inStr[n:].find("(") + n
            bList.append( item )
            #for end

            #print("posIn0:",posIn0)
            #  OK to here
        #for end
        #print("bList:",bList)


    #if end


    #print("b4 List")
    #print("List:",List)

    for n in List :
        #print("n:",n)
        thisPos=n
        if posIn0==0:
            return thisPos   #returns and re-enters here
        else:
            if thisPos>posIn0:
                return thisPos
            else:
                continueDoh=True
                #keep looping
            #if end
        #if end
    #for end
    thisPos=-1
    #print("thisPos:",thisPos)
    return thisPos



    # or "$" "("  which is '+$[0$](' 
    # Use List=re.findall("+$[0$](")
    # Use List=re.search("+$[0$](", pattStr).start()
    #   will search for each matching pattern in the pattStr
    #     and return a list of the starting positions
    #procedure

    # replace "_a-ZA-Z0-9" with "0" where "0" is in "_a-ZA-Z0-9" ie valid subseq char equiv
    # replace "_a-ZA-Z" with "_"  wher  e "_" is in "_a-ZA-Z"    ie valid first char equiv
    # L-R find pos of first "0(""-3*(4+var+3.40+st2r4(27))+p2hi(35+a)+12b()-a()"
    # discard all to the right of "("
    # R-L find pos of first "_"
    # discard all to the left of "_"
    # fin what remains (it begins with a "_" first char equiv and ends with a "("
    # return the pos of what is found

#def end posNxFnUsed_v4()

#::::::::::textpak=>t17.py
#def functionList(testStr="",v="v02") :
    #if v=="?" : return "v02"
    #return functionList_v02(testStr,v)
#def end

#def functionList_v02(testStr, v) :
    # by D@CC on 2022CMar26
    #. . . .
    #. . . . function definition statements go here
    # . . . .
    #return anyValue
#def end functionList

def mainroutine() :
    #main program used to test the functionList function

    from functionList_pkg import functionList, posNxFnUsed

    line="abc = aStr(1000*unixTime() ) + bigI(333)"
    print("line:"+line+":")
    fList=functionList(line)
    for x in fList : 
        print(x, end=" " )
    #for end
    print()
    vMain=17
    print("vsn of t.py: ",vMain)
    vsnStr=str( functionList("","?") )
    print( "vsn of functionList:  "+ vsnStr )
    vsnStr=str( posNxFnUsed("",0,"?")[1] )
    print( "vsn of posNxFnUsed:  "+ vsnStr )
    return
#def end
if __name__ == '__main__'  : mainroutine()
#end of t17.py

#                                 --------------------------------
#::::::::::textpak=>functionList.py
# beginning of def. functionList.py definition 
def functionList(testStr="#:::",v=3) :
    pass;                      vv=3
    returnValue =  functionList_v03(testStr)
    if v=="?" : return returnValue,vv
    else :      return returnValue
    #if end

def functionList_v03(testStr) :
    # by D@CC on 2022DApr02
    # returns a list of function calls in the input statment: inStr

    #print("functionList v03 on line 1017 in ...._pkg.py")

    functionList=[]
    nPos=0
    many0s="000000000000000000000000000000"
    while nPos>=0 :
        #print("in main while")
        nex = posNxFnUsed(testStr, nPos)
        nextPos=nex             #convert list element to string
        #print("in fList af nextPos:",nextPos)
        isNextPosGood=True
        if nextPos==-1 :   isNextPosGood=False
        if nextPos==None : isNextPosGood=False
        if isNextPosGood==False :
            # no more fNames found
            continueDoh=True
            break   #out of while loop
        else :
            textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #textStr=testStr[0:]
            #print("textStr:  "+textStr)
            #print("          0123456789012345678901234567890123456789012345")
            nextFnPos =nextPos
            # ok   to here                          --------------------------
            #print("nextFnPos: ",nextFnPos)
            nextParPos = testStr[nextFnPos:].find("(")+nextFnPos
            #print("nextParPos: ",nextParPos)
            fName=testStr[nextFnPos+1:nextParPos]
            functionList.append(fName)
            #print("fName:"+fName)
            nPos= nextParPos
            yield(fName)
        #if end
        #keep looping
    #while end

#def end functionList_v03.py definition
