public final class BalancedGroup
extends Object
A node in the tree of balanced groups extracted by find, also exposed on CharSequence via StringGroovyMethods.findBalancedGroups.
Java's Pattern has no .NET-style balancing groups
((?<name1-name2>…)). This type is both the structured result and the
entry point for Groovy's stack-based equivalent: each node is one successfully
closed span, with immediately nested spans as children (richer than .NET's flat
CaptureCollection on a single group).
Offsets mirror .NET Capture.Index / Length: getStart()
and getEnd() describe the range of getMatchedString() in the
original input (half-open [start, end)). getFullStart() /
getFullEnd() always cover the complete pair including delimiters,
even when MatchOptions.includeEdges is false (comparable to
knowing both the balancing capture and the open/close match positions).
Parent links and nesting depth are wired when a node is attached as a child
of another node during construction; root nodes have a null parent
and depth 0. Prefer find (or the GDK methods on
CharSequence) as the public entry point — constructors are
package-private because they perform one-shot parent wiring.
| Modifiers | Name | Description |
|---|---|---|
record |
BalancedGroup.MatchOptions |
Options controlling balanced-group matching. |
| Type Params | Return Type | Name and description |
|---|---|---|
|
public static List<BalancedGroup> |
find(CharSequence text, String openRegex, String closeRegex)Finds balanced groups using MatchOptions.defaults. |
|
public static List<BalancedGroup> |
find(CharSequence text, String openRegex, String closeRegex, BalancedGroup.MatchOptions options)Finds balanced (nested) groups in text and returns them as a forest of
BalancedGroup nodes. |
|
public List<BalancedGroup> |
getChildren()Returns the immediately nested balanced groups. |
|
public int |
getDepth()Nesting depth of this node (0 for a root). |
|
public int |
getEnd()End index of getMatchedString() in the original input (exclusive). |
|
public int |
getFullEnd()End index of the full balanced pair, always including the closing delimiter (exclusive). |
|
public int |
getFullStart()Start index of the full balanced pair, always including the opening delimiter. |
|
public int |
getLength()Length of getMatchedString() ( end - start). |
|
public String |
getMatchedString()Returns the text captured for this group. |
|
public BalancedGroup |
getParent()Returns the enclosing group, if any. |
|
public int |
getStart()Start index of getMatchedString() in the original input (inclusive). |
|
public String |
toString()Returns the matched text of this group. |
Finds balanced groups using MatchOptions.defaults.
text - text to scanopenRegex - regex for an opening delimiter (must not be empty)closeRegex - regex for a closing delimiter (must not be empty) Finds balanced (nested) groups in text and returns them as a forest of
BalancedGroup nodes.
Relation to .NET balancing groups: .NET keeps a capture stack per
named group, pushes with (?<Open>…), pops with
(?<-Open>…) or (?<Between-Open>…), and can require a
fully empty stack via (?(Open)(?!)). This method uses the same
push/pop idea on an explicit stack, but returns a hierarchical tree
(children + parent) rather than a flat CaptureCollection, and
always extracts every completed span in one left-to-right scan.
Algorithm: matches of a combined tokenizer
(IGNORE? / OPEN / CLOSE) are consumed in order.
Nesting is resolved by the stack, not by recursive regex, so balancing
itself does not introduce ReDoS; cost is proportional to the number of
tokenizer hits times the cost of the user-supplied patterns. Compiled
tokenizers are cached (bounded LRU).
Fault tolerance (differs from a strict .NET
(?(Open)(?!)) pattern): unmatched closers are ignored; unclosed
openers are dropped at end-of-input, but groups already completed inside
them are promoted outward ("orphan rescue").
Named capturing groups OPEN, CLOSE, and IGNORE are
reserved for the tokenizer; do not use those names inside
openRegex, closeRegex, or MatchOptions.ignoreRegex.
text, openRegex, or closeRegex is nullopenRegex or closeRegex is emptytext - text to scanopenRegex - regex for an opening delimiter (must not be empty)closeRegex - regex for a closing delimiter (must not be empty)options - match options; null means MatchOptions.defaultsReturns the immediately nested balanced groups.
null) for a leafNesting depth of this node (0 for a root). Computed once when the parent link is wired; O(1).
End index of getMatchedString() in the original input (exclusive).
Length is getEnd() - getStart(), like .NET Capture.Length.
End index of the full balanced pair, always including the closing delimiter (exclusive).
Start index of the full balanced pair, always including the opening delimiter.
Length of getMatchedString() (end - start).
Returns the text captured for this group.
null); may include or exclude boundary
delimiters depending on MatchOptions.includeEdgesReturns the enclosing group, if any.
null if this is a root Start index of getMatchedString() in the original input (inclusive).
Comparable to .NET Capture.Index.
Returns the matched text of this group.