summaryrefslogtreecommitdiffstats log msg author committer range
path: root/misc/drawtree.pl
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116  #! /usr/local/bin/perl -w use strict; use warnings; my $str = <>; chomp$str; my $cursor = 0; sub parse { my$nodelabel = ""; while (substr($str,$cursor,1) ne "<" && substr($str,$cursor,1) ne ".") { die if $cursor >= length($str); $nodelabel .= substr($str,$cursor,1);$cursor++; } $cursor++ if substr($str,$cursor,1) eq "<"; my %node = ();$node{label} = $nodelabel; die if$nodelabel eq ""; my @children = (); $node{t} = \@children; while (substr($str,$cursor,1) ne ">" && substr($str,$cursor,1) ne ".") { die if$cursor >= length($str); my$child = parse(); $child->{parent} = \%node; push @children,$child; } $cursor++; return \%node; } my$tree = parse; my @leafnodes = (); my @pfxnodes = (); my @sfxnodes = (); sub donodes { my $node = shift; die unless defined($node->{label}); die unless defined($node->{t}); die unless ref($node->{t}) eq "ARRAY"; $node->{depth} = defined($node->{parent}) ? $node->{parent}->{depth} + 1 : 0; push @pfxnodes,$node; $node->{pfx} =$#pfxnodes; if ( scalar(@{$node->{t}}) ) { foreach my$n (@{$node->{t}}) { donodes($n); } } else { push @leafnodes, $node; } push @sfxnodes,$node; $node->{sfx} =$#sfxnodes; } donodes $tree; for ( my$i=0 ; $i{x} =$i * 20; } my %nodenames; for ( my $i=0 ;$i{label}; $base = "o" if$base eq "\#" || $base eq "\@";$base = "p" if $base eq "$$" || base eq "$$"; my$j; for ( $j=0 ; ;$j++ ) { last unless defined($nodenames{$base.$j}); } my$name = $base.$j; $node->{name} =$name; $nodenames{$name} = $node; my$ltxlabel = $node->{label};$ltxlabel = "\\" . $ltxlabel if$ltxlabel eq "\#"; $node->{ltxlabel} =$ltxlabel; } for ( my $i=0 ;$i{parent}) ) { my $p =$node->{parent}; die unless defined $p->{y}; if ( scalar(@{$p->{t}}) > 1 ) { $node->{y} =$p->{y} + 30; } else { $node->{y} =$p->{y} + 20; } } else { $node->{y} = 0; } } for ( my$i=0 ; $i{t}}) ) { my$sum = 0; my $cnt = 0; foreach my$n (@{$node->{t}}) { die unless defined$n->{x}; $sum +=$n->{x}; $cnt++; }$node->{x} = $sum/$cnt; } } printf "\\begin{tikzpicture}$line join=bevel,baseline=(%s.base)$\n", $tree->{name}; for ( my$i=0 ; $i{name},$node->{x}, -$node->{y},$node->{ltxlabel}; if ( defined($node->{parent}) ) { printf " \\draw (%s) -- (%s);\n",$node->{parent}->{name}, \$node->{name}; } else { printf "\n"; } } print "\\end{tikzpicture}\n";