[comp.text.tex] A very "special" problem

krab@iesd.auc.dk (Kresten Krab Thorup) (01/23/91)

Hello folks.. here's one for your brain!

We've made a `parser' which parses an normal math expression to
reversed polish notation :

For example {\math 2+4*x} gives: 2 4 x mul add

The problem now is: We'd like to be able to put the parsed expression
into a \special, so this coudt be used for example to draw a arbitrary
graph based on the expression (using a PostScript printer) like this:

\drawfunc[Xmin,Xmax]{expression} 

to produce a nice graph of the expression in the given interval
[Xmin,Xmax] ..... Think of:

         \drawfunc[-2,2]{x^2-1}

                   |       
            |      |      |
             \     + 1   /
              \    |    /  2   3
        -------+---+---+---+---+----
                \  |  /
                 `-+-' -1
                   |
                   + -2
                   |
 
             Nice... right?

Now take a look at this piece of code which is executable with TeX..
It includes some examples so you can se that it works...

%--------------------cut here-----------------------
{
\catcode`@=11
\catcode`+ =\active%
\catcode`- =\active%
\catcode`* =\active%
\catcode`/ =\active%
\catcode`^ =\active%
\catcode`( =\active \catcode`) =\active %
\catcode`[ =\active \catcode`] =\active %
\gdef\math{\relax%
%
\def\@add{ add}%
\def\@sub{ sub}%
\def\@mul{ mul}%
\def\@div{ div}%
\def\@exp{ exp\egroup}%
\def\@neg{ neg\egroup}%
%
\def\@sin{ sin\egroup}%
\def\@cos{ cos\egroup}%
\def\@tan{ dup sin exch cos div\egroup}%
\def\@abs{ abs\egroup}%
\def\@sqrt{ sqrt\egroup}%
\def\@ln{ ln\egroup}%
\def\@log{ log\egroup}%
\def\@round{ round\egroup}%
\def\@trunc{ truncate\egroup}%
%
\catcode`+\active%
\catcode`-\active%
\catcode`*\active%
\catcode`/\active%
\catcode`^\active%
\def-{\egroup\egroup\egroup\space\bgroup\aftergroup\@sub\bgroup\bgroup}%
%  - subtract
\def+{\egroup\egroup\egroup\space\bgroup\aftergroup\@add\bgroup\bgroup}%  + add
\def*{\egroup\egroup\space\bgroup\aftergroup\@mul\bgroup}%          * multiply
\def/{\egroup\egroup\space\bgroup\aftergroup\@div\bgroup}%          / divide
\def^{\space\bgroup\aftergroup\@exp}%        ^ raise to power of
\def~{\bgroup\aftergroup\@neg}%              ~ unary minus (negation)
%
\def\sin{\bgroup\aftergroup\@sin}%        \sin(angle) sine
\def\cos{\bgroup\aftergroup\@cos}%        \cos(angle) cosine
\def\tan{\bgroup\aftergroup\@tan}%        \tan(angle) tangens
\def\abs{\bgroup\aftergroup\@abs}%        \abs(real) = max(real,-real)
\def\round{\bgroup\aftergroup\@round}%    \round(real) = trunc(real+0.5)
\def\trunc{\bgroup\aftergroup\@truncate}% \trunc(real) = integer
					    %                part of `real'
\def\sqrt{\bgroup\aftergroup\@sqrt}%      \sqrt(real) = square root
				       %                        of `real'
\def\ln{\bgroup\aftergroup\@ln}%          \ln(real) = natural log 
\def\log{\bgroup\aftergroup\@log}%        \log(real) = 10-log
%
\catcode`(\active \catcode`)\active
\catcode`[\active \catcode`]\active
\def({\bgroup\bgroup\bgroup}
\def){\egroup\egroup\egroup}
\let[(\let])%
}}
%
% some examples...
%
\begingroup\math
 [\sin((a+1)/2)] % gives: a 1 add 2 div sin

 [2+3*\sin\cos4] % gives: 2 3 4 cos sin mul add

 [\cos(a+1/2)]   % gives: a 1 2 div add cos

 [\tan(4)]       % gives: 4 dup sin exch cos div

 [\ln(37*x^4)]   % gives: 37 x 4 exp mul ln  = ln(37*(x^4))

 [\ln(37^x*4)]   % gives: 37 x exp 4 mul ln  = ln((37^x)*4)

 [x-2+3]         % gives: x 2 sub 3 add
 
 [x-(2+3)]       % gives: x 2 3 add sub

 [a/b*c]         % gives: a b div c mul

 [a/(b*c)]       % gives: a b c mul div

 [2+3^b*4]       % gives: 2 3 b exp 4 mul add

 [2^3^4]         % gives: 2 3 4 exp exp

 [(2^3)^4]       % gives: 2 3 exp 4 exp

 [\sin3^4]       % gives: 3 4 exp sin

 [(\sin3)^4]     % gives: 3 sin 4 exp

 [3+~\sin~5]     % gives: 3 5 neg sin neg add
\endgroup
\end
%----------------------end--------------------------

You see... it includes a lot of grouping trickery, and our problem
seems to be, that all that stuff is first processed by TeX when it
reaches "TeX's stomach" --- and only REAL text goes there, not the
contents of a special...

We've already tryed a lot of things - like for example this:

-------------------------------------------------------------
\def\drawfunc[#1,#2]{\Xmin =#1 \Xmax=#2 
    \begingroup\math\getfunc}

\def\getfunc#1{\xdef\func{{{{#1}}}}\endgroup\drawit}

\def\drawit{\special{ ... /func \func def ...}
-------------------------------------------------------------

but... neither the argument of `\getfunc' nor `\func' are ever expanded
to more than a lot of bgroups and egroups....

We'd apreciate your help very much

/Kresten and Frank

NB: You're welcome to email if you have further questions

--

        (  .                     
      (. )  )                    
       ) ( (                     
    .________.                   <krab@iesd.auc.dk>
    | |    __|                   
    |       ))                   Kresten Krab Thorup
    | |    //|                   Institute for electronic systems
`---`-`------'---'               Dept. of mathemathics and computer science
Coffee coffee ... (C) 1991       Aalborg University - Denmark, EC