Regex 为较旧的Perl版本重写递归正则表达式

Regex 为较旧的Perl版本重写递归正则表达式,regex,perl,Regex,Perl,下面的代码在Perl(v5.16.2)中运行良好。但是,当我使用PerlV5.8.9运行它时,它会抱怨下面的正则表达式。如何使用PerlV5.8.9重写这个正则表达式。(我无法更新版本) REGEX: use strict; use warnings; our %formula_per_k; INIT { # List all functions that you want to allow in formulas. All other words will be interpret

下面的代码在Perl(v5.16.2)中运行良好。但是,当我使用PerlV5.8.9运行它时,它会抱怨下面的正则表达式。如何使用PerlV5.8.9重写这个正则表达式。(我无法更新版本)

REGEX:

use strict;
use warnings;

our %formula_per_k;
INIT {
    # List all functions that you want to allow in formulas.  All other words will be interpretted as variables.
    my @FORMULA_FUNCS = qw(sqrt exp log);

    # Load the data via a file.
    my $data = do {local $/; <DATA>};

    # Parse K blocks
    while ($data =~ m{
        ^K \s+ (\w+) \s* \{
            ( (?: [^{}]+ | \{(?2)\} )* )         # Matched braces only.
        \}
    }mgx) {
        my ($name, $params) = ($1, $2);

        # Parse LOL block
        next if $params !~ m{
            LOL \s* \{ 
                ( (?: [^{}]+ | \{(?1)\} )*? )    # Matched braces only.
            \}
        }mx;
        my $lol = $1;

        # Start building anonymous subroutine
        my $conditions = '';

        # Parse Conditions and Formulas
        while ($lol =~ m{
            COND \s* \{ (.*?) \} \s* 
            FORMULA \s* \{ (.*?) \}
        }gx) {
            my ($cond, $formula) = ($1, $2);

            # Remove Excess spacing and translate variable into perl scalar.
            for ($cond, $formula) {
                s/^\s+|\s+$//g;
                s{([a-zA-Z]+)}{
                    my $var = $1;
                    $var = "\$hashref->{$var}" if ! grep {$var eq $_} @FORMULA_FUNCS;
                    $var
                }eg;
            }

            $conditions .= "return $formula if $cond; ";
        }

        my $code = "sub {my \$hashref = shift; ${conditions} return; }";

        my $sub = eval $code;
        if ($@) {
            die "Invalid formulas in $name: $@";
        }

        $formula_per_k{$name} = $sub;
    }
}

sub formula_per_k {
    my ($k, $vars) = @_;

    die "Unrecognized K value '$k'" if ! exists $formula_per_k{$k};

    return $formula_per_k{$k}($vars);
}

print "'K1', {d => .1}   = " . formula_per_k('K1', {d => .1}) . "\n";
print "'K1', {d => .05}  = " . formula_per_k('K1', {d => .05}) . "\n";
print "'K3', {d => .02}  = " . formula_per_k('K3', {d => .02}) . "\n";
print "'K3', {d => .021} = " . formula_per_k('K3', {d => .021}) . "\n";


__DATA__
... #OTHER STUFFS
K K1 {
    LOL {
        COND { d < 0.01 }
        FORMULA { -0.2 + 3.3*sqrt(d) }
        COND { d >= 0.01 }
        FORMULA { -0.2 + 3.3*sqrt(d+0.4) }
    }
}
... #OTHER STUFFS
K K2 {
    LOL {
        COND { d < 0.03 }
        FORMULA { -2.2 + 1.3*sqrt(d) }
        COND { d >= 0.03 }
        FORMULA { -2.2 + 1.3*sqrt(d+0.8) }
    }
}
... #OTHER STUFFS
K K3 {
    LOL {
        COND { d < 0.02 }
        FORMULA { -4.3 + 0.3*sqrt(d) }
        COND { d >= 0.02 }
        FORMULA { -4.3 + 0.3*sqrt(d+0.3) }
    }
}
... #OTHER STUFF
Sequence (?1...) not recognized in regex; marked by <-- HERE in m/
            ^K \s+ M3 \s* {
                ( (?: [^{}]+ | {(?2 <-- HERE )} )* )         # Matched braces only.
            }
        / at ./code.pl line 215, <RFILE> line 12.
错误:

use strict;
use warnings;

our %formula_per_k;
INIT {
    # List all functions that you want to allow in formulas.  All other words will be interpretted as variables.
    my @FORMULA_FUNCS = qw(sqrt exp log);

    # Load the data via a file.
    my $data = do {local $/; <DATA>};

    # Parse K blocks
    while ($data =~ m{
        ^K \s+ (\w+) \s* \{
            ( (?: [^{}]+ | \{(?2)\} )* )         # Matched braces only.
        \}
    }mgx) {
        my ($name, $params) = ($1, $2);

        # Parse LOL block
        next if $params !~ m{
            LOL \s* \{ 
                ( (?: [^{}]+ | \{(?1)\} )*? )    # Matched braces only.
            \}
        }mx;
        my $lol = $1;

        # Start building anonymous subroutine
        my $conditions = '';

        # Parse Conditions and Formulas
        while ($lol =~ m{
            COND \s* \{ (.*?) \} \s* 
            FORMULA \s* \{ (.*?) \}
        }gx) {
            my ($cond, $formula) = ($1, $2);

            # Remove Excess spacing and translate variable into perl scalar.
            for ($cond, $formula) {
                s/^\s+|\s+$//g;
                s{([a-zA-Z]+)}{
                    my $var = $1;
                    $var = "\$hashref->{$var}" if ! grep {$var eq $_} @FORMULA_FUNCS;
                    $var
                }eg;
            }

            $conditions .= "return $formula if $cond; ";
        }

        my $code = "sub {my \$hashref = shift; ${conditions} return; }";

        my $sub = eval $code;
        if ($@) {
            die "Invalid formulas in $name: $@";
        }

        $formula_per_k{$name} = $sub;
    }
}

sub formula_per_k {
    my ($k, $vars) = @_;

    die "Unrecognized K value '$k'" if ! exists $formula_per_k{$k};

    return $formula_per_k{$k}($vars);
}

print "'K1', {d => .1}   = " . formula_per_k('K1', {d => .1}) . "\n";
print "'K1', {d => .05}  = " . formula_per_k('K1', {d => .05}) . "\n";
print "'K3', {d => .02}  = " . formula_per_k('K3', {d => .02}) . "\n";
print "'K3', {d => .021} = " . formula_per_k('K3', {d => .021}) . "\n";


__DATA__
... #OTHER STUFFS
K K1 {
    LOL {
        COND { d < 0.01 }
        FORMULA { -0.2 + 3.3*sqrt(d) }
        COND { d >= 0.01 }
        FORMULA { -0.2 + 3.3*sqrt(d+0.4) }
    }
}
... #OTHER STUFFS
K K2 {
    LOL {
        COND { d < 0.03 }
        FORMULA { -2.2 + 1.3*sqrt(d) }
        COND { d >= 0.03 }
        FORMULA { -2.2 + 1.3*sqrt(d+0.8) }
    }
}
... #OTHER STUFFS
K K3 {
    LOL {
        COND { d < 0.02 }
        FORMULA { -4.3 + 0.3*sqrt(d) }
        COND { d >= 0.02 }
        FORMULA { -4.3 + 0.3*sqrt(d+0.3) }
    }
}
... #OTHER STUFF
Sequence (?1...) not recognized in regex; marked by <-- HERE in m/
            ^K \s+ M3 \s* {
                ( (?: [^{}]+ | {(?2 <-- HERE )} )* )         # Matched braces only.
            }
        / at ./code.pl line 215, <RFILE> line 12.

序列(?1…)在正则表达式中无法识别;在引入
(?PARNO)
之前,我们必须使用
(?{code})
来创建递归正则表达式。可以在中找到一个例子

以下内容在
v5.8.9
perlbrew上进行了测试,并在本地进行了测试:

our $braces_re;
$braces_re = qr{
    \{
    (?:
        (?> [^{}]+ )
    |
        (??{ $braces_re })
    )*
    \}
}sx;

# parse FOO block
while (
    $data =~ m{
    ^FOO \s+ (\w+) \s* \{
        ( (?: [^{}]+ | (??{ $braces_re }) )* )         # Matched braces only.
    \}
}mgx
    )
{
    my $params = $1;

    # parse BAR block
    next if $params !~ m{
        BAR \s* \{ 
            ( (?: [^{}]+ | (??{ $braces_re }) )*? )    # Matched braces only.
        \}
    }mx;
    # SOME CODE
}
注意,我特意将_re变量的声明及其初始化分开。有些版本的perl允许您在初始化时在同一语句中声明递归正则表达式,但v5.8.9不是其中之一

此外,如果您愿意修改原始正则表达式,而不仅仅是替换
(?PARNO)
符号,那么上述内容可以简化为以下内容。还确认了:


我建议尝试在本地安装较新版本的perl。感谢您的友好和快速帮助。我需要完整的代码(最初由您自己建议)。请继续测试你的。我失败了。我希望您不要因为现在更改代码而讨厌我。这里有两个已确认的工作测试:我目前使用的最古老的Perl是5.10.1。已经确认了。我可能最终会设置一个旧Perl的perlbrew,但直到明天才有时间。