diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/boolexpr/boolexpr.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/boolexpr/boolexpr.dtx | 1052 |
1 files changed, 1052 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/boolexpr/boolexpr.dtx b/Master/texmf-dist/source/latex/boolexpr/boolexpr.dtx new file mode 100644 index 00000000000..fb4f03f7095 --- /dev/null +++ b/Master/texmf-dist/source/latex/boolexpr/boolexpr.dtx @@ -0,0 +1,1052 @@ +% \iffalse meta-comment +% boolexpr : purely expandable boolean expressions and switch (eTeX) +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either +% version 1.3 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 +% +% Copyright (C) 2009 by Florent Chervet <florent.chervet@free.fr> +% +% This work consists of the main source file keycommand.dtx +% and the derived files +% boolexpr.sty, boolexpr.pdf, boolexpr.ins, +% +% Unpacking: +% (a) If boolexpr.ins is present: +% etex boolexpr.ins +% (b) Without boolexpr.ins: +% etex boolexpr.dtx +% (c) If you insist on using LaTeX +% latex \let\install=y\input{boolexpr.dtx} +% (quote the arguments according to the demands of your shell) +% +% Documentation: +% (pdf)latex boolexpr.dtx +% +%<*ignore> +\begingroup + \def\x{LaTeX2e}% +\expandafter\endgroup +\ifcase 0\ifx\install y1\fi\expandafter + \ifx\csname processbatchFile\endcsname\relax\else1\fi + \ifx\fmtname\x\else 1\fi\relax +\else\csname fi\endcsname +%</ignore> +%<*install> +\input docstrip.tex +\Msg{************************************************************************} +\Msg{* Installation} +\Msg{* Package: boolexpr 2009/08/12 v2.1 provides purely expandable boolean expressions and switch (eTeX)} +\Msg{************************************************************************} + +\keepsilent +\askforoverwritefalse + +\let\MetaPrefix\relax +\preamble + +This is a generated file. + +boolexpr : a purely expandable boolean expressions and switch (eTeX) + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either +version 1.3 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 + +Copyright (C) 2009 by Florent Chervet <florent.chervet@free.fr> + +This work consists of the main source file boolexpr.dtx +and the derived files + boolexpr.sty, boolexpr.pdf, boolexpr.ins, + +boolexpr : a purely expandable boolean expressions and switch (eTeX) +\endpreamble +\let\MetaPrefix\DoubleperCent + +\generate{% + \file{boolexpr.ins}{\from{boolexpr.dtx}{install}}% + \file{boolexpr.sty}{\from{boolexpr.dtx}{package}}% +} + +\obeyspaces +\Msg{************************************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the following} +\Msg{* file into a directory searched by TeX:} +\Msg{*} +\Msg{* boolexpr.sty} +\Msg{*} +\Msg{* To produce the documentation run the file `boolexpr.dtx'} +\Msg{* through LaTeX.} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{*} +\Msg{************************************************************************} + +\endbatchfile +%</install> +%<*ignore> +\fi +%</ignore> +%<*driver> +\edef\thisfile{\jobname} +\def\thisinfo{Purely expandable boolean expressions and switch (\eTeX).} +\let\loadclass\LoadClass +\def\LoadClass#1{\loadclass[abstracton]{scrartcl}\let\scrmaketitle\maketitle\AtEndOfClass{\let\maketitle\scrmaketitle}} +\documentclass[a4paper,oneside]{ltxdoc} +\usepackage{tracing} +\usepackage[latin9]{inputenc} +\usepackage[american]{babel} +\usepackage{etex,holtxdoc,etoolbox,geometry,tocloft,fancyhdr,color,bbding,embedfile,enumitem,framed,txfonts,relsize}\CodelineNumbered +\usepackage{fancyvrb} +\IfFileExists{boolexpr.sty} + {\RequirePackage{boolexpr}} + \relax +\embedfile{\thisfile.dtx} +\geometry{top=2cm,headheight=1cm,headsep=.3cm,bottom=1.4cm,footskip=.5cm,left=4cm,right=2cm} +\hypersetup{% + pdftitle={The boolexpr package}, + pdfsubject={An e-TeX package for more useful tools for LaTeX package writers}, + pdfauthor={Florent CHERVET}, + colorlinks,linkcolor=reflink,urlcolor=refurl, + pdfstartview={FitH}, + pdfkeywords={tex, e-tex, latex, package, boolexpr, boolean, ifthen, ifthenelse, conditionals}, + bookmarksopen=true,bookmarksopenlevel=2} +\begin{document} + \DocInput{\thisfile.dtx} +\end{document} +%</driver> +% \fi +% +% \CheckSum{257} +% +% \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 \~} +% +% \DoNotIndex{\begin,\CodelineIndex,\CodelineNumbered,\def,\DisableCrossrefs} +% \DoNotIndex{\DocInput,\documentclass,\EnableCrossrefs,\end,\GetFileInfo} +% \DoNotIndex{\NeedsTeXFormat,\OnlyDescription,\RecordChanges,\usepackage} +% \DoNotIndex{\ProvidesClass,\ProvidesPackage,\ProvidesFile,\RequirePackage} +% \DoNotIndex{\filename,\fileversion,\filedate,\let} +% \DoNotIndex{\@listctr,\@nameuse,\csname,\else,\endcsname,\expandafter} +% \DoNotIndex{\gdef,\global,\if,\item,\newcommand,\nobibliography} +% \DoNotIndex{\par,\providecommand,\relax,\renewcommand,\renewenvironment} +% \DoNotIndex{\stepcounter,\usecounter,\nocite,\fi} +% \DoNotIndex{\@fileswfalse,\@gobble,\@ifstar,\@unexpandable@protect} +% \DoNotIndex{\AtBeginDocument,\AtEndDocument} +% \DoNotIndex{\frenchspacing,\MessageBreak,\newif,\PackageWarningNoLine} +% \DoNotIndex{\protect,\string,\xdef,\ifx,\texttt,\@biblabel,\bibitem} +% \DoNotIndex{\z@,\wd,\vrule,\voidb@x,\verb,\bibitem} +% \DoNotIndex{\hskip,\hfil,\hfill,\hsize,\hspace,\hss,\hbox,\hb@xt@,\escapechar} +% \DoNotIndex{\date,\ifdefined,\ifhmode,\ifmmode,\cr} +% \DoNotIndex{\box,\author,\advance,\multiply,\Command,\outer,\kern,\title,\tt} +% \DoNotIndex{\the,\space,\section,\subsection,\textwidth} +% \DoNotIndex{\",\@empty,\@latex@error,\makeatletter,\makeatother} +% \DoNotIndex{\maketitle,\parindent,\setbox} +% +% +% \makeatletter +% \lastlinefit999 +% \newif\ifboolexprLoaded +% \ifdefined\boolexpr\boolexprLoadedtrue\else\boolexprLoadedfalse\fi +% \newcommand\macrocodecolor{\color{macrocode}}\definecolor{macrocode}{rgb}{0.18,0.00,0.45} +% \newcommand\reflinkcolor{\color{reflink}}\definecolor{reflink}{rgb}{0.49,0.00,0.00} +% \newcommand\refurlcolor{\color{refurl}}\definecolor{refurl}{rgb}{0.00,0.00,1.00} +% \newcommand\cmdref[1]{\hyperref[#1]{\underline{\reflinkcolor\CS{#1}}}} +% \newcommand\cmdlabel[1]{\label{#1}\hyperdef{cmdlabel}{#1}{}} +% \definecolor{dg}{rgb}{0.02,0.37,0.00} +% \def\ThisPackage{\Xpackage{\thisfile}}\def\thispackage{\xpackage{\thisfile}} +% \fancyhf{}\fancyhead[L]{\thispackage\ -- \thisinfo} +% \fancyfoot[L]{\color[gray]{.35}\scriptsize\thispackage\quad\copyright\oldstylenums{2009}\,\lower.3ex\hbox{\NibRight}\,Florent Chervet} +% \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}} +% \pagestyle{fancy} +% \fancypagestyle{plain}{\fancyhf{}\let\headrulewidth\z@\fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}}} +% +% \catcode`\§\active\def§{\par\nobreak\vskip-\parskip} +% \newlength\saveparskip\saveparskip.4\baselineskip +% \newcommand\restoreparskip{\parskip\saveparskip} +% \parindent\z@\parskip\saveparskip\topsep\z@\partopsep\z@ +% \g@addto@macro\macro@font{\macrocodecolor\let\AltMacroFont\macro@font} +% \def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}} +% \def\csred#1{\textcolor{red}{\cs{#1}}} +% \def\CSif\bgroup\ignorespaces#1{\bgroup\ignorespaces\ifx#1\unskip\else \CS{#1}\fi} +% \def\CSbf#1{\textbf{\CS{#1}}} +% \def\Repeat#1#2{\ifnum\numexpr#1\relax>0\relax #2\relax\Repeat{#1-1}{#2}\fi} +% \def\Xpackage{\@dblarg\X@package} +% \def\X@package[#1]#2{% +% \xpackage{#2\footnote{\noindent\xpackage{#2}: \href{http://www.ctan.org/tex-archive/macros/latex/contrib/#1}{\nolinkurl{CTAN:macros/latex/contrib/#1}}}}} +% \deffootnote{1em}{0pt}{\rlap{\textsuperscript{\thefootnotemark}}\kern1em} +% \def\nq{\,!\!=} +% \def\nq{<>} +% \def\ie{\textsl{ie.\,}} +% \newbox\Sharpbox\setbox\Sharpbox=\hbox{|#|} +% \newcommand\Sharp[1]{\usebox\Sharpbox|#1|} +% \newcommand\myfbox[2][3em]{\fbox{\hbox to#1{\hss#2\hss}}} +% \newbox\boxedb@x +% \newcommand\boxedbox[1]{\setbox\boxedb@x\vbox{#1}\fbox{\box\boxedb@x}} +% \DefineVerbatimEnvironment{VerbEx}{Verbatim}{gobble=1,commandchars=![]} +% \newcommand\evaluated{\textcolor{blue}} +% \newcommand\notevaluated{\textcolor{black}} +% \newcommand\stripmeaning{\expandafter\strip@prefix\meaning} +% \makeatother +% +% \title{\mdseries The {\bfseries \ThisPackage}\kern.6em package} +% \author{Florent Chervet {\small\xemail{florent.chervet@free.fr}}} +% \date{July 22, 2009} +% \subtitle{\thisinfo} +% +% \maketitle \vskip-2\baselineskip\strut +% +% \makeatletter\begingroup\let\@thefnmark\@empty\let\@makefntext\@firstofone +% \footnotetext{\noindent +% This documentation is produced with the |DocStrip| utility. +% \begin{tabbing} +% \qquad\=\smex\=To get the documentation, \= run (thrice):\quad\= \texttt{pdflatex boolexpr.dtx} \\ +% \>\>for the index:\>\>\texttt{makeindex -s gind.ist boolexpr.idx} \\ +% \>\smex\>To get the package, \> run:\> \texttt{etex boolexpr.dtx} +% \end{tabbing}§ +% The \xext{dtx} file is embedded into this pdf file thank to \xpackage{embedfile} by H. Oberdiek.} +% \endgroup\makeatother +% +% \deffootnote{1em}{0pt}{\rlap{\thefootnotemark.}\kern1em} +% +% \begin{abstract}\parindent0pt\noindent\parskip\medskipamount\small\abovedisplayskip=0pt\belowdisplayskip=0pt +% \vskip-\baselineskip +% \xpackage{boolexpr} provides a purely expandable way to evaluate boolean expressions of the form: +% +% \hfil\framebox[.618\linewidth][c]{$\alpha\quad\cs{AND}\quad\beta\quad\cs{OR}\quad\gamma\quad\dots$}\hfil +% +% where $\alpha$\,,\, $\beta$\, and $\gamma$ are \textit{atomic expressions} of one of those 8 valid forms: +% \begin{center} +% \begin{tabular}{*{6}{>{\hskip4pt}c<{\hskip4pt}}} +% \myfbox{$x=y$} & \myfbox{$x\nq y$}\footnotemark & \myfbox{$x<y$} & \myfbox{$x<=y$} & \myfbox{$x>y$} & \myfbox{$x>=y$} \\[12pt] +% \multicolumn{3}{c}{\myfbox[4.5cm]{\cs{if}\meta{test}\ $0$\cs{else} $1$\cs{fi}}} & +% \multicolumn{3}{c}{\myfbox[4.5cm]{another \cs{boolexpr} evaluation}} +% \end{tabular}\end{center} +% \footnotetext{The choice of $\nq$ rather than $\char33\!=$ is due to \nameref{catcodes}.} +% +% where $x$ and $y$ are either numeric expressions (or dimensions, glue, muglue to test using |\dimexpr|, |\glueexpr| +% or |\muexpr| -- please refer to the \nameref{examples}) and \meta{test} may be a switch (\cs{iftrue} / \cs{iffalse} +% or a conditional\footnote{\cs{if}, \cs{ifcase}, \cs{ifcat}, \cs{ifcsname}, \cs{ifdefined}, \cs{ifdim}, \cs{ifeof}, +% \cs{iffontchar}, \cs{ifhmode}, \cs{ifinner}, \cs{ifmmode}, \cs{ifnum}, \cs{ifodd}, \cs{ifvmode}, \cs{ifvoid}, \cs{ifx}}). +% \xpackage{boolexpr} abide by the precedence of |\AND| on |\OR|, +% and the whole expression is evaluated until the result is known (in other words, |\AND| and |\OR| are \textit{shortcut} +% boolean operators). +% +% \cmdref{boolexpr} will expand to \textbf{0} if the expression is \textbf{true}, making it proper to work with |\ifcase|. +% +% Furthermore, \xpackage{boolexpr} defines a \cmdref{switch} syntax which remains purely expandable. +% +% The \xpackage{boolexpr} package is designed to work with an \eTeX{} distribution of \LaTeX{}: +% it is based on the \eTeX{} |\numexpr| primitive and requires no other package. +% +% \end{abstract}\vskip-\baselineskip +% +% \cftbeforesecskip=5pt plus2pt minus4pt +% \bigskip\setcounter{tocdepth}{2} +% {\smaller\tableofcontents} +% +% \def\B#1{\texttt{[}\meta{#1}\texttt{]}} +% +% +% \section{Introduction -- Using \xpackage{boolexpr} : \cs{boolexpr} and \cs{switch}} +% +% \begin{declcs}{boolexpr}\,\M{boolean expression} +% \end{declcs}\cmdlabel{boolexpr} +% \cs{boolexpr} is a macro that takes for unique argument a series of \textit{atomic expressions} of the form:\par +% \hskip2em\begin{tabular}{r>{$}c<{$}l} +% numeric expr. & = & numeric expr. \\ +% numeric expr. & \nq & numeric expr. \\ +% numeric expr. & < & numeric expr \\ +% numeric expr. & <= & numeric expr \\ +% numeric expr. & > & numeric expr. \\ +% numeric expr. & >= & numeric expr. \\ +% \cs{if}& \meta{test}& 0\ \cs{else}\ 1\cs{fi}\\ +% \multicolumn{3}{c}{\cs{boolexpr}\{\meta{boolean expression}\}} +% \end{tabular}\par\noindent +% related by \CSbf{AND} or \CSbf{OR} (with the usual logical precedence). +% +% \textbf{\cs{boolexpr} expands to \textbf{0} if the whole expression is \textbf{true}} +% and to a non nul number if the whole expression is false. +% +% \cs{boolexpr} is \textbf{purely expandable}. +% +% \begin{framed} +% Therefore, testing may be used as follow:§ +% \begin{Verbatim}[gobble=1] +% \ifcase\boolexpr{ boolean expression } +% what to do if true +% \else +% what to do if false +% \fi +% \end{Verbatim} +% \end{framed} +% +% It is possible to use \texttt{switches} as boolean quantities into a \cs{boolexpr} expression +% with the syntax:§ +% \qquad|\ifswitch 0\else 1\fi| +% +% It is also possible to use |\ifdim|, |\ifnum| etc. (although it is not necessary because other forms +% of atomic expression can perform those tests more easily) and |\ifdefined|, |\ifcsname| etc. with +% the same syntax, f.ex.:§ +% \qquad|\ifcsname| \meta{cs-name} |\endcsname 0\else 1\fi| +% +% It means that if the conditional is \texttt{true} then the \textit{atomic expression} is \texttt{true} +% (expands to |0|), otherwise the \textit{atomic expression} is |false| (expands to non |0|). +% +% It is possible to test |dimensions| (or |glue| or |muglue|) by writing |\dimexpr| +% (or |\glueexpr| or |\muexpr|) in front of the \textit{atomic expression}; therefore, the following are valid atomic expressions:§ +% \hskip2em\begin{tabular}{rr>{$}c<{$}l} +% \cs{dimexpr} & dimen expr. & < & dimen expr \\ +% \cs{glueexpr} & glue expr. & \nq & glue expr. \\ +% \cs{muexpr} & mu expr. & = & mu expr. +% \end{tabular} +% +% It is allowed to group expressions inside the argument of |\boolexpr| by inserting another |\boolexpr| evaluation, f.ex.:§ +% \qquad|\boolexpr{ \boolexpr{ |$\alpha$ | \OR | $\beta$ |} \AND | $\gamma$ | }| +% +% The logical \textbf{NOT} operator can be achieved by writing for example:§ +% \qquad|\ifcase\boolexpr{|\meta{boolean expression}|} 1\else 0\fi| +% +% Finally, if the \meta{boolean expression} is missing:§ +%\qquad|\boolexpr{ }| expands to |1| (\ie |false|). +% +% \begin{declcs}{ifboolexpr}\,\M{boolean expression}\,\M{true part}\,\M{false part} +% \end{declcs} +% \cs{ifboolexpr} is the \LaTeX{} form of a |\boolexpr| test.\enlargethispage{\baselineskip} +% +% \cs{ifboolexpr} is purely expandable (provided \meta{true part} and \meta{false part} are so). +% +% +% \clearpage +% \subsection*{\CSbf{boolexpr} examples}\label{examples}\addcontentsline{toc}{subsection}{\cs{boolexpr} Examples} +% \vskip-\baselineskip The part of the expression that is evaluated \textcolor{blue}{is in blue} (the remainder is not evaluated). +% +% \begin{tabular}{m{9.5cm}>{\color{dg}\smex\tt}m{5.6cm}}\hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[45 > 80 \OR 5<>5 \AND] 5<4 } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \ifcase\boolexpr{ 45 > 80 \OR 5<>5 \AND 5<4 } +% boolexpr is true +% \else boolexpr is false +% \fi +% \else +% boolexpr is false +% \fi +% \\ \hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[45 < 80 \OR] 5 = 5 \AND 0<>0 } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \ifcase\boolexpr{ 45 < 80 \OR 5 = 5 \AND 0<>0 } +% boolexpr is true +% \else boolexpr is false +% \fi +% \else +% boolexpr is true +% \fi +% \\ \hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[\boolexpr{ 45 < 80 \OR !notevaluated[5 = 5] } \AND 0<>0] } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \ifnum\boolexpr{ \boolexpr{ 45 < 80 \OR 5 = 5 } \AND 0<>0 }=0 +% boolexpr is true +% \else boolexpr is false +% \fi +% \else +% boolexpr is false +% \fi +% \\ \hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[12>0 \AND (4+3)*5 > 20] } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \ifcase\boolexpr{ 12>0 \AND (4+3)*5 > 20} +% boolexpr is true +% \else boolexpr is false +% \fi +% \else +% boolexpr is true +% \fi +% \\ \hline +% \begin{VerbEx} +% \makeatletter +% \number\boolexpr{ !evaluated[\the\catcode`\@=11] } +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \makeatletter +% $\number\boolexpr{\the\catcode`\@=11}$ §{\small(catcode of character @ is 11)} +% \else +% $0$ §{\small(catcode of character @ is 11)} +% \fi +% \\ \hline +% \begin{VerbEx} +% \makeatother +% \number\boolexpr{ !evaluated[\the\catcode`\@=11] \AND \ifdefined\@undefined 0\else 1\fi } +% \end{VerbEx} +% &\omit \\[-2ex] & \omit +% \ifboolexprLoaded {\color{dg}\smex +% $\number\boolexpr{\catcode`\@=11 \AND \ifdefined\@undefined 0\else 1\fi}$} \\ &\omit {\color{dg}\tt\small(catcode of character @ is 12)} +% \else {\color{dg}\smex +% $1$ {\small(catcode of character @ is 12)} } +% \fi +% \\ \hline +% \begin{VerbEx} +% \makeatletter +% \number\boolexpr{ !evaluated[3<4 \AND \@ifundefined{iftest}{1}]{\iftest 0\else 1\fi} } +% \end{VerbEx} +% & \omit\\[-2ex] & \omit +% \ifboolexprLoaded {\color{dg}\smex +% \makeatletter +% \number\boolexpr{ 3<4 \AND \@ifundefined{iftest}{1}{\iftest 0\else 1\fi} }: |\iftest| not defined \hfil} +% \else {\color{bg} \smex 1: |\iftest| not defined\hfil} +% \fi +% \\ \hline +% \begin{VerbEx} +% \makeatletter \newif\iftest \testtrue +% \number\boolexpr{ !evaluated[3<4 \AND \@ifundefined{iftest}]{1}!evaluated[{\iftest 0\else 1\fi}] } +% \end{VerbEx} +% & \omit\\[-2ex] & \omit +% \ifboolexprLoaded {\color{dg}\smex +% \makeatletter\newif\iftest\testtrue +% \number\boolexpr{ 3<4 \AND \@ifundefined{iftest}{1}{\iftest 0\else 1\fi} }: |\iftest| is true \hfil} +% \else {\color{bg} \smex 0: |\iftest| is true \hfil} +% \fi +% \\ \hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[\dimexpr 12pt + 1in > 8mm * 2 \AND \iftest 0\else 1\fi] } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \newif\iftest \testtrue +% \ifcase\boolexpr{ \dimexpr 12pt + 1in > 8mm * 2 \AND \iftest 0\else 1\fi } +% boolexpr is true +% \else boolexpr is false +% \fi +% \else boolexpr is true +% \fi +% \\ \hline +% \begin{VerbEx} +% \ifcase\boolexpr{ !evaluated[0=0 \AND \ifcase\boolexpr{1=1 \AND 5<=5} 1\else 0\fi] } +% boolexpr is true +% \else boolexpr is false +% \fi +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \ifcase\boolexpr{ 0=0 \AND \ifcase\boolexpr{ 1=1 \AND 5<=5 } 1\else 0\fi } +% boolexpr is true +% \else boolexpr is false +% \fi +% \else boolexpr is false +% \fi \footnotesize +% § $\alpha$ |\AND NOT( |$\beta$| \AND |$\gamma$| )| +% § $\!\!\!\!\!\!=\alpha$| \AND NOT |$\beta$| \OR |$\alpha$| \AND NOT |$\gamma$ +% \\ \hline +% \end{tabular} +% +% \ifboolexprLoaded Results in green were evaluated by \xpackage{boolexpr.sty} at compilation time. +% \else Results in green were not evaluated at compilation time: \xpackage{boolexpr} was not found. +% \fi +% +% \clearpage +% \subsection*{The \CSbf{switch} syntax}\label{switchsyntax}\addcontentsline{toc}{subsection}{The \cs{switch} syntax} +% +% \begin{declcs}{switch}\\ +% \CSbf{case}\,\M{boolean expression}\quad... \\ +% \CSbf{case}\,\M{boolean expression}\quad... \\ +% \CSbf{otherwise}\quad... \\ +% \CS{endswitch} +% \end{declcs}\cmdlabel{switch} +% +% \xpackage{boolexpr} defines a syntax for \cs{switch} conditionals which remains purely expandable: +% \iffalse +% \begin{VerbEx} +% \switch +% !textbf[\case]{ !meta[bool expr] } ... +% !textbf[\case]{ !meta[beel expr] } ... +% !textbf[\case]{ !meta[bool expr] } ... +% !textbf[\otherwise] ... +% \endswitch +% \end{VerbEx} +% \fi +% +% \textbf{Each part of the switch is optional.} That means: +% \begin{center} +% \begin{tabular}{m{.4\textwidth}m{.4\textwidth}} +% \begin{VerbEx} +% \switch +% !textbf[\case]{ !meta[bool expr] } ... +% !textbf[\case]{ !meta[beel expr] } ... +% !textbf[\case]{ !meta[bool expr] } ... +% \endswitch +% \end{VerbEx} +% & +% \begin{VerbEx} +% \switch +% !textbf[\otherwise] ... +% \endswitch +% \end{VerbEx} +% \\ +% \begin{VerbEx} +% \switch +% \endswitch +% \end{VerbEx} +% & are allowed by \xpackage{boolexpr}. +% \end{tabular} +% \end{center} +% +% +% +% \subsection*{\CSbf{switch} examples}\label{switchexamples}\addcontentsline{toc}{subsection}{switch examples} +% +% The part of the expression that is evaluated \textcolor{blue}{is in blue} (the remainder is not evaluated). +% +% \begin{tabular}{m{9.5cm}>{\color{dg}\smex\tt}m{5.6cm}}\hline +% \begin{VerbEx} +% !evaluated[\switch] +% !evaluated[\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%] +% !evaluated[\case{3<10}$> 5$ and $< 10$%] +% \case{3>10}$\geq 10$% +% !evaluated[\endswitch] +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \switch +% \case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$% +% \case{3<10}$>5$ and $< 10$% +% \case{3>10}$\geq 10$% +% \endswitch +% \else +% $>5$ and $< 10$% +% \fi +% \\ \hline +% \begin{VerbEx} +% \edef\result{% +% !evaluated[\switch] +% !evaluated[\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%] +% !evaluated[\case{3<10}$> 5$ and $< 10$%] +% \case{3>10}$\geq 10$% +% !evaluated[\endswitch]} +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \edef\result{% +% \switch +% \case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$% +% \case{3<10}$>5$ and $< 10$% +% \case{3>10}$\geq 10$% +% \endswitch} +% \else +% \def\result{$>5$ and $< 10$} +% \fi +% result:\par\stripmeaning\result +% \\ \hline +% \begin{VerbEx} +% \def\result#1{\textbf{% +% !evaluated[\switch] +% !evaluated[\case{\pdfstrcmp{#1}{one}}one]% +% !evaluated[\case{\pdfstrcmp{#1}{two}}two]% +% !evaluated[\otherwise something else]% +% !evaluated[\endswitch]}} +% +% \protected@edef\result{\result{12}} +% \end{VerbEx} +% & +% \ifboolexprLoaded +% \def\result#1{\textbf{% +% \switch +% \case{\pdfstrcmp{#1}{one}}one% +% \case{\pdfstrcmp{#1}{two}}two% +% \otherwise something else% +% \endswitch}} +% \makeatletter\protected@edef\result{\result{12}}\makeatother +% \else +% \makeatletter\protected@edef\result{\textbf{something else}}\makeatother +% \fi +% result:\stripmeaning\result +% \\ \hline +% +% \end{tabular} +% +% \ifboolexprLoaded Results in green were evaluated by \xpackage{boolexpr.sty} at compilation time. +% \else Results in green were not evaluated at compilation time: \xpackage{boolexpr} was not found. +% \fi +% +% \StopEventually{ +% } +% +% \clearpage +% \section{Implementation} +% +% \subsection{The algorithm} \enlargethispage{2\baselineskip} +% +% The \emph{string} is the suite of \textit{atomic expressions} connected by |\AND| or |\OR|.§ +% The \emph{result} must be $0$ if the \emph{string} is true, and non zero if the \emph{string} is false.§ +% ``\emph{go to} |some macro|'' means: ``\emph{now expand} |some macro|''. +% +% \def\orbuffer{\textsc{or}-buffer} +% \begin{enumerate}[label=\fbox{\Alph*},itemsep=12pt] +% \item |\bex@OR| +% \begin{enumerate}[label=\arabic*)] +% \item Split the \emph{string} into two parts:\\ +% |#1| = before the first |\OR| (|#1| does not contain any |\OR|) \\ +% |#2| = after the first |\OR| +% \item If |#2| is blank: the \emph{string} contains no |\OR|\\ +% \hspace*{2em} then go to |\bex@AND| to test |\AND| relations in |#1| \\ +% Otherwise: test the |\AND| relations in |#1| and keep |#2| in a so called ``\orbuffer'' for further testing. +% \end{enumerate} +% \item |\bex@AND| \\ +% |#1| = \orbuffer\ for further testing if needed +% \begin{enumerate}[label=\arabic*)] +% \item Split the string ``before the first |\OR|'' (\ie the |#1| of A.1) into two parts:\\ +% |#2| = before the first |\AND| (|#2| is an \textit{atomic expression}) \\ +% |#3| = after the first |\AND| (|#3| does not contain any |\OR|) +% \item Then test |#2| (the \textit{atomic expression}): +% \begin{enumerate}[label=\textbullet\:] +% \item[TRUE:] \underline{If \Sharp3 is blank} then |#2| is either: +% \begin{enumerate}[label=\textbullet,topsep=0pt,partopsep=0pt,itemsep=0pt,parsep=0pt] +% \item an atomic expression alone +% \item the last atomic expression in \emph{string}, preceded by |\OR| +% \item an atomic expression preceded by |\OR| and followed by |\OR| +% \end{enumerate} +% In each of these 3 cases, the whole expression (\ie the \textit{string}) is true +% because |#2| is true (otherwise, we had known the result of the whole \textit{string} earlier, and +% were not into testing |#2|) \\ +% \underline{Now if \Sharp3 is not blank} then |#2| is followed by |\AND|:\\ +% \hspace*{2em} go to |\bex@ANDAND| to test the series of |\AND| +% \item[FALSE:] \underline{if the \orbuffer\ \Sharp1 is blank} then |#2| is either: +% \begin{enumerate}[label=\textbullet,topsep=0pt,partopsep=0pt,itemsep=0pt,parsep=0pt] +% \item an atomic expression alone +% \item an atomic expression followed a series of |\AND| (and no |\OR|) +% \item the last atomic expression of the \emph{string} +% \end{enumerate} +% In each or these 3 cases, the whole expression (\ie the \emph{string}) is false +% because |#2| is false (otherwise, the result would have been known earlier) \\ +% \underline{Now if the \orbuffer\ \Sharp1 is not blank,} then we have to do more tests to get the result:\\ +% \hspace*{2em} go to |\bex@OR| to split the \orbuffer\ (|#1| here) and continue testing... +% \end{enumerate} +% \end{enumerate} +% \item |\bex@ANDAND| \\ +% |#1| is the \orbuffer\ for further testing if needed +% \begin{enumerate}[label=\arabic*)] +% \item Split the string (\ie |#3| in B.2.\textsc{true}) into two parts:\\ +% |#2| : before the first |\AND| (|#2| is an \textit{atomic expression}) \\ +% |#3| : after the first |\AND| \\ \clearpage +% \item Test the \textit{atomic expression} |#2|: +% \begin{enumerate}[label=\textbullet\:] +% \item [TRUE:] \underline{If \Sharp3 is blank} then |#2| is the last atomic expression of a series of |\AND| +% (possibly followed by |\OR|). \\ +% Conclusion: the whole \emph{string} is true (otherwise, we would have concluded earlier +% that it was false and were not into testing |#2|... think about it) \\ +% \underline{Now if \Sharp3 is not blank} then |#2| is followed by |\AND| and we have to test further:\\ +% \hspace*{2em} go to |\bex@ANDAND| to test |#3|. +% +% \item [FALSE:] we do not have to test the following |\AND|: the |\AND|-connected series is false.\\ +% \underline{If the \orbuffer\ \Sharp1 is blank} then the whole \emph{string} is false. \\ +% \underline{Now if the \orbuffer\ \Sharp1 is not blank}: continue testing into this \orbuffer\ :\\ +% \hspace*{2em} go to |\bex@OR|. +% \end{enumerate} +% \end{enumerate} +% +% \end{enumerate} +% +% \subsection{Category codes considerations}\label{catcodes} +% +% At first glance, the author of this package wanted to test inequality with the operator $\char33\!=$. A problem arose +% because some languages make the character \char33\ active (f.ex. french). As far as babel changes the catcodes +% |\AtBeginDocument|, the category code of \char33\ is different in the preamble (12) than in the document (13). +% +% After all, it was possible to change the definitions after begin document but... if you try to make the = character +% active, you will (surprisingly) observe that a test like:§ +% \qquad|\ifnum 4=4 ok\fi|§ +% leads you to one of the following error messages:\parskip=0pt§ +% \begin{tabbing} +%\qquad\=|undefined control sequence =|\qquad\= if |=| is undefined \\ +%\>|missing = inserted for \ifnum|\> if |=| is defined. +% \end{tabbing}\restoreparskip +% +% The same apply for |<| or |>|. Therefore: such conditionals are possible for \TeX{} only if |=|\,,\,|<| and |>| +% have a category code of 12 (11 is forbidden too). +% +% Thus the choice of |<>| is far easier and more reliable than the c-like $\char33\!=$. +% +% \subsection{Identification} +% +% This package is intended to use with a \LaTeX{} distribution of \eTeX{}. +% +% \begin{macrocode} +%<*package> +\ProvidesPackage{boolexpr} + [2009/08/12 v2.1 Purely expandable boolean expressions and switch (eTeX)] +% \end{macrocode} +% \iffalse +%<package> +% \fi +% +% \subsection{Special catcode} +% The colon (:) will be used as a delimiter. We give it a category code of 4. +% \iffalse +%<package>% Make a colon (:) of catcode 4 (used as delimiter) +% \fi +% \begin{macrocode} +\let\bex@AtEnd\@empty +\def\TMP@EnsureCode#1#2{% + \edef\bex@AtEnd{% + \bex@AtEnd + \catcode#1 \the\catcode#1\relax + }% + \catcode#1 #2\relax +} +\TMP@EnsureCode{42}{4}% : +% \end{macrocode} +% \iffalse +%<package> +% \fi +% +% \subsection{Helper macros} +% +% While reading the \texttt{log} file it is preferable to read |\@firstoftwo|/|\@secondoftwo| +% when the algorithm is making a choice (|\ifblank|) and |\bex@truepart|/|bex@falsepart| +% when the algorithm has just determined the result of an atomic expression. +% \iffalse +%<package>% Five helper macros +% \fi +% \begin{macrocode} +\let\bex@truepart\@firstoftwo +\let\bex@falsepart\@secondoftwo +% \end{macrocode} +% \iffalse +%<package> +% \fi +% +% \begin{macrocode} +\def\bex@afterelse#1\else#2\fi{\fi#1} +% \end{macrocode} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\bex@ifblank} +% The following macro is purely expandable and its code is most probably due to D. Arseneau (\xpackage{url.sty}) +% \begin{macrocode} +\begingroup\catcode`\|=3 +\long\gdef\bex@ifblank#1{\bex@ifbl@nk#1||\@secondoftwo\@firstoftwo:} +\long\gdef\bex@ifbl@nk#1#2|#3#4#5:{#4} +\endgroup +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\bex@ifblankdef} +% It's just the same but expand once the control sequence given as an argument. +% \begin{macrocode} +\long\def\bex@ifblankdef#1{\expandafter\bex@ifblank\expandafter{#1}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \subsection{Atomic expression evaluation} +% +% The six possible numeric atomic expressions\, $x < y$\,, $x<=y$\,, $x > y$\,, $x>=y$\,, $x<>y$\, and $x=y$ are first +% transformed to their zero-form:§ +% |\numexpr| $x-y<0$\,,|\numexpr| $x-y>0$\,,|\numexpr| $x-y<>0$\,, |\numexpr| $x-y=0$\, etc. +% +% Before all, we need to know which relation is used in the atomic expression: +% +% \begin{macro}{\bex@rel} +% |\bex@rel| tests an \textit{atomic expression}: first determine its type +% (inferior to, superior to, equality, inequality, other |\boolexpr|) and then +% use the appropriate evaluation macro: +% \iffalse +%<package>% \bex@rel tests each atomic expression: choose which evaluation macro to use first +% \fi +% \begin{macrocode} +\def\bex@rel#1{% + \bex@test@eval#1: + {\bex@eval{#1}} + {\bex@test@neq#1<>: + {\bex@test@infeq#1<=: + {\bex@test@inf#1<: + {\bex@test@supeq#1>=: + {\bex@test@sup#1>: + {\bex@test@eq#1=: + {\@latex@error{Unknown relation found while scanning + \noexpand\boolexpr!}\@ehd} + {\bex@eq#1:}} + {\bex@sup#1:}} + {\bex@supeq#1:}} + {\bex@inf#1:}} + {\bex@infeq#1:}} + {\bex@neq#1:}}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{The test macros} +% They test each \textit{atomic expression} in order to determine its type: +% \iffalse +%<package>% Tests macros to determine the type of each atomic expression +% \fi +% \begin{macrocode} +\def\bex@test@neq#1<>#2:{\bex@ifblank{#2}} +\def\bex@test@eq#1=#2:{\bex@ifblank{#2}} +\def\bex@test@infeq#1<=#2:{\bex@ifblank{#2}} +\def\bex@test@inf#1<#2:{\bex@ifblank{#2}} +\def\bex@test@supeq#1>=#2:{\bex@ifblank{#2}} +\def\bex@test@sup#1>#2:{\bex@ifblank{#2}} +\def\bex@test@eval#1#2:{% + \ifcat\noexpand#1\relax% #1 is a control sequence + \bex@afterelse\bex@test@Eval{#1} + \else \expandafter\@secondoftwo + \fi} +\def\bex@test@Eval#1{\csname @% + \ifx#1\the second% + \else\ifx#1\numexpr second% + \else\ifx #1\number second% + \else\ifx #1\dimexpr second% + \else\ifx #1\glueexpr second% + \else\ifx #1\muexpr second% + \else first% + \fi\fi\fi\fi\fi\fi oftwo\endcsname} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{Evaluation macros} +% They evaluate each \textit{atomic expression} according to its type: +% \iffalse +%<package>% Evaluation macro that evaluates an atomic expression depending on its type: +% \fi +% \begin{macrocode} +\def\bex@true@or@false#1{\csname bex@% + \ifnum\numexpr#1 true\else false\fi part\endcsname} +\def\bex@false@or@true#1{\csname bex@% + \ifnum\numexpr#1 false\else true\fi part\endcsname} +% \end{macrocode} +% +% \iffalse +%<package> +% \fi +% \begin{macrocode} +\def\bex@eq#1=#2:{\bex@true@or@false{#1-(#2)=0}} +\def\bex@neq#1<>#2:{\bex@false@or@true{#1-(#2)=0}} +\def\bex@infeq#1<=#2:{\bex@false@or@true{#1-(#2)>0}} +\def\bex@inf#1<#2:{\bex@true@or@false{#1-(#2)<0}} +\def\bex@supeq#1>=#2:{\bex@false@or@true{#1-(#2)<0}} +\def\bex@sup#1>#2:{\bex@true@or@false{#1-(#2)>0}} +\def\bex@eval#1{\bex@true@or@false{#1=0}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \subsection{\texttt{\textbf{\textbackslash AND}} and \texttt{\textbf{\textbackslash OR}} management} +% +% \begin{macro}{\bex@OR} +% |\bex@OR| splits the string to evaluate into two parts: before the first |\OR| and after: +% \iffalse +%<package>% \bex@OR splits the string to evaluate into two parts: before the first \OR and after +% \fi +% \begin{macrocode} +\def\bex@OR#1\OR#2:{% + \bex@ifblank{#2} + {\bex@AND{}#1\AND:} + {\expandafter\bex@AND\expandafter{\bex@removeOR#2:}#1\AND:}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{bex@removeOR} +% Just remove the extra |\OR:| inserted into the argument of |\bex@OR|: +% \iffalse +%<package>% \remove@OR removes the extra \OR: inserted into the argument of \bex@OR +% \fi +% \begin{macrocode} +\def\bex@removeOR#1\OR:{#1} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\bex@AND} +% |\bex@AND| splits the string to evaluate into two parts: before the first |\AND| and after: +% \iffalse +%<package>% \bex@AND splits the string to evaluate into two parts: before the first \AND and after: +% \fi +% \begin{macrocode} +\def\bex@AND#1#2\AND#3:{% + \bex@rel{#2} + {\bex@ifblank{#3} + {0} + {\bex@ANDAND{#1}#3:}} + {\bex@ifblank{#1}{+1}{\bex@OR#1 \OR:}}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\bex@ANDAND} +% |\bex@ANDAND| evaluate successive \textit{atomic expressions} related by |\AND| until +% false is found or until the end if every expression is true: +% \iffalse +%<package>% \bex@ANDAND evaluate successive atomic expressions related by \AND: +% \fi +% \begin{macrocode} +\def\bex@ANDAND#1#2\AND#3:{% + \bex@rel{#2} + {\bex@ifblank{#3}{+0}{\bex@ANDAND{#1}#3:}} + {\bex@ifblank{#1}{+1}{\bex@OR#1 \OR:}}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\boolexpr} +% |\boolexpr| is the entry point for evaluating boolean expressions: +% \iffalse +%<package>% \boolexpr: the entry point for evaluating boolean expressions +% \fi +% \begin{macrocode} +\newcommand\boolexpr[1]{\bex@ifblank{#1}{1}{\numexpr\bex@OR#1 \OR:+0}} +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\@first@or@second} +% +% \begin{macrocode} +\newcommand\bex@first@or@second[1]{% + \csname bex@\ifnum\boolexpr{#1}=0 true\else false\fi part\endcsname} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifboolexpr} +% |\ifboolexpr| is the \LaTeX{} form of |\boolexpr| tests: +% \iffalse +%<package>% \ifboolexpr: the LaTeX form of \boolexpr tests +% \fi +% \begin{macrocode} +\newcommand\ifboolexpr{} +\let\ifboolexpr\bex@first@or@second +% \end{macrocode} +% \end{macro} +% \iffalse +%<package> +% \fi +% +% \begin{macro}{\switch} +% \cs{switch} is not long to implement... see: +% \begin{macrocode} +\def\switch#1\endswitch{\bex@ifblank{#1}{}% + {\bex@switch@otherwise#1\otherwise\endswitch}} + +\def\bex@switch@otherwise#1\otherwise#2\endswitch{% + \bex@switch@case#1\case\endswitch + {\bex@ifblank{#2}{}{\bex@otherwise#2\endswitch}} + \endswitch} + +\def\bex@switch@case#1\case#2\endswitch{% + \bex@ifblank{#1} + {\bex@ifblank{#2}{\@firstoftwo}{\bex@switch@case#2\endswitch}} + {\case#1\endcase + {\bex@ifblank{#2}{\@firstoftwo}{\bex@switch@case#2\endswitch}}% + }} + +\def\case#1#2\endcase{% + \ifboolexpr{#1}{\bex@after@endswitch{#2}}} + +\def\bex@after@endswitch#1#2\endswitch{#1} +\def\bex@otherwise#1\otherwise#2\endswitch{#1} +% \end{macrocode} +% \end{macro} +% +% Restore original catcode: +% \iffalse +%<package>% Restore original catcode +% \fi +% \begin{macrocode} +\bex@AtEnd +%</package> +% \end{macrocode} +% +% \subsection{Future developments : to do} +% +% \xpackage{boolexpr} should work either with \eTeX{} or \eTeX-\LaTeX{}... +% +% May be build a ``real'' |\NOT| operator. +% +% \begin{History} +% +% \begin{Version}{2009/08/12 v2.1} +% \item +% Added the \cs{switch} syntax +% \item +% Small bug (|\numexpr| forgotten in the ``list of exceptions'' (\cs{bex@test@Eval}) +% \item +% Redesigned tests for better compilation +% \end{Version} +% +% \begin{Version}{2009/07/22 v1.0} +% \item +% First version. +% \end{Version} +% +% \end{History} +% +% \PrintIndex +% +% \label{LastPage} +% \Finale
\ No newline at end of file |