% cnv-word.tex --- an example of the usage of cnv.tex: word to word converting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % April 2005 Petr Olsak \input cnv % This file is a complex example of the usage of cnv.tex macro. % The macros presented here give the possibility to declare word to word % conversion a of given string. Each occurence of declared words will be % converted to the declared outputs. % Double percent: "%%" is a prefix of technical comments. % Please, read the "user" comments (prefixed by one "%") first. %% \wtest is an internal macro which tests if the given {pattern} matches %% the begin of the input stream. If it is true then other \wtests %% are ignored and a given {output} is stored to \cnvout. The input %% stream is reduced by the pattern. Else input stream is restored %% and the next \wtest is run. We suppose the following parameters: %% \wtest{pattern}{output}\wtest{pattern}{output}...\endwtest{letter}input stream\END %% The main idea of \wtest is to declare the macro \trywtest by: %% \def\trywtest #1pattern#2\end and run it by: %% \trywtest input-stream\END pattern\end. If #1 is empty then pattern %% matches. \gdef\wtest #1#2#3\endwtest#4#5\END {\def\wout{#2}\def\otherwtests{#3}% \def\inputstream{#5}% \def\trywtest ##1#1##2\end {\def\tmp{##1}% \def\tmpa{#1}\ifx\tmpa\empty \def\tmp{}\fi % empty pattern \ifx\tmp\empty % found! \def\next{\cnvstoree{\expandafter \cnvout \wout}% \expandafter \cnvcontinue \inputstream\END}% \else % not found! \def\next{\expandafter\otherwtests\expandafter\endwtest \expandafter{\expandafter#4\expandafter}% \inputstream \END}% \fi \next} \def\cnvcontinue #1{\cnvnext}% \expandafter\trywtest \inputstream \END#1\end } %% \stringdef {} {} %% adds to the internal cnv macro \E:: the next part of %% the type "\wtest{pattern}{output}" The \E::
looks like: %% \cnvexec \wtest{pattern1}{output1}\wtest{pattern2}{output2}...\endwtest{} %% The new "\wtest{pattern}{output}" is added at the end of \wtests %% string before \endwtest{letter}. \def\wstringdef #1#2 #3{% \expandafter\ifx \csname E:\string#1:\cnvtable\endcsname \relax \def\tmp{}% \else \expandafter\expandafter\expandafter \wstoretmp \csname E:\string#1:\cnvtable\endcsname \fi \expandafter \def \csname E:\string#1:\cnvtable \expandafter\endcsname \expandafter {\expandafter \cnvexec \tmp \wtest{#2}{#3}\endwtest{#1}} } \def\wstoretmp \cnvexec #1\endwtest#2{\def\tmp{#1}} \def\stringdef #1#2{\wstringdef #1 {#2}} %% If all wtests fail then \endwtest{} is processed. It adds %% the itself to the \cnvout. \def\endwtest#1{\def\tmp{#1}% \ifx\tmp\inSPACE \cnvstoree{\expandafter \cnvout \space}% \else \cnvstore{\cnvout #1} \fi\cnvnext} \def\inSPACE{\SPACE} %% The \wconvert{} does the main conversion. It runs %% \cnvin twice (with different tables). First conversion converts the %% spaces to \SPACE tokens and braces to \BGROUP and \EGROUP tokens. The %% reason is that now we can read \SPACE and converted braces to #1 parameter %% without changes. This is needed in \wtest macro. No matter that %% \SPACE is undefined. We never process it by normal \TeX{} expansion. %% The second conversion (with table 2) does the real word to word conversion and %% returns the \SPACE \BGROUP and \EGROUP to the desired output. \def\wconvert #1{% \def\cnvtable{1}\cnvin{#1} \def\cnvtable{2}% \expandafter \cnvin \expandafter {\cnvout \END}} %% Table 1: only converts spaces and braces \def\cnvtable{1} \findef { } {\SPACE} %% Table 2: the \END mark is ignored and \SPACE is converted back to space \def\cnvtable{2} \findef \END {} \findef \SPACE { } %% We have to keep the \BGROUP and \EGROUP unchanged. Unfortunately, %% the declaration: %% %% \let\findefmethod=\edef %% \findef \BGROUP {{\iffalse}\fi} %% \findef \EGROUP {\iffalse{\fi}} %% %% does not work because the cnv macro fails: the \output macro needs %% to be balanced text everytime during conversion process. It means %% that there is impossible to return the input tokens of catcode 1 %% and 2 to their original maening. We can return them to their original %% meaning only if the \cnvout can be normally expanded. In such a case, %% we can write after \wconvert is done: %% %% \bgroup \def\BGROUP {{\iffalse}\fi} \def\EGROUP {\iffalse{\fi}} %% \xdef \cnvout{\cnvout} \egroup % Users can declare the "word to word" conversion here. Each string declared at % the left hand side will be converted to the output at the right hand side. % If there are more left side strings with the same initial letter then % the table is read in this order during the conversion. It means % that the last declaration in the following example is irrelevant: % if the string begins by "th" then the result of conversion is "TH" % and the last declaration of "the" is ignored. \stringdef {input} {output} \stringdef {this} {THIS} \stringdef {test} {TEST} \stringdef {th} {TH} \stringdef {the} {THE} % Now, we can try this declaration. \wconvert {this is a test of the motherboard input} \message {"\cnvout"} % The result is: "THIS is a TEST of THe moTHerboard output". % Users have to use the \SPACE or \BGROUP or \EGROUP instead of real tokens % of catcode 10, 1 and 2 at the left hand side of the declaration: \stringdef {\SPACE the} { !THE!} \wconvert {this is a test of the motherboard input} \message {output: "\meaning\cnvout"} \end