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
};
},