Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Balanced braces/brackets/parens regex in Ruby

Tags:

regex

ruby

I came across a regex in the pickaxe Ruby book for finding balanced brace-expressions, and I'm trying to build upon it to get a regex that matches balanced braces/brackets/parens.

The original:

re = /
  \A
    (?<brace_expression>
      {
        (
          [^{}]                 # anything other than braces
        |                       # ...or...
          \g<brace_expression>  # a nested brace expression
        )*
      }
    )
  \Z
/x

My version so far:

re = /
  \A
    (?<brace_expression>
      (?:
        (?<brace> { ) | (?<bracket> \[ ) | ( \( )
      )
        (
          [^{}\[\]()]           # anything other than braces
        |                       # ...or...
          \g<brace_expression>  # a nested brace expression
        )*
      (?(<brace>) } | (?(<bracket>) \] | \) ) )
    )
  \Z
/x

It correctly matches "{xyz}", "[xyz]", "(xyz)", and correctly fails to match something like "{xyz]", but the recursion isn't behaving as I'd expect. It fails to match nested brace expressions like "{[]}". What am I missing?

like image 352
ivan Avatar asked Apr 09 '26 14:04

ivan


1 Answers

Interesting question. Your current pattern looks quite good. What about using alternation instead of conditionals which seem to be unreliable when using together with recursion.

re = /
  \A(                            # start group 1
    \(([^)(\]\[}{]+|\g<1>)*+\)|  # parens & set group 2
    \[\g<2>*+\]|                 # brackets
    \{\g<2>*+\}                  # braces
  )\z                            # group 1 end
/x
  • \g<1> is the subexpression call to first group which holds the pattern between start and end.
  • \g<2> is a call to group 2 which holds [^)(\]\[}{]+|\g<1> for reducing the pattern.
  • *+ is a possessive quantifier to improve failing-performance if unbalanced.

See demo at Regex101 (PCRE) or Rubular v1.9.3+

like image 116
bobble bubble Avatar answered Apr 12 '26 05:04

bobble bubble



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!