Class BalancedGroup

java.lang.Object
groovy.util.regex.BalancedGroup

public final class BalancedGroup extends Object
A node in the tree of balanced groups extracted by find(java.lang.CharSequence, java.lang.String, java.lang.String), also exposed on CharSequence via StringGroovyMethods.findBalancedGroups(CharSequence, String, String).

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 BalancedGroup.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(java.lang.CharSequence, java.lang.String, java.lang.String) (or the GDK methods on CharSequence) as the public entry point — constructors are package-private because they perform one-shot parent wiring.

Since:
6.0.0
  • Method Details

    • find

      public static List<BalancedGroup> find(CharSequence text, String openRegex, String closeRegex)
      Finds balanced groups using BalancedGroup.MatchOptions.defaults().
      Parameters:
      text - text to scan
      openRegex - regex for an opening delimiter (must not be empty)
      closeRegex - regex for a closing delimiter (must not be empty)
      Returns:
      unmodifiable list of outermost groups (empty if none)
      Since:
      6.0.0
      See Also:
    • find

      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.

      Relation to .NET balancing groups: .NET keeps a capture stack per named group, pushes with (?&lt;Open&gt;…), pops with (?&lt;-Open&gt;…) or (?&lt;Between-Open&gt;…), 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 BalancedGroup.MatchOptions.ignoreRegex().

      Parameters:
      text - text to scan
      openRegex - regex for an opening delimiter (must not be empty)
      closeRegex - regex for a closing delimiter (must not be empty)
      options - match options; null means BalancedGroup.MatchOptions.defaults()
      Returns:
      unmodifiable list of outermost groups (empty if none)
      Throws:
      NullPointerException - if text, openRegex, or closeRegex is null
      IllegalArgumentException - if openRegex or closeRegex is empty
      PatternSyntaxException - if a supplied pattern is not a valid Java regex
      Since:
      6.0.0
    • getMatchedString

      public String getMatchedString()
      Returns the text captured for this group.
      Returns:
      the matched text (never null); may include or exclude boundary delimiters depending on BalancedGroup.MatchOptions.includeEdges()
    • getStart

      public int getStart()
      Start index of getMatchedString() in the original input (inclusive). Comparable to .NET Capture.Index.
      Returns:
      the start offset
    • getEnd

      public int getEnd()
      End index of getMatchedString() in the original input (exclusive). Length is getEnd() - getStart(), like .NET Capture.Length.
      Returns:
      the end offset
    • getLength

      public int getLength()
      Length of getMatchedString() (end - start).
      Returns:
      the length
    • getFullStart

      public int getFullStart()
      Start index of the full balanced pair, always including the opening delimiter.
      Returns:
      the full-span start offset
    • getFullEnd

      public int getFullEnd()
      End index of the full balanced pair, always including the closing delimiter (exclusive).
      Returns:
      the full-span end offset
    • getChildren

      public List<BalancedGroup> getChildren()
      Returns the immediately nested balanced groups.
      Returns:
      an unmodifiable list of children; empty (never null) for a leaf
    • getParent

      public BalancedGroup getParent()
      Returns the enclosing group, if any.
      Returns:
      the parent node, or null if this is a root
    • getDepth

      public int getDepth()
      Nesting depth of this node (0 for a root). Computed once when the parent link is wired; O(1).
      Returns:
      the number of ancestors
    • toString

      public String toString()
      Returns the matched text of this group.
      Overrides:
      toString in class Object
      Returns:
      the same value as getMatchedString()