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<scalar(@leafnodes) ; $i++ ) {
$leafnodes[$i]->{x} = $i * 20;
}
my %nodenames;
for ( my $i=0 ; $i<scalar(@pfxnodes) ; $i++ ) {
my $node = $pfxnodes[$i];
my $base = $node->{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<scalar(@pfxnodes) ; $i++ ) {
my $node = $pfxnodes[$i];
if ( defined($node->{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<scalar(@sfxnodes) ; $i++ ) {
my $node = $sfxnodes[$i];
if ( scalar(@{$node->{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<scalar(@pfxnodes) ; $i++ ) {
my $node = $pfxnodes[$i];
printf "\\node (%s) at (%.3fbp,%.3fbp) \[draw=none\] {\$%s\$};", $node->{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";
|