根据水平提取if-elsif条件

时间:2015-01-13 02:51:39

标签: perl

if (CONDITION_1) {
    if (CONDITION_A) {
        a = 1;
    }
}
elsif (CONDITION_2) {
    if (CONDITION_B) {
        if (CONDITION_i) {
            a = 2;
        }
        elsif (CONDITION_ii) {
            a = 3;
        }
        endif
    }
    endif
}
endif

我想将条件作为字符串提取出来,并根据它们的级别打印出来,如:

CONDITION_1
CONDITION_1//CONDITION_A
CONDITION_2
CONDITION_2//CONDITION_B
CONDITION_2//CONDITION_B//CONDITION_i
CONDITION_2//CONDITION_B//CONDITION_ii

我应该如何在Perl中递归编码,因为真实文件可能有超过3级的if-else块?我无法设法使逻辑正确。非常感谢。

---------- ---------- EDIT

我已经弄明白背后的逻辑,这是我的工作代码:

my (%cond, $lvl);
open my $fh, '<', $file or die;
while (<$fh>) {
    if (/if\s\((\w+)\)/) {
        $lvl++;
        push @{ $cond{$lvl} }, $1;
        for my $i (1 .. $lvl) {
            print "${ $cond{$i} }[-1]";
            print "//" if $i != $lvl;
        }
        print "\n";
    }
    elsif (/elsif\s\((\w+)\)/) {
        push @{ $cond{$lvl} }, $1;
        for my $i (1 .. $lvl) {
            print "${ $cond{$i} }[-1]";
            print "//" if $i != $lvl;
        }
        print "\n";
    }
    elsif (/else/) {
        push @{ $cond{$lvl} }, 'else';
        for my $i (1 .. $lvl) {
            print "${ $cond{$i} }[-1]";
            print "//" if $i != $lvl;
        }
        print "\n";
    }
    elsif (/endif/) {
        $lvl--;
    }
}
close $fh;

1 个答案:

答案 0 :(得分:0)

这是完全未经测试的代码,但是使用你的&#34; if-elsif-endif&#34;样本构造。我认为从概念上讲它是正确的,但需要一些开发和调试时间:

#!/usr/bin/perl

use warnings;
use strict;

my $in = "if-elsif-endif_feed";
my $out = "if-elsif-endif_parsed";

my $level;
my $condition;
my @levels;
my @conditions;

open IN, "<", $in or die "IN: $!\n";
open OUT, ">", $out or die "OUT: $!\n";

while (<IN>) {
    if ( $_ =~ m/^[elsif].*$/i ) {
        if ( $_ =~ m/endif/i ) {
            next;
        } else {
            $level = 1;
            ($condition) = $_ =~ m/[elsif].*\((.*)\).*$/;
            push @levels, $level;
            push @conditions, $condition;
        }
    } elsif ( $_ =~ m/^\s+[elsif].*$/i ) {
        if ( $_ =~ m/endif/i ) {
            next;
        } else {
            $level++;
            ($condition) = m/\s+[elsif].*\((.*)\).*$/;
            push @levels, $level;
            push @conditions, $condition;
        }
    } elsif ( $_ =~ m/\s+\}.*$/ ) {
        $condition = "end";
        push @levels, $level;
        push @conditions, $condition;
        $level--;
    } elsif ( $_ =~ m/\}.*$/ ) {
        $condition = "end";
        $level = 1;
        push @levels, $level;
        push @conditions, $condition;
    } else {
        next;
    }
}

my $numlevels = @levels;
my $i;
my $curlevel;
my $curcond;
my $string;
my $stringc;

for ($i = 0; $i <= $numlevels; $i++) {
    $curlevel = $levels[$i];
    $curcond = $conditions[$i];


    if ( $curlevel == 1 ) {
        if ( $curcond ne "end" ) {
            $string = "$curcond";
            print "$string\n";
            print OUT "$string\n";
        } else {
            $string = undef;
        }
    } elsif ($curlevel > 1 ) {
        if ( $curcond ne "end" ) {
            $stringc = $string;
            if (( $levels[++$i] == $curlevel ) && ( $conditions[++$i] eq "end" )) {
                $string .= "\/\/$curcond";
                print "$string\n";
            } elsif (( $levels[++$i] == $curlevel ) && ( $conditions[++$i] ne "end" )) {
                $string = $stringc;
            }
        } elsif ( $curcond eq "end" ) {
            print "$string\n";
            print OUT "$string\n";
        }
    }
}

因此,在第一部分中,您基本上循环遍历文件并将级别和条件信息捕获到数组中,其级别与空间数无关。他们,你将数组解析成适当的字符串并将它们打印在适当的位置。

希望有所帮助!!