home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / nicol / sti_expr / sti_expr.pas
Encoding:
Pascal/Delphi Source File  |  1979-12-31  |  9.0 KB  |  315 lines

  1. unit STI_EXPR;                              { expression parser             }
  2.  
  3. interface
  4.  
  5. Var
  6.   STI_CALCErrorMsg  : string;               { returned error message        }
  7.   BuffPos           : word;                 { position in buffer            }
  8.  
  9.  
  10. function STI_Expression(Var Inbuffer; Size : word) : real;
  11.  
  12. {---------------------------------------------------------------------------}
  13.  
  14. implementation
  15.  
  16. Const
  17.   BUFFSIZE         = 255;                   { size of the buffer            }
  18.  
  19.   NUMBER           = 1;                     { a number TOKEN                }
  20.   LEFTBRACKET      = 2;                     { (                             }
  21.   RIGHTBRACKET     = 3;                     { )                             }
  22.  
  23.   PLUS             = 4;                     { +                             }
  24.   MINUS            = 5;                     { -                             }
  25.   TIMES            = 6;                     { *                             }
  26.   DIVIDE           = 8;                     { /                             }
  27.   SHIFTRIGHT       = 9;                     { SHR                           }
  28.   SHIFTLEFT        = 10;                    { SHL                           }
  29.   MODULO           = 11;                    { MOD                           }
  30.   ANDOP            = 13;                    { AND                           }
  31.   OROP             = 14;                    { OR                            }
  32.  
  33.   ARCTANGENT       = 15;                    { ARCTAN                        }
  34.   COSINE           = 16;                    { COS                           }
  35.   EXPONENTIAL      = 17;                    { EXP                           }
  36.   SINE             = 20;                    { SIN                           }
  37.   SQUARE           = 21;                    { SQR                           }
  38.   SQUAREROOT       = 22;                    { SQRT                          }
  39.  
  40.  
  41. Type
  42.   BigStr = Packed Array[0..255] of char;    { a buffer : just like a string }
  43.  
  44. Var
  45.   Buffer    : ^BigStr;
  46.   Token     : string;
  47.   TokenType : byte;
  48.   MaxLength : word;
  49.  
  50. {---------------------------------------------------------------------------}
  51.  
  52. procedure KeySearch(Key : string);          { SLOWLY find a keyword         }
  53.                                             { assign TOKEN to TokenType     }
  54. begin
  55.   if Key = 'SHR'     then TokenType := SHIFTRIGHT     else
  56.   if Key = 'SHL'     then TokenType := SHIFTLEFT      else
  57.   if Key = 'MOD'     then TokenType := MODULO         else
  58.   if Key = 'AND'     then TokenType := ANDOP          else
  59.   if Key = 'OR'      then TokenType := OROP           else
  60.  
  61.   if Key = 'ARCTAN'  then TokenType := ARCTANGENT     else
  62.   if Key = 'COS'     then TokenType := COSINE         else
  63.   if Key = 'EXP'     then TokenType := EXPONENTIAL    else
  64.   if Key = 'SIN'     then TokenType := SINE           else
  65.   if Key = 'SQR'     then TokenType := SQUARE         else
  66.   if Key = 'SQRT'    then TokenType := SQUAREROOT     else
  67.     begin
  68.       STI_CALCErrorMsg := 'UnKnown Identifier';
  69.     end;
  70.  
  71. end;
  72.  
  73. {---------------------------------------------------------------------------}
  74.  
  75. procedure GetToken;                         { dig a token out of the buffer }
  76.  
  77. Var
  78.   Dummy : string;
  79.  
  80. begin
  81.   Dummy := '';
  82.   Token := '';
  83.   TokenType := 0;
  84.   while (Buffer^[BuffPos] < #33) and (BuffPos < MaxLength) do
  85.     Inc(BuffPos);
  86.   case Buffer^[BuffPos] of
  87.     '0'..'9' : begin
  88.                  while (Buffer^[BuffPos] in ['0'..'9','.']) and (BuffPos <= MaxLength) do
  89.                    begin
  90.                      Dummy := Dummy + Buffer^[BuffPos];
  91.                      Inc(BuffPos);
  92.                    end;
  93.                  TokenType := NUMBER;
  94.                end;
  95.     '(',')'  : begin
  96.                  Dummy := Buffer^[BuffPos];
  97.                  case Dummy[1] of
  98.                    '('  : TokenType := LEFTBRACKET;
  99.                    ')'  : TokenType := RIGHTBRACKET;
  100.                  end;
  101.                  Inc(BuffPos);
  102.                end;
  103.     '^','%',
  104.     '+','-',
  105.     '*','/'  : begin
  106.                  Dummy := Buffer^[BuffPos];
  107.                  case Dummy[1] of
  108.                    '+'  : TokenType := PLUS;
  109.                    '-'  : TokenType := MINUS;
  110.                    '*'  : TokenType := TIMES;
  111.                    '/'  : TokenType := DIVIDE;
  112.                    '^'  : TokenType := EXPONENTIAL;
  113.                    '%'  : TokenType := MODULO;
  114.                  end;
  115.                  Inc(BuffPos);
  116.                end;
  117.     'A'..'Z',
  118.     'a'..'z' : begin
  119.                  while (UpCase(Buffer^[BuffPos]) in ['A'..'Z']) and (BuffPos < MaxLength) do
  120.                    begin
  121.                      Dummy := Dummy + Buffer^[BuffPos];
  122.                      Inc(BuffPos);
  123.                    end;
  124.                  KeySearch(Dummy);
  125.                end;
  126.   end;{case}
  127.   Token    := Dummy;
  128. end;
  129.  
  130. {---------------------------------------------------------------------------}
  131.  
  132. procedure Unary(Op : byte; Var Result : real); { unary operators            }
  133.  
  134. begin
  135.   case Op of
  136.     PLUS        : Result := abs(Result);
  137.     MINUS       : Result := -Result;
  138.     ARCTANGENT  : Result := ArcTan(Result);
  139.     COSINE      : Result := Cos(Result);
  140.     SINE        : Result := Sin(Result);
  141.     SQUARE      : Result := Sqr(Result);
  142.     SQUAREROOT  : Result := Sqrt(Result);
  143.   end;
  144. end;
  145.  
  146. {---------------------------------------------------------------------------}
  147.  
  148. procedure DoArith(Op : byte; Var A,B : real); { do the arithmetic           }
  149.  
  150. begin
  151.   case Op of
  152.     PLUS           : A := A +         B;
  153.     MINUS          : A := A -         B;
  154.     TIMES          : A := A *         B;
  155.     DIVIDE         : A := A /         B;
  156.     MODULO         : A := Trunc(A) mod Trunc(B);
  157.     SHIFTRIGHT     : A := Trunc(A) shr Trunc(B);
  158.     SHIFTLEFT      : A := Trunc(A) shl Trunc(B);
  159.     ANDOP          : A := Trunc(A) and Trunc(B);
  160.     OROP           : A := Trunc(A) or  Trunc(B);
  161.     EXPONENTIAL    : begin
  162.                      end;
  163.   end;
  164. end;
  165.  
  166. {---------------------------------------------------------------------------}
  167.  
  168. procedure Primitive(Var Result : Real);     { simple value                  }
  169.  
  170. Var
  171.   Test : integer;
  172.  
  173. begin
  174.   if TokenType <> NUMBER then
  175.     STI_CALCErrorMsg := 'Number Expected'
  176.   else
  177.     begin
  178.       Val(Token,Result,Test);
  179.       if Test <> 0 then
  180.         STI_CALCErrorMsg := 'Bad numeric format';
  181.       GetToken;
  182.     end;
  183. end;
  184.  
  185. {---------------------------------------------------------------------------}
  186.  
  187. procedure Level2(Var Result : Real); forward;
  188.  
  189. procedure Level6(Var Result : Real);
  190.  
  191. Var
  192.   Dummy : real;
  193.  
  194. begin
  195.   if TokenType = LEFTBRACKET then
  196.     begin
  197.       GetToken;
  198.       Level2(Result);
  199.       if TokenType <> RIGHTBRACKET then
  200.         STI_CALCErrorMsg := ') Expected';
  201.       GetToken;
  202.     end
  203.   else
  204.     begin
  205.       Primitive(Result);
  206.     end;
  207. end;
  208.  
  209. {---------------------------------------------------------------------------}
  210.  
  211. procedure Level5(Var Result : Real);
  212.  
  213. Var
  214.   Dummy : real;
  215.   Oper  : byte;
  216.  
  217. begin
  218.   Oper := 0;
  219.   if (TokenType = PLUS) or (TokenType = MINUS) or
  220.      ((TokenType >= ARCTANGENT) and (TokenType <= SQUAREROOT)) then
  221.     begin
  222.       Oper := TokenType;
  223.       GetToken;
  224.     end;
  225.   Level6(Result);
  226.   if Oper <> 0 then
  227.     begin
  228.       Unary(Oper,Result);
  229.     end;
  230. end;
  231.  
  232. {---------------------------------------------------------------------------}
  233.  
  234. procedure Level4(Var Result : Real);
  235.  
  236. Var
  237.   Dummy : real;
  238.   Oper  : byte;
  239.  
  240. begin
  241.   Level5(Result);
  242.   if TokenType = EXPONENTIAL then
  243.     begin
  244.       Oper := TokenType;
  245.       GetToken;
  246.       Level4(Dummy);
  247.       DoArith(Oper,Result,Dummy);
  248.     end;
  249. end;
  250.  
  251. {---------------------------------------------------------------------------}
  252.  
  253. procedure Level3(Var Result : Real);
  254.  
  255. Var
  256.   Dummy : real;
  257.   Oper  : byte;
  258.  
  259. begin
  260.   Level4(Result);
  261.   while (TokenType = TIMES) or (TokenType = DIVIDE) or
  262.         ((TokenType >= SHIFTRIGHT) and (TokenType <= OROP)) do
  263.     begin
  264.       Oper := TokenType;
  265.       GetToken;
  266.       Level4(Dummy);
  267.       DoArith(Oper,Result,Dummy);
  268.     end;
  269. end;
  270.  
  271. {---------------------------------------------------------------------------}
  272.  
  273. procedure Level2(Var Result : Real);
  274.  
  275. Var
  276.   Dummy : real;
  277.   Oper  : byte;
  278.  
  279. begin
  280.   Level3(Result);
  281.   while (TokenType = PLUS) or (TokenType = MINUS) do
  282.     begin
  283.       Oper := TokenType;
  284.       GetToken;
  285.       Level3(Dummy);
  286.       DoArith(Oper,Result,Dummy);
  287.     end;
  288. end;
  289.  
  290. {---------------------------------------------------------------------------}
  291.  
  292. function STI_Expression(Var Inbuffer; Size : word) : real;
  293.  
  294. Var
  295.   Dummy  : BigStr absolute InBuffer;
  296.   Result : Real;
  297.  
  298. begin
  299.   Buffer    := addr(Dummy[1]);
  300.   BuffPos   := 0;
  301.   MaxLength := Size;
  302.   STI_CALCErrorMsg  := '';
  303.   GetToken;
  304.   if Token = '' then
  305.     begin
  306.       STI_CALCErrorMsg := 'No Expression To Parse';
  307.     end;
  308.   Level2(Result);                           { recursively descend the parse }
  309.   STI_Expression := Result;
  310. end;
  311.  
  312. {---------------------------------------------------------------------------}
  313.  
  314. begin
  315. end.