% \iffalse meta-comment % % Copyright (C) 2011 by Kevin W. Hamlen % ------------------------------------- % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3a of this license or (at your option) any later % version. The latest version of this license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3a or later is part of all distributions of % LaTeX version 2004/10/01 or later. % % \fi % % \iffalse %<*driver> \ProvidesFile{trfrac.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{trfrac} %<*package> [2011/5/20 v2.3 Tree Fraction Package] % % %<*driver> \documentclass{ltxdoc} \usepackage{amsmath} \usepackage{hyperref} \usepackage{trfrac} \newcount\seclevel% \newcommand{\getseclevel}{% \global\seclevel=3\relax% \ifnum\arabic{subsection}=0\global\seclevel=2\relax\fi% } {\catcode`/=0 \catcode`\\=11 /gdef/DescMacro#1{% /getseclevel% /pdfbookmark[/the/seclevel]{\\#1}{macdef-#1}% /expandafter/DescribeMacro/expandafter{/csname #1/endcsname}% /hyperdef{macro}{#1}{}/kern0pt% } } \newcommand{\DescEnv}[1]{% \getseclevel% \pdfbookmark[\the\seclevel]{#1}{envdef-#1}% \DescribeEnv{#1}% \hyperdef{env}{#1}{}\kern0pt% } \newcommand{\mac}[1]{{\tt\hyperlink{macro.#1}{\char92 #1}}} \newcommand{\env}[1]{{\tt\hyperlink{env.#1}{#1}}} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{trfrac.dtx} \end{document} % % \fi % % \CheckSum{412} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \changes{v1.0}{2005/09/05}{Initial version} % \changes{v2.0}{2006/05/01}{Renamed to TrFrac package} % % \DoNotIndex{\@depth,\@height,\@width} % \DoNotIndex{\advance,\begingroup,\bgroup,\box,\def,\dp,\egroup,\else} % \DoNotIndex{\endgroup,\fi,\fontdimen,\futurelet,\global} % \DoNotIndex{\hb@xt@,\hbox,\hfil,\hss,\ht,\ifdim,\ifmmode,\ifnum,\ifx} % \DoNotIndex{\kern,\let,\m@th,\newcommand,\newenvironment,\newif} % \DoNotIndex{\null,\offinterlineskip,\p@,\PackageError,\penalty} % \DoNotIndex{\protect,\raise,\relax,\setbox,\space,\strut} % \DoNotIndex{\textfont,\thr@@,\tw@,\unhbox,\vbox,\vrule,\vtop,\wd,\z@} % % \GetFileInfo{trfrac.dtx} % % \title{The \textsf{trfrac} package\thanks{This document corresponds to % \textsf{trfrac}~\fileversion, dated~\filedate.}} % \author{Kevin W.~Hamlen} % % \maketitle % % \begin{abstract} % The |trfrac| package provides convenient mechanisms for typesetting % derivation trees in \LaTeX. % Derivation trees look like nested fractions; thus, the primary contribution % of this software is a macro |\trfrac| that functions much like \LaTeX's % |\frac| for fractions, but with a number of important differences that make % it better suited to tree-like structures. % \end{abstract} % % \section{Introduction} % % Typing rules and typing derivations in formal typing systems are usually % written like fractions in which the numerator consists of one or more % premise judgments or derivations, and the denominator consists of a % single conclusion judgment. % For example, the typing rule for application in the simply-typed lambda % calculus is typically written % \[ \trfrac[\small(\emph{app})] % {\Gamma \vdash e_1:\tau\rightarrow\tau' \qquad % \Gamma \vdash e_2:\tau} % {\Gamma \vdash e_1 e_2 : \tau'} \] % where $\Gamma \vdash e_1:\tau\rightarrow\tau'$ and $\Gamma \vdash e_2:\tau$ % are the two premise judgments of the rule, and % $\Gamma \vdash e_1 e_2 : \tau'$ is the conclusion judgment. % % Simple rules like the above are easy to typeset with \LaTeX's built-in % |\frac| macro, or with fraction macros like |\dfrac| provided by the % |amslatex| package; but when derivations consist of a tree of nested rules, % |\frac| and |\dfrac| often prove inadequate because they yield spacing % and alignment that is unsuited to derivation trees. % For example, consider the derivation % \[ \trfrac[\small(\emph{app})] % {\Gamma \vdash e_1:\tau\rightarrow\tau' \qquad % \trfrac[\small(\emph{app})] % {\Gamma \vdash e_2:\tau''\rightarrow\tau \qquad % \Gamma \vdash e_3:\tau''} % {\Gamma \vdash e_2 e_3:\tau}} % {\Gamma \vdash e_1 (e_2 e_3):\tau'} \] % which contains a nested subderivation of one of its premise judgments. % This was easily typeset using the |\trfrac| macro provided by % the |trfrac| package. % The complete \LaTeX\ code is as follows: % \begin{verbatim} % \[ \trfrac[\small(\emph{app})] % {\Gamma \vdash e_1:\tau\rightarrow\tau' \qquad % \trfrac[\small(\emph{app})] % {\Gamma \vdash e_2:\tau''\rightarrow\tau \qquad % \Gamma \vdash e_3:\tau''} % {\Gamma \vdash e_2 e_3:\tau}} % {\Gamma \vdash e_1 (e_2 e_3):\tau'} \] % \end{verbatim} % In contrast, if one writes analogous code using |\dfrac| instead of % |\trfrac|, the result is % \[ \dfrac{\Gamma \vdash e_1:\tau\rightarrow\tau' \qquad % \dfrac{\Gamma \vdash e_2:\tau''\rightarrow\tau \qquad % \Gamma \vdash e_3:\tau''} % {\Gamma \vdash e_2 e_3:\tau}\text{\small(\emph{app})}} % {\Gamma \vdash e_1 (e_2 e_3):\tau'}\text{\small(\emph{app})} \] % which is unsuitable for two reasons: % First, the leftmost premise is floating up above the fraction bar when % it should be sitting on the bar. % Second, the bottom fraction bar is longer than it should be; it has been % unnecessarily extended rightward to span the entire ``numerator'' of the % ``fraction''. % This can become problematic when derivations are large and horizontal % space is at a premium. % % In addition to providing |\trfrac| as an alternative to fraction macros, % the |trfrac| package also provides two environments that can be helpful % for squeezing numerous and/or lengthy premise judgments into a smaller % amount of horizontal space. % Derivations can sometimes contain long judgments that must be wrapped, or % numerous premise judgments that must be placed above one another for lack % of space. % The |trfrac| package provides math environments |trgather| and |tralign| % for stacking sets of judgments vertically within a derivation tree. % The |trgather| environment horizontally centers each judgment in the stack, % whereas the |tralign| environment aligns each judgment at a specified point. % For example, the derivation % \[ \trfrac[\small(\emph{case})] % {\begin{trgather} % \Gamma \vdash e:\tau_1+\tau_2 \\ % \Gamma[x_1\mapsto\tau_1] \vdash e_1:\tau \qquad % \Gamma[x_2\mapsto\tau_2] \vdash e_2:\tau % \end{trgather}} % {\begin{tralign} % \Gamma \vdash \mathbf{case}~e~\mathbf{of}~ % &\mathit{in}_1(x_1)\Rightarrow e_1 \\ % \mid\,&\mathit{in}_2(x_2)\Rightarrow e_2 : \tau % \end{tralign}} \] % can be produced with % \begin{verbatim} % \[ \trfrac[\small(\emph{case})] % {\begin{trgather} % \Gamma \vdash e:\tau_1+\tau_2 \\ % \Gamma[x_1\mapsto\tau_1] \vdash e_1:\tau \qquad % \Gamma[x_2\mapsto\tau_2] \vdash e_2:\tau % \end{trgather}} % {\begin{tralign} % \Gamma \vdash \mathbf{case}~e~\mathbf{of}~ % &\mathit{in}_1(x_1)\Rightarrow e_1 \\ % \mid\,&\mathit{in}_2(x_2)\Rightarrow e_2 : \tau % \end{tralign}} \] % \end{verbatim} % % The |split| and |aligned| environments provided by the |amsmath| package % provide facilities for vertically stacking sub-equations in similar ways, % but like |\dfrac|, these often prove inadequate for derivation trees % because they vertically center the material they typeset, causing any % adjacent material to float above the fraction bar. % % \section{Usage} % % To start using the macros and environments provided by the |trfrac| package, % place the line % % \medskip{\narrower|\usepackage{trfrac}|}\medskip % % \noindent % somewhere near the top of your \TeX\ file. % % \DescMacro{trfrac} % Subsequently, within any math environment you can use % % \medskip{\narrower % |\trfrac[|\meta{name}|]{|\meta{premises}|}{|\meta{consequent}|}| % }\medskip % % \noindent % to typeset a derivation rule, where % \meta{name} is optional material processed in horizontal text mode % that is to sit to the right of the fraction bar, % \meta{premises} is math material that is to sit above the fraction bar, and % \meta{consequent} is math material that is to sit below the fraction bar. % The \meta{consequent} and \meta{name} may not contain additional |\trfrac| % macros, but the \meta{premises} may. % % The outermost |\trfrac| in a derivation is vertically centered on its % fraction bar, but inner |\trfrac|'s in a derivation have baselines at % the bottoms of their consequents. % This makes it possible to typeset something like % \[ {\cal D} = % \trfrac[\small(\emph{app})] % {\Gamma \vdash e_1:\tau\rightarrow\tau' \qquad % \trfrac[\small(\emph{app})] % {\Gamma \vdash e_2:\tau''\rightarrow\tau \qquad % \Gamma \vdash e_3:\tau''} % {\Gamma \vdash e_2 e_3:\tau}} % {\Gamma \vdash e_1 (e_2 e_3):\tau'} \] % in which the material ``${\cal D} =$'' should be vertically centered with % respect to the bottom fraction bar, but the left premise should not be % centered with respect to the right subderivation's fraction bar. % % \DescEnv{trgather} % The environment % % \medskip{\narrower\parindent=0pt % |\begin{trgather}|\par % \hskip1em \meta{eqn$_1$} |\\[|\meta{len$_1$}|]|\par % \hskip1em \meta{eqn$_2$} |\\[|\meta{len$_2$}|]|\par % \hskip2em $\vdots$\par % \hskip1em \meta{eqn$_n$} |\\[|\meta{len$_n$}|]|\par % |\end{trgather}|\par % }\medskip % % \noindent % can be used in math mode to stack a set of equations, each of which is to % be centered horizontally over one another. % Here, \meta{eqn$_i$} is material processed in math mode and % \meta{len$_i$} is an optional length that modifies the vertical spacing % between the current equation and the next. % The baseline of the resulting stack of equations is the baseline of % the bottom equation in the stack. % % \DescEnv{tralign} % The environment % % \medskip{\narrower\parindent=0pt % |\begin{tralign}|\par % \hskip1em \meta{left$_1$}|&|\meta{right$_1$} |\\[|\meta{len$_1$}|]|\par % \hskip1em \meta{left$_2$}|&|\meta{right$_2$} |\\[|\meta{len$_2$}|]|\par % \hskip2em $\vdots$\par % \hskip1em \meta{left$_n$}|&|\meta{right$_n$} |\\[|\meta{len$_n$}|]|\par % |\end{tralign}|\par % }\medskip % % \noindent % can be used in math mode to stack a set of equations, each of which is to % be aligned horizontally by the position of the |&| in the equation. % Here, \meta{left$_i$} and \meta{right$_i$} is the math material to be % placed to the left and right, respectively, of the vertical center axis of % the resulting stack of equations; % and \meta{len$_i$} is an optional length that modifies the vertical % spacing between the current equation and the next. % The baseline of the resulting stack of equations is the baseline of % the bottom equation in the stack. % % \DescMacro{trtopgap} % \DescMacro{trbotgap} % The space just above and just below each fraction bar can be adjusted by % changing the values of lengths |\trtopgap| and |\trbotgap|. % For example, to decrease the distance between fraction bars and numerators % by 2 points and increase the distance between fraction bars and denominators % by 1 point of space, you could write: % % \medskip{\narrower\parindent=0pt % |\trtopgap=-2pt|\par % |\trbotgap=1pt|\par % }\medskip % % \StopEventually{\PrintIndex} % % \section{Implementation} % % The following is a verbatim listing of the |trfrac| package implementation % with comments explaining how it works. % % \begin{macro}{\trtopgap} % \begin{macro}{\trbotgap} % Declare dimension registers that allow users to control the amount of % space above and below fraction bars. % \begin{macrocode} \newdimen\trtopgap\trtopgap\z@ \newdimen\trbotgap\trbotgap\z@ % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\TRF@startp} % \begin{macro}{\TRF@endp} % When processing a numerator, the |\TRF@trfrac| code must be able to determine % if (a)~the current derivation is the first thing being added to the current % horizontal list, and if (b)~the current horizontal list ends in a derivation. % To accomplish this, two sentinal penalties are added to horizontal lists: % |\TRF@startp| is added at the beginning of a horizontal list comprising a % numerator, and |\TRF@endp| is added just after every derivation. % Then |\lastpenalty| can be used to inquire whether the current horizontal % list ends in either penalty. % (Since derivations encased within numerators cannot undergo line-breaking, % these extra penalties will have no effect on \LaTeX's processing of the % actual output.) % \begin{macrocode} \newcommand\TRF@startp{31415926} \newcommand\TRF@endp{27182818} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\ifTRF@first} % In accordance with the above, the following conditional remembers if the % current derivation is the first in the horizontal list comprising the % numerator of a larger derivation. % \begin{macrocode} \newif\ifTRF@first % \end{macrocode} % \end{macro} % % \begin{macro}{\ifTRF@outer} % The outermost derivation behaves slightly differently than subderivations % within a derivation tree. % (Its baseline is its fraction bar instead of its denominator's baseline, % and it should not include the spurious |\TRF@endp| penalty, since % line-breaking might occur.) % The following conditional therefore remembers whether we're at the % outermost level. % \begin{macrocode} \newif\ifTRF@outer\TRF@outertrue % \end{macrocode} % \end{macro} % % \begin{macro}{\ifTRF@derivok} % Subderivations are not permitted to appear within denominators or within % rule names. % The |\ifTRF@derivok| conditional is set to |false| when processing such % material. % \begin{macrocode} \newif\ifTRF@derivok\TRF@derivoktrue % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@lhang} % \begin{macro}{\TRF@rhang} % After processing a horizontal list that might contain one or more % derivations, |\TRF@lhang| holds the distance from the left edge of the % resulting box to the leftmost item's denominator % (or |0pt| if the leftmost list item is not a derivation), % and |\TRF@rhang| holds the distance from the rightmost item's denominator % to the right edge of the resulting box % (or |0pt| if the rightmost list item is not a derivation). % \begin{macrocode} \newdimen\TRF@lhang\TRF@lhang\z@ \newdimen\TRF@rhang\TRF@rhang\z@ % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\TRF@lsave} % We also need a place to save the value of |\TRF@lhang| so that we can % (sometimes) restore it to its original value after it has been globally % modified by nested |\trfrac| macros. % \begin{macrocode} \newdimen\TRF@lsave % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@ni} % \begin{macro}{\TRF@bi} % \begin{macro}{\TRF@bw} % The temporary registers declared below store the the numerator indentation, % bar indentation, and bar width, respectively, when typesetting a % derivation rule. % \begin{macrocode} \newdimen\TRF@ni \newdimen\TRF@bi \newdimen\TRF@bw % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\TRF@numbox} % \begin{macro}{\TRF@denombox} % \begin{macro}{\TRF@eqbox} % While constructing a derivation, the following three boxes hold the % derivation's numerator, denominator, and rule name, respectively. % \begin{macrocode} \newbox\TRF@numbox \newbox\TRF@denombox \newbox\TRF@eqbox % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\TRF@trfrac} % The following macro typesets a single derivation rule in a derivation tree. % Its arguments are % (1)~the rule name (processed in horizontal mode), % (2)~the numerator (processed in math mode), and % (3)~the denominator (processed in math mode). % \begin{macrocode} \newcommand\TRF@trfrac[3]{% \begingroup% % \end{macrocode} % We start by saving the original value of |\TR@lhang| and deciding whether % this is the first subderivation in a numerator of a larger derivation. % These must come before anything else, and the results used later. % \begin{macrocode} \ifnum\lastpenalty=\TRF@startp\relax% \TRF@firsttrue% \else% \TRF@firstfalse% \fi% \TRF@lsave\TRF@lhang% % \end{macrocode} % Typeset the equation number and put it in a box. % \begin{macrocode} \setbox\TRF@eqbox\hbox{\TRF@derivokfalse#1}% \ifdim\wd\TRF@eqbox>\z@% \setbox\TRF@eqbox\hbox{\kern\p@\unhbox\TRF@eqbox}% \fi% % \end{macrocode} % Typeset the numerator and put it in a box. % We begin the box with the |\TRF@startp| penalty so that if the first list % item is a derivation, it will see that nothing has preceded it and will % therefore set |\TRF@lhang|. % We initialize it to zero so that if the first item is not a derivation, % |\TRF@lhang| will remain zero. % If the last thing in the numerator is a |\TRF@endp| penalty, then the list % must have ended with a subderivation whose denominator is a distance % |\TRF@rhang| from its right edge. % Otherwise the rightmost item was not a subderivation, so we zero % |\TRF@rhang|. % \begin{macrocode} \TRF@lhang\z@% \setbox\TRF@numbox\hbox{% \TRF@outerfalse% \m@th$\strut% \penalty\TRF@startp\relax% #2% \ifnum\lastpenalty=\TRF@endp\relax\else% \global\TRF@rhang\z@% \fi% $% }% % \end{macrocode} % Finally, typeset the denominator in a box. % Denominators may not contain subderivations, so this preserves the % values of |\TRF@lhang| and |\TRF@rhang|. % \begin{macrocode} \setbox\TRF@denombox\hbox{% \TRF@derivokfalse% \m@th$\strut#3$% }% % \end{macrocode} % Compute the % bar width $\mathit{bw}=\max(n-l-r,d)$, % denominator indentation $l'=\max((n-r+l)-d,0)/2$, % numerator indentation $\mathit{ni}=\max(d-(n-r+l),0)/2$, and % bar indentation $\mathit{bi}=\min(\mathit{ni}+l,\mathit{di})$, % respectively, where $n$ is the numerator width, $d$ is the denominator % width, $l$ is the old value of |\TRF@lhang|, and $r$ is |\TRF@rhang|. % \begin{macrocode} \dimen@\wd\TRF@numbox% \advance\dimen@-\TRF@rhang% \TRF@bw\dimen@% \advance\TRF@bw-\TRF@lhang% \ifdim\wd\TRF@denombox>\TRF@bw\TRF@bw\wd\TRF@denombox\fi% \advance\dimen@\TRF@lhang% \advance\dimen@-\wd\TRF@denombox% \TRF@ni\ifdim\dimen@>\z@\z@\else-.5\dimen@\fi% \TRF@bi\TRF@ni% \advance\TRF@bi\TRF@lhang% \TRF@lhang\ifdim\dimen@<\z@\z@\else.5\dimen@\fi% \ifdim\TRF@bi>\TRF@lhang\TRF@bi\TRF@lhang\fi% % \end{macrocode} % Compute the new value of |\TRF@rhang| as % $r'=\max(\mathit{ni}+n,\mathit{bi}+\mathit{bw}+e)-l'-d$, % where $e$ is the width of the equation number. % The final result is globally assigned so that its value will persist % beyond the local scope in which numerators are typeset. % \begin{macrocode} \TRF@rhang\TRF@ni% \advance\TRF@rhang\wd\TRF@numbox% \dimen@\TRF@bi% \advance\dimen@\TRF@bw% \advance\dimen@\wd\TRF@eqbox% \ifdim\dimen@>\TRF@rhang\TRF@rhang\dimen@\fi% \advance\TRF@rhang-\TRF@lhang% \advance\TRF@rhang-\wd\TRF@denombox% \global\TRF@rhang\TRF@rhang% % \end{macrocode} % Begin typesetting the final fraction as a math-inner node. % The vbox that comprises the node has an hbox comprising the denominator on % the bottom and an hbox comprising everything else on the top. % This allows the denominator baseline to become the baseline of the entire % fraction. % If this is the outermost level, the final box is set with |\vtop| so that % the numerator is the baseline, and then raised a bit so that the fraction % bar becomes the baseline. % \begin{macrocode} \mathinner{% \ifTRF@outer% \raise\fontdimen22\textfont\tw@\vtop% \else% \vbox% \fi% {% \offinterlineskip% \hbox{% \vbox{% % \end{macrocode} % Compute the distance between the numerator and the fraction bar. % The formula for computing this number is given in step 15d of Appendix G % of {\it The \TeX book} (p.~445). % \begin{macrocode} \dimen@\fontdimen8\textfont\tw@% \advance\dimen@-\fontdimen22\textfont\tw@% \advance\dimen@-.5\fontdimen8\textfont\thr@@% \advance\dimen@-\dp\TRF@numbox% \ifdim\dimen@<3\fontdimen8\textfont\thr@@% \dimen@3\fontdimen8\textfont\thr@@% \fi% \advance\dimen@\trtopgap% % \end{macrocode} % Typeset the numerator part, horizontally centered over the fraction bar % (but possibly overhanging the equation number). % \begin{macrocode} \hbox{\kern\TRF@ni\unhbox\TRF@numbox}% \kern\dimen@% % \end{macrocode} % Typeset the fraction bar followed by the equation number. % The height of the fraction bar is based on math font metric~8. % The equation number is typeset at zero height so that it does not push % the numerator or denominator away from the fraction bar. % \begin{macrocode} \hbox{% \kern\TRF@bi% \vrule\@width\TRF@bw% \@height.5\fontdimen8\textfont\thr@@% \@depth.5\fontdimen8\textfont\thr@@% \vbox{% \dimen@.5\ht\TRF@eqbox% \advance\dimen@.5\dp\TRF@eqbox% \kern-\dimen@% \box\TRF@eqbox% \kern-\dimen@% }% }% }% }% % \end{macrocode} % Insert the vertical space that separates a fraction bar from its % denominator. % See step 15d of Appendix G of {\it The \TeX book} (p.~445) for a % derivation of this distance. % \begin{macrocode} \dimen@\fontdimen11\textfont\tw@% \advance\dimen@\fontdimen22\textfont\tw@% \advance\dimen@-.5\fontdimen8\textfont\thr@@% \advance\dimen@-\ht\TRF@denombox% \ifdim\dimen@<3\fontdimen8\textfont\thr@@% \dimen@3\fontdimen8\textfont\thr@@% \fi% \advance\dimen@\trbotgap% \kern\dimen@% % \end{macrocode} % Typeset the denominator horizontally centered below the fraction bar. % \begin{macrocode} \hbox{\kern\TRF@lhang\box\TRF@denombox}% }% }% % \end{macrocode} % If this is a subderivation within another, add a |\TRF@endp| penalty to % the current horizontal list so that if this is the last item in a numerator, % the value we computed for |\TRF@rhang| will be used by the outer derivation % to determine the amount by which its numerator may overhang the fraction % bar to the right. % \begin{macrocode} \ifTRF@outer\else% \penalty\TRF@endp\relax% \fi% % \end{macrocode} % If this is the leftmost subderivation in the numerator of another derivation, % the value of |\TRF@lhang| must be made global so that it can be used by the % outer derivation to compute the amount by which its numerator may overhang % the fraction bar to the left. % Otherwise |\TRF@lhang| must be restored to whatever value it had on entrance % to this |\trfrac|. % (It is not enough to just let it get restored to whatever it was before the % current local scope, since some nested modifications to it might have been % global.) % \begin{macrocode} \global\TRF@lhang\ifTRF@first\TRF@lhang\else\TRF@lsave\fi% \endgroup% } % \end{macrocode} % \end{macro} % % \begin{macro}{\trfrac} % The following is the entrypoint to the derivation code. % The |\trfrac| macro takes one optional argument which, if present, is the % name of the rule (processed in horizontal mode), % followed by two mandatory arguments---the rule's numerator and denominator. % Derivations can only appear in math mode, and cannot appear within the % denominator of another derivation or within its rule name. % \begin{macrocode} \newcommand\trfrac[3][]{% \ifTRF@derivok% \ifmmode% \TRF@trfrac{#1}{#2}{#3}% \else% \TRF@mmerr% \fi% \else% \TRF@derr% \fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@mmerr} % Produce an error if |\trfrac| is used outside of math mode. % \begin{macrocode} \newcommand\TRF@mmerr{% \PackageError{trfrac}{\protect\trfrac\space% only allowed in math mode}% {I encountered a \protect\trfrac\space% macro without first encountering a begin-math token.}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@derr} % Subderivations within denominators are not supported because that would % require computing chiastic structures rather than tree structures. % \begin{macrocode} \newcommand\TRF@derr{% \PackageError{trfrac}{\protect\trfrac\space% not allowed in the consequent of another \protect\trfrac}% {\protect\trfrac\space can only appear in the premise (numerator% ) of another \protect\trfrac, not in the consequent (denominator% ) of a \protect\trfrac.}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@next} % The |\TRF@next| token is here reserved so that it can be used in conjunction % with |\futurelet| (when processing optional arguments). % \begin{macrocode} \newcommand\TRF@next{} % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@sep} % In a |trgather| or |tralign| environment, the |\\| macro is used to delimit % lines. % It is temporarily set equal to |\TRF@sep| (below), which is just like |\cr| % in an |\halign| except that it takes an optional length argument that % has the effect of inserting a vertical space between the lines. % \begin{macrocode} \newcommand\TRF@sep{\futurelet\TRF@next\TRF@@sep} % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@@sep} % The following processes the optional argument to |\TRF@sep|. % \begin{macrocode} \newcommand\TRF@@sep{% \ifx[\TRF@next% \let\TRF@next\TRF@separg% \else% \let\TRF@next\TRF@sepnoarg% \fi% \TRF@next% } % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@separg} % The following is the code for a |\TRF@sep| that has been provided the % optional argument. % \begin{macrocode} \newcommand\TRF@separg{} \def\TRF@separg[#1]{\cr\noalign{\kern#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\TRF@sepnoarg} % The following is the code for a |\TRF@sep| that has not been provided the % optional argument. % You might think that it would have been simpler to use |\let| instead of % |\newcommand| in the line below, or even to just use |\cr| within some of % the code above instead of defining this new macro at all, % but |\cr| is a strange beast; it can only be expanded onto the token % stream when we're sure of everything that is to follow it. % \begin{macrocode} \newcommand\TRF@sepnoarg{\cr} % \end{macrocode} % \end{macro} % % \begin{environment}{trgather} % A |trgather| environment is just like |amsmath|'s |gathered| environment % except that its baseline is at the bottom instead of in the middle. % \begin{macrocode} \newenvironment{trgather}{% \vbox\bgroup% \let\\\TRF@sep% \ialign\bgroup\hfil{\m@th$##$}\hfil\cr% }{% \crcr\egroup\egroup% } % \end{macrocode} % \end{environment} % % \begin{environment}{tralign} % A |tralign| environment is like |amsmath|'s |aligned| environment except that % its baseline is at the bottom instead of in the middle, and it's restricted % to two columns (for simplicity). % \begin{macrocode} \newenvironment{tralign}{% \vbox\bgroup% \let\\\TRF@sep% \ialign\bgroup\hfil{\m@th$##\null$}&{\m@th$\null##$}\hfil\cr% }{% \crcr\egroup\egroup% } % \end{macrocode} % \end{environment} % % \Finale \endinput