# Regex extension to handle matching parens?

**URL:** <https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500>\
**Category:** Ruby\
**Created:** [January 23, 2009, 11:35pm UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500 "2009-01-23T23:35:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 23, 2009, 11:35pm UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/1 "2009-01-23T23:35:55Z")

</div>

Dear Experts: I am very new to ruby, literally having just read the  
ruby book.

I want to write a program that does basic LaTeX parsing, so I need to  
match ‘}’ closings to the opening ‘{’. (yes, I understand that LaTeX  
has very messy syntax, so this will only work for certain LaTeX docs.)  
Does a gem exist that facilitates closing-paren-matching fairly  
painlessly? For example,

sample = " \caption{my table \label{table-label} example:  
$\sqrt{2+\sqrt{2}}$} more here {}"

so, I want to find my “\caption” matcher ruby program to be able to  
detect the closing paren, and provide me with everything in between  
the opener and closer (i.e., “my table \label{table-label} example:  
$\sqrt{2+\sqrt{2}}$”). Possible?

I searched this mailing list first, but I only found discussions from  
years back about this issue. I understand that this is not strictly  
speaking a regular expression. I come from a perl background. There  
are now some regex extension libraries that make it possible for the  
built-in regex engine to parse matching parens  
(Regexp::Common::balanced and Text::Balanced). I was hoping I could  
find some similar gem for ruby.

help appreciated.

Sincerely,

/iaw

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 24, 2009, 1:26am UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/2 "2009-01-24T01:26:38Z")

</div>

Ah, specifically, the “Back reference with nest level” section of  
[http://oniguruma.rubyforge.org/oniguruma/files/Syntax\_txt.html](http://oniguruma.rubyforge.org/oniguruma/files/Syntax_txt.html)

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 24, 2009, 2:05am UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/3 "2009-01-24T02:05:50Z")

</div>

thank you, rob. great reference. now I know that it can be done.  
alas, this doc is a little over my head. can someone who has used  
this construct possibly please show me how I would try it on my simple  
example?

sample = " \caption{my table \label{table-label} example: $\sqrt{2+  
\sqrt{2}}$} more here {}"

accomplishing this is actually not ugly at all in perl:

use Regexp::Common;  
my $matchingarg = qr/$RE{balanced}{-parens=\>’{ }’})/;  
/\caption$matchingarg/;  
print “The \caption argument is $1\n”;

of course, perl is ugly in many other respects, but here, it does  
nicely.

regards, /iaw

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 24, 2009, 1:17am UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/4 "2009-01-24T01:17:17Z")

</div>

I think that you need to look at what Oniguruma might be able to do.  
[http://oniguruma.rubyforge.org/](http://oniguruma.rubyforge.org/)

I believe I’ve seen it demonstrated that balanced open/close pairs can  
be found with this regular expression engine. It might be ugly,  
however, but then you probably expected that.

-Rob

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 24, 2009, 3:35am UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/5 "2009-01-24T03:35:57Z")

</div>

ivowel wrote:

> accomplishing this is actually not ugly at all in perl:
> 
> use Regexp::Common;  
> my $matchingarg = qr/$RE{balanced}{-parens=\>’{ }’})/;  
> /\caption$matchingarg/;  
> print “The \caption argument is $1\n”;
> 
> of course, perl is ugly in many other respects, but here, it does  
> nicely.
> 
> regards, /iaw

sample = " \caption{my table \label{table-label}  
example: $\sqrt{2+\sqrt{2}}$} more here {}"

def bal\_fences str  
left = str[0,1]  
fences = /[#{Regexp.escape “(){}[]\<\>”[/#{Regexp.escape left}./]}]/  
accum = “” ; count = 0  
str.scan( /.\*?#{fences}/ ){|s|  
count += if s[-1,1] == left ; 1 else -1 end  
accum \<\< s  
break if 0 == count  
}  
accum  
end

p bal\_fences( sample[/caption(.\*)/m, 1] )

---

<div class="post-metadata">

**Author:** ![ivo\_welch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/d2c977/32.png) [@ivo\_welch](https://www.ruby-forum.com/u/ivo_welch)\
**Post date:** [January 24, 2009, 5:40pm UTC](https://www.ruby-forum.com/t/regex-extension-to-handle-matching-parens/158500/6 "2009-01-24T17:40:49Z")

</div>

On 24.01.2009 02:00, ivowel wrote:

> use Regexp::Common;  
> my $matchingarg = qr/$RE{balanced}{-parens=\>’{ }’})/;  
> /\caption$matchingarg/;  
> print “The \caption argument is $1\n”;
> 
> of course, perl is ugly in many other respects, but here, it does  
> nicely.

Ugliness often means bad maintainability… I’d probably use a  
different approach which also works with simpler regular expressions:

# untested

Node = Struct.new :parent, :children

current = root = Node.new nil, []  
tokens = input.split(%r{({}])})

tokens.each do |token|  
case token  
when %r{[({]}  
current = Node.new current, []  
when %r{[])}]}  
current = current.parent  
else  
current.children \<\< token  
end  
end

In other words: build a rudimentary context free parser. Depends of  
course on what you want to do.

Cheers

robert
