findSection: function()

in xooki.js [312:369]


    findSection: function(/*string*/str, /*string or regexp*/open, /*string or regexp*/close, /*number, optional*/from) {
        // finds a section delimited by open and close tokens in the given string
        // the algorithm looks for matching open and close tokens
        // the returned object has the following properties:
        //   outerStart: the index in str where the first open token was found
        //   innerStart: the index in str just after the found open token
        //   innerEnd: the index in str where the matching close token was found
        //   outerEnd: the index in str just after the matching close token
        //   children: an array of similar objects if nested sections where found
        // if no section is found (no open token, an open token with no matching 
        // close token, or a close token before an open token), null is returned
        //
        // for instance if open=='(' and close==')' then the section will find
        // a section delimited by the first found open parenthesis and the matching
        // close parentethis, taking into account other opening parentethis
        // examples:
        // findSection("a(test)b", "(", ")") == {outerStart: 1, innerStart:2, innerEnd:6, outerEnd:7, children:[]}
        // findSection("a(te(s)(t))b", "(", ")") == {outerStart: 1, innerStart:2, innerEnd:10, outerEnd:11, 
        //      children:[
        //          {outerStart: 4, innerStart:5, innerEnd:6, outerEnd:7, children:[]},
        //          {outerStart: 7, innerStart:8, innerEnd:9, outerEnd:10, children:[]}
        //      ]}
        
        var openResult = this.find(str, open, from);        
        if (openResult == null) {
            return null;
        }
        var closeResult = this.find(str, close, from);        
        if (closeResult == null || closeResult.begin < openResult.end) {
            return null;
        }
        if (openResult.end <= openResult.begin || closeResult.end <= closeResult.begin) {
            // empty match are not allowed
            return null;
        }
        
        var children = [];
        var child = this.findSection(str, open, close, openResult.end);
        while (child != null) {
            if (child.outerEnd > closeResult.begin) {
                closeResult = this.find(str, close, child.outerEnd);        
                if (closeResult == null) {
                    // unmatched open token
                    return null;
                }
            }
            children.push(child);
            child = this.findSection(str, open, close, child.outerEnd);
        }

        return {
            outerStart: openResult.begin,
            innerStart: openResult.end,
            innerEnd: closeResult.begin,
            outerEnd: closeResult.end,
            children: children
        };        
    },