home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / PASCAL / PARSE10.ZIP / PARSER.PAS < prev   
Pascal/Delphi Source File  |  1991-03-23  |  19KB  |  573 lines

  1. (******************************************************************************
  2. *                                   parser                                    *
  3. * Ron Loewy, 1991. A mathematical recursive decent parser +-/*^ and functions *
  4. ******************************************************************************)
  5. unit parser;
  6.  
  7. interface
  8.  
  9. type  TokenType   = (Delimiter,Non,variable,Digit,endExpr,Error,Func);
  10.       TokenPtr    = ^TokenRec;
  11.       TokenRec    = Record
  12.                           Next : TokenPtr;
  13.                           Start,Close : Byte;
  14.                     end;
  15.  
  16. var Macro : string;
  17.     V     : array ['0'..'9'] of Real; {macro program variables}
  18.     ErrAt : Byte;
  19.  
  20. function GetExpr(var Valid:Boolean) : Real;
  21.  
  22. implementation 
  23.  
  24. var
  25.    c  : char;
  26.    i  : byte;
  27.  
  28. (******************************************************************************
  29. *                                    DoErr                                    *
  30. ******************************************************************************)
  31. procedure DoErr(var n : TokenType);
  32.  
  33. begin
  34.      n := Error;
  35.      ErrAt := i; {globl err pos}
  36. end; {doErr}
  37.  
  38. (******************************************************************************
  39. *                                  ReadWord                                   *
  40. ******************************************************************************)
  41. function ReadWord : string;
  42. var 
  43.    WordIn : string;
  44. begin
  45.      WordIn := '';
  46.      While (not(Macro [i] in
  47.                       [' ','\',';','*','/','^','+','=','-','%','(',')']))
  48.             and (i <= Length(Macro)) do
  49.      begin
  50.           WordIn := WordIn + UpCase(Macro[i]);
  51.           Inc(i);
  52.      end;
  53.      ReadWord := WordIn;
  54. end; {readWord}
  55.  
  56. (******************************************************************************
  57. *                                 ReadNumber                                  *
  58. ******************************************************************************)
  59. function ReadNumber : Real;
  60. var 
  61.    Number : Real;
  62.    Code   : Integer;
  63.    StrNum : string;
  64. begin
  65.      StrNum := ReadWord;
  66.      if StrNum[1] = '.' then StrNum := '0' + StrNum;
  67.      Val(StrNum,Number,Code);
  68.      if Code <> 0 then Number := 0;
  69.      ReadNumber := Number;
  70. end; {readNumber}
  71.  
  72. procedure Level1(var Result : Real; var n : TokenType) ; forward;
  73.  
  74. (******************************************************************************
  75. *                                 SkipBlanks                                  *
  76. ******************************************************************************)
  77. procedure SkipBlanks;
  78. begin
  79.      While Macro [i] = ' ' do Inc(i);
  80. end; {skipBlanks}
  81.  
  82. (******************************************************************************
  83. *                                  GetToken                                   *
  84. ******************************************************************************)
  85. function GetToken : TokenType;
  86. var 
  87.    Temp : string;
  88.    n    : TokenType;
  89. begin
  90.      SkipBlanks;
  91.      if Macro [i] in ['+','-','/','*','=','^','%','(',')'] then
  92.                          n := Delimiter
  93.                     else if Macro [i] in ['v','V'] then begin
  94.                          n := variable;
  95.                     end else if Macro [i] in ['0'..'9','.'] then
  96.                         n := Digit
  97.                     else if Macro [i] = ';' then
  98.                          n := endExpr
  99.                     else if Macro[i] in ['a'..'z','A'..'Z']
  100.                          then n := Func
  101.                     else n := Non;
  102.      GetToken := n;
  103. end; {getToken}
  104.  
  105. (******************************************************************************
  106. *                                  MatchFunc                                  *
  107. ******************************************************************************)
  108. function MatchFunc(Match : string; var Result : Real; var n : TokenType) :
  109.                                                                Boolean;
  110. var 
  111.    j : Byte;
  112. begin
  113.      j := i; {restore i if no match}
  114.      if (ReadWord = Match) then begin
  115.         MatchFunc := True;
  116.         skipblanks;
  117.         if (Macro [i] <> '(') then DoErr(n)
  118.            else begin
  119.                      Inc(i);
  120.                      n := GetToken;
  121.                      Level1(Result,n);
  122.                      SkipBlanks; {Reach closing parenthasis}
  123.                      if Macro[i] <> ')' then DoErr(n);
  124.                      Inc(i);
  125.                      SkipBlanks;
  126.            end;
  127.      end else begin
  128.          MatchFunc := False;
  129.          i := j; {no Func Match, restore}
  130.      end;
  131. end; {matchFunc}
  132.  
  133. (******************************************************************************
  134. *                                 MatchToken                                  *
  135. ******************************************************************************)
  136. function MatchToken(Match : string) : boolean;
  137. var 
  138.    j : byte;
  139. begin
  140.     j := i;
  141.     if (readWord = match) then MatchToken := True
  142.         else begin
  143.             MatchToken := False;
  144.             i := j;
  145.         end; {else}
  146. end; {matchToken}
  147.  
  148. (******************************************************************************
  149. *                                    doPI                                     *
  150. ******************************************************************************)
  151. function doPI(var r:real) : boolean;
  152. begin
  153.     doPI := matchToken('PI');
  154.     r := pi;
  155. end; {doPI}
  156.  
  157. (******************************************************************************
  158. *                                     doE                                     *
  159. ******************************************************************************)
  160. function doE(var r:real) : boolean;
  161. begin
  162.     doE := matchToken('E');
  163.     r := exp(1.0);
  164. end; {doE}
  165.  
  166. (******************************************************************************
  167. *                                    DoSin                                    *
  168. ******************************************************************************)
  169. function DoSin(var Result : Real; var n : TokenType) : Boolean;
  170. var 
  171.    r : Boolean;
  172. begin
  173.      r := MatchFunc('SIN',Result,n);
  174.      Result := sin(Result);
  175.      DoSin := r;
  176. end; {doSin}
  177.  
  178. (******************************************************************************
  179. *                                    DoExp                                    *
  180. ******************************************************************************)
  181. function DoExp(var Result : Real; var n : TokenType) : Boolean;
  182. var 
  183.    r : Boolean;
  184. begin
  185.      r := MatchFunc('EXP',Result,n);
  186.      Result := exp(Result);
  187.      DoExp := r;
  188. end; {doSin}
  189.  
  190. (******************************************************************************
  191. *                                    DoCos                                    *
  192. ******************************************************************************)
  193. function DoCos(var Result : Real; var n : TokenType) : Boolean;
  194. var 
  195.    r : Boolean;
  196. begin
  197.      r := MatchFunc('COS',Result,n);
  198.      Result := cos(Result);
  199.      DoCos := r;
  200. end; {doCos}
  201.  
  202. (******************************************************************************
  203. *                                    DoLn                                     *
  204. ******************************************************************************)
  205. function DoLn(var Result : Real; var n : TokenType) : Boolean;
  206. var 
  207.    r : Boolean;
  208. begin
  209.      r := MatchFunc('LN',Result,n);
  210.      if (Result > 0.0) then Result := ln(Result)
  211.         else DoErr(n);
  212.      DoLn := r;                   
  213. end; {doLn}
  214.  
  215. (******************************************************************************
  216. *                                   DoLog10                                   *
  217. ******************************************************************************)
  218. function DoLog10(var Result : Real; var n : TokenType) : Boolean;
  219. var 
  220.    r : Boolean;
  221. begin
  222.      r := MatchFunc('LOG10',Result,n);
  223.      if (Result > 0.0) then Result := ln(Result)/ln(10.0)
  224.         else DoErr(n);
  225.      DoLog10 := r;                   
  226. end; {doLog10}
  227.  
  228. (******************************************************************************
  229. *                                   DoLog2                                    *
  230. ******************************************************************************)
  231. function DoLog2(var Result : Real; var n : TokenType) : Boolean;
  232. var 
  233.    r : Boolean;
  234. begin
  235.      r := MatchFunc('LOG2',Result,n);
  236.      if (Result > 0.0) then Result := ln(Result)/ln(2.0)
  237.         else DoErr(n);
  238.      DoLog2 := r;                   
  239. end; {doLog2}
  240.  
  241. (******************************************************************************
  242. *                                    DoAbs                                    *
  243. ******************************************************************************)
  244. function DoAbs(var Result : Real; var n : TokenType) : Boolean;
  245. var 
  246.    r : Boolean;
  247. begin
  248.      r := MatchFunc('ABS',Result,n);
  249.      Result := Abs(Result);
  250.      DoAbs := r;
  251. end; {doAbs}
  252.  
  253. (******************************************************************************
  254. *                                  DoArcTan                                   *
  255. ******************************************************************************)
  256. function DoArcTan(var Result : Real; var n : TokenType) : Boolean;
  257. var 
  258.    r : Boolean;
  259. begin
  260.      r := MatchFunc('ARCTAN',Result,n);
  261.      Result := ArcTan(Result);
  262.      DoArcTan := r;
  263. end; {doArcTan}
  264.  
  265. (******************************************************************************
  266. *                                    DoSqr                                    *
  267. ******************************************************************************)
  268. function DoSqr(var Result : Real; var n : TokenType) : Boolean;
  269. var 
  270.    r : Boolean;
  271. begin
  272.      r := MatchFunc('SQR',Result,n);
  273.      Result := Sqr(Result);
  274.      DoSqr := r;
  275. end; {doSqr}
  276.  
  277. (******************************************************************************
  278. *                                   DoSqrt                                    *
  279. ******************************************************************************)
  280. function DoSqrt(var Result : Real; var n : TokenType) : Boolean;
  281. var 
  282.    r : Boolean;
  283. begin
  284.      r := MatchFunc('SQRT',Result,n);
  285.      Result := Sqrt(Result);
  286.      DoSqrt := r;
  287. end; {doSqrt}
  288.  
  289. (******************************************************************************
  290. *                                    DoTan                                    *
  291. ******************************************************************************)
  292. function DoTan(var Result : Real; var n : TokenType) : Boolean;
  293. var 
  294.    r : Boolean;
  295. begin
  296.      r := MatchFunc('TAN',Result,n);
  297.      if ( cos(result) <> 0 ) then 
  298.     Result := Sin(Result) / cos(Result)
  299.      else doErr(n);
  300.      DoTan := r;
  301. end; {doTan}
  302.  
  303. (******************************************************************************
  304. *                                   DoCoTan                                   *
  305. ******************************************************************************)
  306. function DoCoTan(var Result : Real; var n : TokenType) : Boolean;
  307. var 
  308.    r : Boolean;
  309. begin
  310.      r := MatchFunc('COTAN',Result,n);
  311.      if ( sin(result) <> 0 ) then 
  312.     Result := cos(Result) / sin(Result)
  313.      else doErr(n);
  314.      DoCoTan := r;
  315. end; {doCoTan}
  316.  
  317. (******************************************************************************
  318. *                                  DoArcSin                                   *
  319. ******************************************************************************)
  320. function DoArcSin(var Result : Real; var n : TokenType) : Boolean;
  321. var 
  322.    r : Boolean;
  323. begin
  324.      r := MatchFunc('ARCSIN',Result,n);
  325.      if (abs(Result) < 1.0) then
  326.     Result := arcTan(Result/sqrt(1-result*result))
  327.      else doErr(n);
  328.      DoArcSin := r;
  329. end; {doArcSin}
  330.  
  331. (******************************************************************************
  332. *                                  DoArcCos                                   *
  333. ******************************************************************************)
  334. function DoArcCos(var Result : Real; var n : TokenType) : Boolean;
  335. var 
  336.    r : Boolean;
  337. begin
  338.      r := MatchFunc('ARCCOS',Result,n);
  339.      if ((Result <> 0.0) and (result < 1.0)) then
  340.        Result := arcTan(sqrt(1-result*result)/result)
  341.     else doErr(n);
  342.     DoArcCos := r;
  343. end; {doArcCos}
  344.  
  345. (******************************************************************************
  346. *                                   DoFunc                                    *
  347. ******************************************************************************)
  348. procedure DoFunc(var Result : Real; var n : TokenType);
  349. begin
  350.      case Macro [i] of
  351.           's','S' : begin
  352.                          if not(DoSin(Result,n)) then
  353.                             if not(DoSqr(Result,n)) then
  354.                                if not(DoSqrt(Result,n)) then
  355.                             DoErr(n);
  356.                     end;
  357.           'c','C' : begin
  358.                          if not(DoCos(Result,n)) then
  359.                if not(DoCoTan(result,n)) then
  360.                             DoErr(n);
  361.                     end;
  362.           'l','L' : begin
  363.                          if not(DoLn(Result,n)) then
  364.                 if not(doLog10(result,n)) then
  365.                     if not(doLog2(result,n)) then
  366.                             DoErr(n);
  367.                     end;
  368.           'a','A' : begin
  369.                          if not(DoAbs(Result,n)) then
  370.                             if not(DoArcTan(Result,n)) then
  371.                 if not(doArcSin(Result,n)) then
  372.                      if not(doArcCos(result,n))
  373.                                then DoErr(n);
  374.                     end;
  375.           'e','E' : begin
  376.                          if not(DoExp(Result,n)) then
  377.                 if not(doE(result)) then
  378.                                      DoErr(n);
  379.                     end;
  380.       't','T' : begin
  381.             if not(doTan(result,n)) then
  382.                 doErr(n);
  383.             end;
  384.       'p','P' : begin
  385.             if not(doPI(result)) then 
  386.                 doErr(n);
  387.             end;     
  388.           else DoErr(n);
  389.      end; {case}
  390. end;
  391.  
  392. procedure Primitive(var Result : Real; var n : TokenType);
  393.  
  394. begin
  395.      if n = variable then begin
  396.         Inc(i);
  397.         SkipBlanks;
  398.         if Macro [i] in ['0'..'9'] then begin
  399.            Result := V [Macro [i]];
  400.            Inc(i);
  401.         end else DoErr(n);
  402.      end else if n = Digit then Result := ReadNumber
  403.      else if (n = Func) then DoFunc(Result,n);
  404.      SkipBlanks;
  405. end;
  406.  
  407. procedure Level6(var Result : Real; var n : TokenType);
  408.  
  409. {deal with parenthsis}
  410.  
  411. begin
  412.      if (n = Delimiter) and (Macro [i] = '(') then begin
  413.         Inc(i);
  414.         n := GetToken;
  415.         Level1(Result,n);
  416.         SkipBlanks; {Reach closing parenthasis}
  417.         if Macro[i] <> ')' then DoErr(n);
  418.         Inc(i);
  419.         SkipBlanks;
  420.      end else Primitive (Result,n);
  421. end;
  422.  
  423. procedure Level5(var Result : Real; var n : TokenType);
  424.  
  425. {Unary +,-}
  426.  
  427. var op : Char;
  428.  
  429. begin
  430.      op := Macro [i];
  431.      if op in ['-','+'] then Inc(i);
  432.      n := GetToken;
  433.      Level6(Result,n);
  434.      if op = '-' then Result := - (Result);
  435. end;
  436.  
  437. function Sign(Number : Real) : Real;
  438.  
  439. {-1 if Number < 0 , 1 otherwise}
  440.  
  441. begin
  442.      if (Number < 0.0) then Sign := -1.0
  443.         else Sign := 1.0;
  444. end;
  445.  
  446. procedure Level4(var Result : Real; var n : TokenType);
  447.  
  448. var Hold : Real;
  449.  
  450. begin
  451.      Level5(Result,n);
  452.      if (n <> Error) then
  453.         if macro [i] = '^' then begin
  454.            Inc(i);
  455.            n := GetToken;
  456.            Level4(Hold,n);
  457.            if (Result = 0.0) then
  458.               if (hold = 0.0) then result := 1.0
  459.                    else Result := 0.0
  460.            else Result := Sign(Result) * Exp(Hold * Ln(Abs(Result)));
  461.                                           {mimic power}
  462.            SkipBlanks;
  463.            end;
  464. end;
  465.  
  466. procedure Level3(var Result : Real; var n : TokenType);
  467.  
  468. {Multipy / divide 2 factors}
  469.  
  470. var Hold : Real;
  471.     op   : Char;
  472.  
  473. begin
  474.      Level4(Result,n);
  475.      if (n <> Error) then begin
  476.         SkipBlanks;
  477.         While Macro [i] in ['*','/','%'] do begin
  478.            op := Macro[i];
  479.            Inc(i);
  480.            n := GetToken;
  481.            Level4(Hold,n);
  482.            if op = '*' then Result := Result * Hold
  483.               else begin
  484.             if (hold = 0.0) then doErr(n)
  485.               else 
  486.             if op = '/' then Result := Result / Hold
  487.                            else Result := Trunc(Result) mod Trunc(Hold);
  488.           end;
  489.            SkipBlanks;
  490.         end;
  491.      end; {not error}
  492. end;
  493.  
  494. procedure Level2(var Result : Real; var n : TokenType);
  495.  
  496. {add/sub 2 terms}
  497.  
  498. var Hold : Real;
  499.     op   : Char;
  500.  
  501. begin
  502.      Level3(Result,n);
  503.      if (n <> Error) then begin
  504.         SkipBlanks;
  505.         While (Macro [i] in ['+','-']) do begin
  506.            op := Macro [i];
  507.            inc(i);
  508.            n := GetToken;
  509.            Level3(Hold,n);
  510.            if op = '+' then Result := Result + Hold
  511.               else Result := Result - Hold;
  512.            SkipBlanks;
  513.         end; {while}
  514.      end; {not error}
  515. end;
  516.  
  517. procedure Level1(var Result : Real; var n : TokenType);
  518.  
  519. var Slot : Char;
  520.     m    : TokenType;
  521.     j    : Byte;
  522.  
  523. begin
  524.      if n = variable then begin
  525.         j := i; {save  i}
  526.         Inc(i);
  527.         SkipBlanks;
  528.         if Macro [i] in ['0'..'9'] then Slot := Macro [i]
  529.            else DoErr(n);
  530.         if (n <> Error) then begin
  531.            Inc(i);
  532.            m := GetToken;
  533.            if ((m = Delimiter) and (Macro [i] = '=') and (i <=length(Macro)))
  534.            then begin
  535.                 Inc(i);
  536.                 n := GetToken;
  537.                 Level2(Result,n);
  538.                 V [Slot] := Result;
  539.            end else begin
  540.                i := j; {restore ..}
  541.                level2(Result,n);
  542.            end; {not a vx = ...}
  543.         end {n <> error}
  544.      end {variable case} else
  545.          Level2(Result,n);
  546. end;
  547.  
  548. {Deal with assinment here}
  549.  
  550. function GetExpr(var Valid:Boolean) : Real;
  551.  
  552. var Result : Real;
  553.     n      : TokenType;
  554.  
  555. begin
  556.      i := 1;
  557.      Result := 0; {if no result returned}
  558.      n := GetToken;
  559.      if Not (n in [endExpr,Non]) then Level1(Result,n);
  560.      if (n <> endExpr) and (i < Length(Macro)) then Dec(i);
  561.      GetExpr := Result;
  562.      if (n = Error) then Valid := False
  563.         else Valid := True;
  564. end;
  565.  
  566. (******************************************************************************
  567. *                                    MAIN                                     *
  568. ******************************************************************************)
  569. begin
  570.    for c := '0' to '9' do
  571.       v[c] := 0.0;
  572. end.
  573.