Hi Tao, > -----Original Message----- > From: tao wang [mailto:[EMAIL PROTECTED] > Sent: Saturday, March 01, 2003 9:49 AM > To: [EMAIL PROTECTED] > Subject: how to detect a circular macro by using perl > > > Hi Everyone, > I'm trying to parse lines of macros definitions as > following: > > AV $(G)/er $(M)/q $(T)/w/f > G ter/eee > M $(W) > T g/ee/fet > W $(AV) > > You can see the AV is actually a circular macro since > the AV -> M -> W-> AV. I'm think about create a tree > to do it. Is it possible? and how can i do it? Are > there any other ways to do it? thank a lot. I really > appreciate it. - tao >
This was a real brain teaser for me! I have put together a script that seems to work, but it's *neither* concise *nor* elegant. If you or anyone else has some nice solution, please post it! :) My script: #!/usr/bin/perl use strict; use warnings; # sample input my $input = <<'*EOF*'; AV $(G)/er $(M)/q $(T)/w/f G ter/eee M $(W) T g/ee/fet W $(AV) *EOF* # parse input into a hash having key == macro name # and value == hash (ref) of dependent macro names my %macros; my @lines = split /\n/, $input; for (@lines) { my ($name, $value) = /^(\w+)\s+(.*)/; next unless $name and $value; my (@macs) = /\$\((\w+)\)/g; $macros{$name}->{$_} = 1 for (@macs); } # print (for debugging) print "input:\n"; for (sort keys %macros) { print "$_:"; for my $mac (sort keys %{$macros{$_}}) { print " -> $mac"; } print "\n"; } # iterate thru hash finding circular dependences print "expand:\n"; my $cir_count = 0; for (sort keys %macros) { my $def = "$_:"; $cir_count += expand (\$def, $_, $macros{$_}); print "$def\n"; } print "$cir_count circular definitions\n"; # recursive expand and check circular routine sub expand { my ($def, $name, $mhash) = @_; return 0 unless $mhash; for my $mac (sort keys %{$mhash}) { $$def .= " -> $mac"; if ($mac eq $name) { $$def .= " *CIRCULAR*"; return 1; } return 1 if expand ($def, $name, $macros{$mac}); } return 0; } output: input: AV: -> G -> M -> T M: -> W W: -> AV expand: AV: -> G -> M -> W -> AV *CIRCULAR* M: -> W -> AV -> G -> M *CIRCULAR* W: -> AV -> G -> M -> W *CIRCULAR* 3 circular definitions Note: I am correct in that AV, M, and W are circular (not just AV) am I not? Notice that I have not captured the 'guts' of each macro, just calls to other macros. The parsing may have to be adjusted to suit your purposes. The 'sort' of hashes in the script is optional, I used it simply to put the results in some kind of order; in your real script you probably should use array references to insure the expansion sequence is maintained. Well, it's a poor, old, hacker's start at least... again, does anyone have a really slick solution? Aloha => Beau; -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]