%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Version: 26 Mar 91 %% %% Primitive Linguistics Tree Formatter %% %% Copyright (c) 1991 Avery DeLano Andrews 3rd %% You can use these macros to typeset your own documents, or you %% can use them as basis for your own macros. In the latter case, %% you must (1) give proper credit, and (2) document the usage of %% your macros/changes (if the usage of your macros is not worth %% documenting, they must not be worth using). %% %% Parameter-list handling technique & above post-copyright notice %% blurb cribbed from gloss.sty by Marcel R. van der Goot (1990). %% %% %% 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: %% {{}} %% {, , }, 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. & %% 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{} in a mother node sets mother-daughter %% spacing to for daughters of that node. %% \sistergap{} in a node spaces it 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. %% %% If you want to switch off 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 %% Linguistics, The Faculties %% ANU PO Box 4 %% Canberra ACT 2601 %% %% email: ada612@fac.anu.edu.au %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% { \catcode`\_=11 % sets underbar to letter \catcode` =9 % causes spaces to be ignored \catcode`\^^M=9 % causes 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 \gdef\daughtergap#1{\global\daughter_skip=#1} % chris: should remove global? \gdef\sistergap#1{\global\sister_skip=#1} % 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 % 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 \global\setbox\treebox=\hbox{#1} \global\treewidth=\wd\treebox \global\treecenter=.5\treewidth \else \get_daughters#2. \daughtergap{\daughterskip} \setbox\mother_box=\hbox{#1} \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 \global\treewidth=\wd\treebox \global\treecenter=\daughter_center \ifdim\mother_offset<0pt \global\advance\treecenter by -\mother_offset \fi \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! \gdef\get_daughters#1,#2.{ \treenode#1 % process first daughter \first_center=\treecenter \last_center=\treewidth \setbox\daughter_box=\hbox{\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. } \gdef\more_daughters#1,#2.{ \sistergap{\sisterskip} {\treenode#1} \setbox\daughter_box=\hbox{ \unhbox\daughter_box\hskip\sister_skip\box\treebox} \def\more{#2} \ifx\more\empty \advance\last_center by \treecenter \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 \advance\last_center by \sister_skip \let\more=\more_daughters \fi \more#2. } \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 \hbox to \stack_width{\strut\hss\t_style #1\hss} \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 this (for f-descriptions?) \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 #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