(text)
| 64 | // ── Internal: parse `[func1(...), func2(...)]` or bare `func(...)` ────────── |
| 65 | |
| 66 | function _parseCallList(text) { |
| 67 | let s = text.trim(); |
| 68 | if (!s) return []; |
| 69 | // Strip outer brackets if the whole thing is a list (the documented form). |
| 70 | if (s.startsWith('[') && s.endsWith(']')) { |
| 71 | s = s.slice(1, -1).trim(); |
| 72 | } |
| 73 | if (!s) return []; |
| 74 | |
| 75 | const calls = []; |
| 76 | let pos = 0; |
| 77 | while (pos < s.length) { |
| 78 | // Skip whitespace and optional separating commas between calls. |
| 79 | while (pos < s.length && /[\s,]/.test(s[pos])) pos++; |
| 80 | if (pos >= s.length) break; |
| 81 | |
| 82 | const callStart = pos; |
| 83 | // Grab the function name — identifier chars only. |
| 84 | const nameMatch = s.slice(pos).match(/^([A-Za-z_][A-Za-z0-9_]*)\s*\(/); |
| 85 | if (!nameMatch) return []; |
| 86 | const name = nameMatch[1]; |
| 87 | pos += nameMatch[0].length; // now positioned just inside `(` |
| 88 | |
| 89 | // Walk forward until the matching `)`, respecting nested brackets and |
| 90 | // quoted strings. |
| 91 | const argsEnd = _findMatchingParen(s, pos); |
| 92 | if (argsEnd === -1) return []; |
| 93 | const argsText = s.slice(pos, argsEnd); |
| 94 | pos = argsEnd + 1; |
| 95 | |
| 96 | const args = _parseKwargs(argsText); |
| 97 | if (args == null) return []; // bail out on malformed args |
| 98 | calls.push({ name, arguments: args }); |
| 99 | |
| 100 | // Sanity: prevent infinite loop if regex/pos somehow didn't advance. |
| 101 | if (pos <= callStart) return calls; |
| 102 | } |
| 103 | return calls; |
| 104 | } |
| 105 | |
| 106 | // Walk from `start` forward, return index of the matching `)`. -1 if not found. |
| 107 | function _findMatchingParen(s, start) { |
no test coverage detected