Re: Text::Balanced v Parse::RecDescent

[email protected] (Damian Conway) Wed, 04 Dec 2002 07:32:21 +1100
Newsgroups perl.recdescent
Message-ID <[email protected]>
Andrew Savige wrote:

> I like this elegant solution.
> However, these recursive regexes seem to have a flawed implementation.
> For example, with the following test data:
> 
> __DATA__
> {1}, hello one two three
> 
> it seems to hang. Actually, it finishes eventually, taking 87.33
> seconds on Linux Perl 5.6.1. 

It's not the implementation that's flawed, it's the interaction of recursion,
greediness, and backtracking that's to blame.

Here's a postmaturely optimized solution that makes use of the (?>...)
metasyntax to prevent expensive and useless backtracking.

You should find it runs very much faster.

-----cut----------cut----------cut----------cut----------cut-----

use re 'eval';

our $quoted = qr/ ' [^'\\]* (?> (?> \\. [^'\\]* )* ) '  # Match 'str'
                 | " [^"\\]* (?> (?> \\. [^"\\]* )* ) "  # Match 'str'
                 /x;

our $element = qr/ (?> (?> [^'"{},]+ )          # Match non-special characters
                      | \\.                      # Match escaped anything
                      | $quoted                  # Match quoted anything
                      | (??{$nested})            # Match {...,...,...}
                    )
                  /xs;

our $nested  = qr/ [{]                          # Match {
                    (?> (?: $element , )* )      # Match list of subelements
                    $element?                    # Match last subelement
                    [}]                          # Match }
                  /x;


$data = <DATA>;

@fields = $data =~ m/\G ( $element ) ,? /gx;    # Capture elements repeatedly

use Data::Dumper 'Dumper';
print Dumper( @fields );

__DATA__
{1}, hello one two three four five six seven eight nine heat-death-of-the-universe

-----cut----------cut----------cut----------cut----------cut-----

Note that I also added a \G to the actual m// matcher, to ensure that
the sequence of elements matched is actually sequential (i.e. no
convenient skipping of inconvenient non-elements in the middle).

Damian