summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/LingTrees/lingtrees.sty
blob: 80d9b827f2f01b128eda0d81b03ea2689f6ad0d6 (plain)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Version: 28 Dec 2005
%%                                                     changelog at end
%%
%%     Primitive Linguistics Tree Formatter
%%
%% Copyright (c) 1991, 2005, 2006 Avery DeLano Andrews 3rd
%% These macros can be redistributed and/or modified under the terms
%% of the LaTeX Project Public License Distributed from CTAN
%% archives in directory macros/latex/base/lppl.txt.
%%
%%      Parameter-list handling technique cribbed from gloss.sty
%%         by Marcel R. van der Goot (1990).
%%      Advice and some edits by Christopher D Manning
%%
%% License: LaTeX Project Public License
%%
%% Usage:  \tree{...}      prints out a formatted tree.
%%         \treenode{...}  puts formatted tree into \treebox reg.
%%            either leaves \treewidth reg = width of tree
%%                          \treecenter reg. = `center' of tree
%%
%%         {...} above is a `tree list', of the form:
%%           {{<terminal>}}
%%           {<mother>, <d1>,  <dn>}, where each di is a treelist.
%%            
%%         e.g.  {S, {NP, {Det, {{the}}, {N, {{dog}}}}, {VP, {{barked}}}}
%%
%%         The double braces around terminals are annoying, but I haven't
%%          been clever enough to avoid them.  <terminal> & <mother>
%%          can be any well-balanced material, (feature-structures,
%%          stacks of nodes & annotations ...
%%
%%  Parameters:
%%    \sisterskip (dimen)     default spacing between sisters
%%    \daughterskip (dimen)   default vert. mother-daughter spacing
%%
%%  Fiddles:
%%    \daughtergap{<dimen>} in a mother node sets mother-daughter
%%       spacing to <dimen> for daughters of that node.
%%    \sistergap{<dimen>} in a node spaces it <dimen> horizontally
%%       from its *preceeding* sister
%%
%%  LFG Specials:
%%    To make life easier for LFG people, there are two commands for
%%    doing annotated nodes, \tnode for terminals, \ntnode for nonterminals.
%%    Both are defined in terms of \node from Emma Pease's tree.sty, so they
%%    take two braced arguments, the node tag and the node specification.
%%
%%    The node tag is as in tree.sty, but the node specification is a
%%    series of levels separated by `/' (if you want to combine levels
%%    with GPSG slash notation, groupany level containing a slash in
%%    braces).  With \ntnode, the upper levels are set in math mode
%%    and the bottommost in restricted horizontal; with \tnode, the
%%    upper levels are set in math mode and the bottommost in restricted
%%    horizontal with italic font.
%%
%%    Annotation are now by default in the current mode (usually text).
%%    If you want to switch on automatic math mode for annotations, you
%%    can do it by redefining the \nodeannotation command as follows:
%%
%%      \def\nodeannotation#1{$#1$}
%%
%%   If you want to terminals to be, say slanted rather than italics, you can
%%   do it by redefining \tstyle as follows:
%%   
%%      \def\tstyle{\sl}
%%
%%  If you want to use the stacking, etc., facilities, but not the
%%  line-drawing (which depends on tree.sty), you can redefine \node
%%  to effectively do nothing:
%%
%%      \def\node#1#2{#2}
%%
%%
%%  General Remarks:
%%
%%    Coded for reader's comfort, not computer's speed, according
%%    to my rather inexperienced lights.
%%
%%    Processes nodes on a left-corner schedule, first packing
%%    daughters into an hbox, then mother into another hbox,
%%    then both into a vtop (vbox with alignment along the top).
%%
%%    Improvements & Suggestions welcome.  Please notify to:
%%
%%      Avery D Andrews
%%      School of Language Studies
%%      Faculty of Arts
%%      The Australian national University
%%      Acton ACT 2600
%%
%%      email:  Avery.Andrews@anu.edu.au
%%
%%    Changelog:
%%      27 Dec 2005: \nodeannotation bugfixed
%%                   \sistergap bug fixed
%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\csname LingTreesLoaded\endcsname
\let\LingTreesLoaded\endinput

\ifx\LingTreesWithoutPSTricks\relax\input tree-dvips.sty\else
\ifx\PSTTreeDvipsEmuLoaded\endinput\else\input pst-tree-dvips-emu.sty\fi\relax\fi\relax

\def\CR{
}
{
\catcode`\_=11     % sets underbar to letter
\catcode` =9       % causes spaces to be ignored
\catcode`\^^M=9    % causes <CR> to be ignored

\newbox\treebox        % box register for returned tree
\newbox\mother_box     %     " for mother
\newbox\daughter_box   %     " for local accumulation of daughters
\newbox\daughterr_box  %     " for upward comm. of dtrs
\newbox\stack_box      % for calculating widths for centering annotations

\newskip\sisterskip     % default space between sisters
\newskip\sister_skip    % space before current sister
\newdimen\daughterskip  % default mother-daughter space (vert)
\newdimen\daughter_skip % current  "
\newdimen\stack_width   % for calculating widths for centering annotations
\newskip\annoteskip     % default space between annotations

\global\sisterskip=2em
\global\daughterskip=2ex
\global\annoteskip=0ex

\newdimen\treewidth
\newdimen\treecenter
\newdimen\mother_offset
\newdimen\first_center
\newdimen\last_center
\newdimen\daughter_center
\newdimen\raise_daughter


\newdimen\daughter_spread
\newcount\daughter_count
\newcount\treerationum
\newcount\treeratiodenom
\global\treerationum=0
\global\treeratiodenom=0
\gdef\treeslantratio#1{\@treeslantratio[#1]}
\gdef\@treeslantratio[#1/#2]{%
\treerationum=#1
\treeratiodenom=#2
}

\newdimen\treedotwidth
\global\treedotwidth=0.6pt

\newdimen\nodewidth
\newdimen\node_width
\global\nodewidth=0em
\gdef\@nwbox#1{\hbox{\makebox[\node_width][c]{#1}}}
\gdef\@ifnodewidthzero#1#2{\ifdim\node_width=0em #1\else #2\fi}
\gdef\@fwbox#1{\@ifnodewidthzero{\hbox{#1}}{\@nwbox{#1}}}

\gdef\setnodewidth#1{\global\node_width=#1}

\gdef\daughtergap#1{\global\daughter_skip=#1} % chris: should remove global?
\gdef\sistergap#1{\global\sister_skip=#1}       % avery: no, doesn't work.  wish I could
                                                %  remember how it was supposed to!

% was: \gdef\tree#1{\tree_node#1,.\leavevmode\box\treebox}
\gdef\tree#1{\tree_node#1,.\ifvmode\leavevmode\fi\hbox{\box\treebox}}
          % formats tree & prints it out.
          % sets treewidth & treecenter

\gdef\treenode#1{\tree_node#1,.}  % formats tree & puts it in treebox
          % sets treewidth & treecenter

\gdef\treeann#1{\node_ann{#1}}          % annotation stack

% for centered tree in math mode. cdm Mar 1996
\gdef\treecent#1{\tree_node#1,.\ifvmode\leavevmode\fi\vcenter{\box\treebox}}

\gdef\tree_node#1,#2.{
   \def\daughters{#2}
   \ifx\daughters\empty   % if terminal
%      \message{terminal\CR}
      \global\setbox\treebox=\@fwbox{#1}
%      \message{got_term}
      \global\treewidth=\wd\treebox
      \global\treecenter=.5\treewidth
   \else
%      \message{get daughters}
      \global\node_width=\nodewidth%\message{RestoreA\CR}
      \get_daughters#2.
%      \message{got daughters}
      \global\node_width=\nodewidth%\message{RestoreB\CR}
      \ifnum\treeratiodenom=0
        \daughtergap{\daughterskip}
      \else
        \ifnum\daughter_count=1
           \daughtergap{\daughterskip}
         \else
           \daughter_spread=\last_center
           \advance \daughter_spread by -\first_center
           \multiply \daughter_spread by \treerationum
           \divide\daughter_spread by \treeratiodenom
           \daughtergap{\daughter_spread}
         \fi
      \fi
      \setbox\mother_box=\@fwbox{#1}
%      \message{got mother\CR}
      \ifdim\ht\mother_box=0em
         \advance\daughter_skip by -2\nodemargin
      \fi
      \mother_offset=\daughter_center
      \advance\mother_offset by -.5\wd\mother_box  % width to center of mother
      \ifdim\mother_offset>0pt
           \global\setbox\treebox=\vtop{
                    \hbox{\hskip\mother_offset\unhbox\mother_box}
                    \vskip\daughter_skip
                    \box\daughterr_box}
      \else
           \global\setbox\treebox=\vtop{
                    \box\mother_box
                    \vskip\daughter_skip
                    \hbox{\hskip-\mother_offset\unhbox\daughterr_box}}
      \fi
      \@ifnodewidthzero
        {\global\treewidth=\wd\treebox}
        {\global\treewidth=\node_width}
      \global\treecenter=\daughter_center
      \ifdim\mother_offset<0pt
        \global\advance\treecenter by -\mother_offset
      \fi
%      \global\node_width=\nodewidth\message{Restore\CR}
   \fi
}

\gdef\d@mmy.{}  % We call this when we are at the end.  A no-op, but you
    % get better performance if you use no-ops! [cdm]

\gdef\d@@mmy.{}{} % two-argument version.

\gdef\get_daughters#1,#2.{
%   \global\node_width=\nodewidth\message{PreRestore\noexpand\node_width\CR}
   {\treenode#1}     %  process first daughter
%   \message{got first daughter\CR}
   \first_center=\treecenter
   \last_center=\treewidth
   \daughter_count=1
   \setbox\daughter_box=\hbox{\raise\raise_daughter\box\treebox}
   \def\more{#2}
   \ifx\more\empty
     \global\daughter_center=\first_center
     \global\setbox\daughterr_box=\box\daughter_box
     \let\more=\d@mmy
   \else
     \let\more=\more_daughters
   \fi
   \more#2.
   \@ifnodewidthzero{}
     {\global\setbox\daughterr_box=\@fwbox{\box\daughterr_box}
      \global\daughter_center=.5\node_width
     }
}

\gdef\more_daughters#1,#2.{
   \sistergap{\sisterskip}
   \node_width=\nodewidth
   {\treenode#1}
   \advance\daughter_count by 1
   \@ifnodewidthzero  % leave out sisterskip for fixed width
     {\setbox\daughter_box=\hbox{
        \unhbox\daughter_box\hskip\sister_skip\raise\raise_daughter\box\treebox}}
     {\setbox\daughter_box=\hbox{
        \unhbox\daughter_box\raise\raise_daughter\box\treebox}}
   \def\more{#2}
   \ifx\more\empty
      \advance\last_center by \treecenter
      \@ifnodewidthzero
        {\advance\last_center by \sister_skip}
        {}
      \advance\last_center by \first_center
      \divide\last_center by 2
      \global\daughter_center=\last_center
      \global\setbox\daughterr_box=\box\daughter_box  
      \let\more=\d@mmy
   \else
      \advance\last_center by \treewidth
      \@ifnodewidthzero
        {\advance\last_center by \sister_skip}
        {}
      \let\more=\more_daughters
   \fi
   \more#2.
   \sistergap{\sisterskip}
}


\gdef\ntnode#1#2{
  \def\t_style{\ntstyle}
  \node{#1}{\node_ann{#2}}
}

\global\let\tstyle=\it
\global\let\ntstyle=\rm

\gdef\tnode#1#2{
  \def\t_style{\tstyle}
  \node{#1}{\node_ann{#2}}
}

\gdef\node_ann#1{
  \global\stack_width=0pt
  \get_widths#1/.
  \vtop{\stack_ann#1/.}
}

\gdef\stack_ann#1/#2.{
  \def\more{#2}
  \ifx\more\empty
    \ifdim\stack_width=0em
      \hbox to\stack_width{\vbox to 0em{}}
      \global\raise_daughter=\ht\strutbox
    \else
      \hbox to \stack_width{\strut\hss\t_style {\nodeannotation{#1}}\hss}
      \global\raise_daughter=0ex
    \fi
    \let\more=\d@mmy
  \else
    \hbox to \stack_width{\hss {\nodeannotation{#1}}\hss}\vskip\annoteskip
    \let\more=\stack_ann
  \fi
  \more#2.
 }

% Default used to be math, (for f-descriptions?) but this was a pain!
% \gdef\nodeannotation#1{$#1$}
\gdef\nodeannotation#1{#1}

\gdef\get_widths#1/#2.{
  \def\more{#2}
  \ifx\more\empty
     \setbox\stack_box=\hbox{\t_style \nodeannotation{#1}}
     \let\more=\d@mmy
  \else
     \setbox\stack_box=\hbox{\nodeannotation{#1}}
     \let\more=\get_widths
  \fi
  \ifdim\stack_width<\wd\stack_box
    \global\stack_width=\wd\stack_box
  \fi
  \more#2.
}

}  % end group & restore standard catcodes

%% Changelog
%%
%% 26 Feb 2006
%%  get vertical spacing with no-label nodes to work
%%  \setnodewidth command and ancilliaries working
%%
%% 28 Dec 2005
%%   fix bugs with \nodeannotation and \sistergap
%%
%% 21 Sep 1997