home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / calculat / pibcal11.zip / EXPRESSI.PAS < prev    next >
Pascal/Delphi Source File  |  1985-03-11  |  21KB  |  601 lines

  1. (*--------------------------------------------------------------------------*)
  2. (*                Expression -- parse and execute expression                *)
  3. (*--------------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Expression( VAR formal: formalty;
  6.                       VAR Iline:  AnyStr;
  7.                       VAR Ipos:   INTEGER;
  8.                       VAR v:      valuety);
  9.  
  10. (*--------------------------------------------------------------------------*)
  11. (*                                                                          *)
  12. (*     Procedure:  Expression                                               *)
  13. (*                                                                          *)
  14. (*     Purpose:    Parse and execute expression                             *)
  15. (*                                                                          *)
  16. (*     Calling sequence:                                                    *)
  17. (*                                                                          *)
  18. (*        Expression( VAR formal: formalty;                                 *)
  19. (*                    VAR Iline:  AnyStr;                                   *)
  20. (*                    VAR Ipos:   INTEGER;                                  *)
  21. (*                    VAR v:      valuety);                                 *)
  22. (*                                                                          *)
  23. (*           formal -- formal parameter block                               *)
  24. (*           Iline  -- input command line                                   *)
  25. (*           Ipos   -- current position in input command line               *)
  26. (*           v      -- value of variable                                    *)
  27. (*                                                                          *)
  28. (*     Calls:     Term                                                      *)
  29. (*                                                                          *)
  30. (*     Called By: DoExp                                                     *)
  31. (*                                                                          *)
  32. (*     Remarks:                                                             *)
  33. (*                                                                          *)
  34. (*        This is the heart of the PibCalc program.  This procedure         *)
  35. (*        controls parsing and execution of an expression in PibCalc        *)
  36. (*        syntax.  The method used is recursive descent.                    *)
  37. (*                                                                          *)
  38. (*        Expression syntax:                                                *)
  39. (*        -----------------                                                 *)
  40. (*                                                                          *)
  41. (*        Expressions are composed of constants, variables, function calls, *)
  42. (*        and the special element '.', using the operators  +, -, *, /, **, *)
  43. (*        MOD, and DIV, acoording to the usual algorithmic programming      *)
  44. (*        language syntax rules.  Parentheses may be used for grouping.     *)
  45. (*        The precise syntax is given below in a modified Backus-Naur form. *)
  46. (*                                                                          *)
  47. (*        Notation used:                                                    *)
  48. (*                                                                          *)
  49. (*           =            is defined to be.                                 *)
  50. (*           .            end of definition.                                *)
  51. (*           '...'        Literal.                                          *)
  52. (*           [...]        Optional.                                         *)
  53. (*           <...>        Repeat 0 or more times.                           *)
  54. (*           |            Or.                                               *)
  55. (*           (...)        Grouping.                                         *)
  56. (*                                                                          *)
  57. (*           EXP     = [SIGN] TERM < ADOP TERM >.                           *)
  58. (*           TERM    = FACTOR < MULOP FACTOR >.                             *)
  59. (*           FACTOR  = ELEMENT < '**' ELEMENT >.                            *)
  60. (*           ELEMENT = CONST | VAR | '(' EXP ')' | '.' | FUNC.              *)
  61. (*           SIGN    = '+' | '-'.                                           *)
  62. (*           ADOP    = '+' | '-'.                                           *)
  63. (*           MULOP   = '*' | '/' | 'MOD' | 'DIV'.                           *)
  64. (*           CONST   = INT | REAL.                                          *)
  65. (*           INT     = DECINT | OCTINT | HEXINT.                            *)
  66. (*           DECINT  = DEC <DEC> ['D'].                                     *)
  67. (*           OCTINT  = OCT <OCT> ['B'|'O'].                                 *)
  68. (*           HEXINT  = HEX <HEX> ['X'].                                     *)
  69. (*           REAL    = DEC <DEC> '.' <DEC> [EXPON] |                        *)
  70. (*                     <DEC> '.' DEC <DEC> [EXPON].                         *)
  71. (*           EXPON   = 'E' [SIGN] DEC <DEC>.                                *)
  72. (*           VAR     = LET.                                                 *)
  73. (*           FUNC    = FNAME [ '(' EXP < ',' EXP > ')' ].                   *)
  74. (*           FNAME   = LET < ALPHNUM >.                                     *)
  75. (*           ALPHNUM = LET | DEC.                                           *)
  76. (*           LET     = 'A' | ... | 'Z'.                                     *)
  77. (*           DEC     = '0' | ... | '9'.                                     *)
  78. (*           OCT     = '0' | ... | '7'.                                     *)
  79. (*           HEX     = '0' | ... | '9' | 'A' | ... | 'F'.                   *)
  80. (*                                                                          *)
  81. (*        The routines here are a quite direct translation of this syntax   *)
  82. (*        into Turbo.  Hence, detailed descriptions of the routines are     *)
  83. (*        not provided.                                                     *)
  84. (*                                                                          *)
  85. (*--------------------------------------------------------------------------*)
  86.  
  87.  
  88. LABEL
  89.    99  (* ERROR EXIT *);
  90.  
  91. VAR
  92.    negate: BOOLEAN;
  93.    op:     Tokenty;
  94.    w:      valuety;
  95.  
  96. (*--------------------------------------------------------------------------*)
  97. (*                NextTok -- Get next token                                 *)
  98. (*--------------------------------------------------------------------------*)
  99.  
  100. PROCEDURE NextTok;
  101.  
  102. BEGIN (* NextTok *)
  103.  
  104.    GetTok( Iline , Ipos );
  105.  
  106. END   (* NextTok *);
  107.  
  108. (*--------------------------------------------------------------------------*)
  109. (*                VarVal -- Get value of variable                           *)
  110. (*--------------------------------------------------------------------------*)
  111.  
  112. PROCEDURE VarVal( varnam: varnamty; VAR v: valuety );
  113.  
  114. VAR
  115.    i:     INTEGER;
  116.    found: BOOLEAN;
  117.  
  118. BEGIN  (* VarVal *)
  119.  
  120.    WITH formal DO
  121.       BEGIN
  122.  
  123.          i     := 0;
  124.          found := FALSE;
  125.  
  126.          WHILE ( i < nump ) AND ( NOT found ) DO
  127.             BEGIN
  128.                i     := i + 1;
  129.                found := ( varnam = parms[i].name );
  130.             END;
  131.  
  132.          IF found THEN
  133.             v := parms[i].VAL
  134.          ELSE
  135.             IF NOT VarVals[varnam].def THEN Undef(varnam)
  136.             ELSE v := VarVals[varnam]
  137.  
  138.       END;
  139.  
  140. END   (* VarVal *);
  141.  
  142. (*--------------------------------------------------------------------------*)
  143. (*                StdFunc -- Get value of standard function                 *)
  144. (*--------------------------------------------------------------------------*)
  145.  
  146. PROCEDURE StdFunc( index:INTEGER; VAR v:valuety );
  147.  
  148. LABEL
  149.    99  (* Error exit *);
  150.  
  151. VAR
  152.       a: valuety;
  153.       b: valuety;
  154.       k: INTEGER;
  155.  
  156. (*--------------------------------------------------------------------------*)
  157. (*                BadArg -- Report error in argument to function            *)
  158. (*--------------------------------------------------------------------------*)
  159.  
  160. PROCEDURE BadArg;
  161.  
  162. BEGIN (* BadArg *)
  163.  
  164.    WRITELN('Bad argument to ',StdFuncs[index].name);
  165.    ErrorFlag := TRUE;
  166.  
  167. END   (* BadArg *);
  168.  
  169. (*--------------------------------------------------------------------------*)
  170.  
  171. BEGIN  (* StdFunc *)
  172.  
  173.    WITH StdFuncs[index],v DO
  174.       BEGIN
  175.  
  176.          def := TRUE;
  177.          typ := rea;
  178.          i    := 0;
  179.  
  180.          IF nparms <> 0 THEN
  181.          BEGIN
  182.                                    (* Evaluate 1st function argument *)
  183.             NextTok;
  184.  
  185.             IF Token <> oparsy THEN
  186.                BEGIN
  187.                   SynErr;
  188.                   GOTO 99;
  189.                END;
  190.  
  191.             NextTok;
  192.  
  193.             Expression( formal, Iline, ipos, a );
  194.  
  195.             IF ErrorFlag THEN GOTO 99;
  196.  
  197.             IF nparms = 2 THEN     (* Evaluate 2nd function argument *)
  198.             BEGIN
  199.  
  200.                IF Token <> commasy THEN
  201.                   BEGIN
  202.                      SynErr;
  203.                      GOTO 99;
  204.                   END;
  205.  
  206.                NextTok;
  207.  
  208.                Expression( formal, Iline, ipos, b );
  209.  
  210.                IF ErrorFlag THEN GOTO 99;
  211.  
  212.             END;
  213.  
  214.          END;
  215.  
  216.                                    (* Convert angle in degrees to angle *)
  217.                                    (* in radians                        *)
  218.  
  219.          IF ( angle = deg ) AND ( func IN [ sinf..cscf ] ) THEN
  220.             a.r := a.r * PI/180.0;
  221.  
  222.                                    (* Check for valid argument values *)
  223.          CASE func OF
  224.             tanf, secf:
  225.                IF COS(a.r) = 0.0 THEN BadArg;
  226.             cotf, cscf:
  227.                IF SIN(a.r) = 0.0 THEN BadArg;
  228.             asinf, acosf:
  229.                IF abs(a.r) > 1.0 THEN BadArg;
  230.             asecf, acscf:
  231.                IF abs(a.r) < 1.0 THEN BadArg;
  232.             atan2f:
  233.                IF abs(a.r)=0.0 THEN IF abs(b.r)=0.0 THEN BadArg;
  234.             lnf, log10f:
  235.                IF a.r <= 0.0 THEN BadArg;
  236.             logf:
  237.                BEGIN
  238.                   IF a.r <= 0.0 THEN BadArg;
  239.                   IF b.r <= 0.0 THEN BadArg
  240.                END;
  241.             sqrtf:
  242.                IF a.r < 0.0 THEN BadArg;
  243.             ELSE;
  244.          END (* CASE *);
  245.  
  246.          IF ErrorFlag THEN GOTO 99;
  247.  
  248.                                    (* Evaluate the function *)
  249.          CASE func OF
  250.  
  251.             absf:
  252.                BEGIN
  253.                   typ := a.typ;
  254.                   r   := abs( a.r );
  255.                   i   := abs( a.i );
  256.                END;
  257.             minf, Maxf:
  258.                BEGIN
  259.                   typ := a.typ;
  260.                   r   := a.r;
  261.                   i   := a.i;
  262.                   WHILE Token = commasy DO
  263.                      BEGIN
  264.                         NextTok;
  265.                         Expression( formal, Iline, ipos, a );
  266.                         IF ErrorFlag THEN GOTO 99;
  267.                         IF a.typ = rea THEN typ := rea;
  268.                         IF ( ( func = minf ) AND ( a.r < r ) ) OR
  269.                            ( ( func = maxf ) AND ( a.r > r ) ) THEN
  270.                            BEGIN
  271.                               r := a.r;
  272.                               i := a.i
  273.                            END
  274.                      END
  275.                END;
  276.  
  277.             truncf:
  278.                BEGIN
  279.                   i   := TRUNC( a.r );
  280.                   k   := i;
  281.                   r   := k;
  282.                   typ := INT;
  283.                END;
  284.  
  285.             roundf:
  286.                BEGIN
  287.                   i   := ROUND( a.r );
  288.                   k   := i;
  289.                   r   := k;
  290.                   typ := INT;
  291.                END;
  292.  
  293.             sinf:   r := SIN( a.r );
  294.             cosf:   r := COS( a.r );
  295.             tanf:   r := SIN( a.r ) / COS( a.r );
  296.             cotf:   r := COS( a.r ) / SIN( a.r );
  297.             secf:   r := 1.0 / COS( a.r );
  298.             cscf:   r := 1.0 / SIN( a.r );
  299.             asinf:  r := arcsin( a.r );
  300.             acosf:  r := arccos( a.r );
  301.             atanf:  r := ARCTAN( a.r );
  302.             acotf:  r := PI / 2.0 - ARCTAN( a.r );
  303.             asecf:  r := arccos( 1.0 / a.r );
  304.             acscf:  r := arcsin( 1.0 / a.r );
  305.             atan2f: r := arctan2( a.r , b.r );
  306.             expf:   r := EXP( a.r );
  307.             lnf:    r := LN( a.r );
  308.             log10f: r := log10( a.r );
  309.             logf:   r := log( a.r , b.r );
  310.             sqrtf:  r := SQRT( a.r );
  311.             EEf:    r := EE;
  312.             PIf:    r := PI;
  313.  
  314.          END (* CASE *);
  315.  
  316.          IF ErrorFlag THEN GOTO 99;
  317.  
  318.                                    (* Convert angles to degrees if needed *)
  319.  
  320.          IF ( angle = deg ) AND ( func IN [asinf..atan2f] ) THEN
  321.             r := r * 180.0/PI;
  322.                                    (* Check if any garbage left over *)
  323.  
  324.          IF (nparms <> 0) AND (Token <> cparsy) THEN SynErr
  325.  
  326.       END  (* WITH *);
  327.  
  328. 99:
  329.    END;
  330.  
  331. (*--------------------------------------------------------------------------*)
  332. (*               UserFunc -- Evaluate user-defined function                 *)
  333. (*--------------------------------------------------------------------------*)
  334.  
  335. PROCEDURE UserFunc (index: INTEGER; VAR v: valuety);
  336.  
  337. LABEL
  338.    99 (* ERROR EXIT *);
  339.  
  340. VAR
  341.    lformal: formalty;
  342.    i:       INTEGER;
  343.    dpos:    INTEGER;
  344.  
  345. BEGIN  (* UserFunc *)
  346.  
  347.    WITH UserFuncs[index],lformal DO
  348.  
  349.       BEGIN
  350.                                    (* Pick up no. of params to function *)
  351.          nump := nparms;
  352.  
  353.          IF nparms > 0 THEN        (* If params, need to evaluate each one *)
  354.             BEGIN
  355.  
  356.                NextTok;            (* Look for open paren of arg list *)
  357.  
  358.                IF Token <> oparsy THEN
  359.                   BEGIN
  360.                      SynErr;
  361.                      GOTO 99;
  362.                   END;
  363.                                     (* Loop over each param *)
  364.  
  365.                FOR i := 1 TO nparms DO
  366.                   BEGIN
  367.                                     (* Pick up formal param name *)
  368.  
  369.                      parms[i].name := pnames[i];
  370.  
  371.                      NextTok;
  372.                                     (* Evaluate its actual value *)
  373.  
  374.                      Expression( formal, Iline, ipos, parms[i].VAL );
  375.  
  376.                      IF ErrorFlag THEN GOTO 99;
  377.  
  378.                                     (* Look for comma *)
  379.  
  380.                      IF i < nparms THEN
  381.                         IF Token <> commasy THEN
  382.                            BEGIN
  383.                               SynErr;
  384.                               GOTO 99;
  385.                            END;
  386.  
  387.                   END;
  388.                                    (* Look for closing right paren *)
  389.                                    (* of argument list             *)
  390.  
  391.             IF Token <> cparsy THEN
  392.                BEGIN
  393.                   SynErr;
  394.                   GOTO 99;
  395.                END;
  396.  
  397.          END;
  398.                                    (* Now scan definition of function, *)
  399.                                    (* inserting actual values in place *)
  400.                                    (* of formal parameters, and hence  *)
  401.                                    (* evaluating function.             *)
  402.  
  403.                                    (* dpos = current position in       *)
  404.                                    (* definition of function.          *)
  405.          dpos := 1;
  406.  
  407.          GetTok( defn , dpos );
  408.  
  409.          Expression( lformal, defn, dpos, v );
  410.  
  411.          IF ErrorFlag THEN GOTO 99;
  412.  
  413.                                    (* Ensure all of function definition *)
  414.                                    (* used up.                          *)
  415.  
  416.          IF Token <> eolsy THEN
  417.             BEGIN
  418.                SynErr;
  419.                GOTO 99;
  420.             END;
  421.  
  422.       END;
  423.  
  424. 99:
  425. END   (* UserFunc *);
  426.  
  427. (*--------------------------------------------------------------------------*)
  428. (*               Element -- pick up 'element' in expression                 *)
  429. (*--------------------------------------------------------------------------*)
  430.  
  431. PROCEDURE Element( VAR v: valuety );
  432.  
  433. LABEL
  434.    99 (* ERROR EXIT *);
  435.  
  436. BEGIN (* Element *)
  437.  
  438.          (*---------------------------------------------------*)
  439.          (* ELEMENT = CONST | VAR | '(' EXP ')' | '.' | FUNC. *)
  440.          (*---------------------------------------------------*)
  441.  
  442.    CASE Token OF
  443.       constsy   :   v := constval;
  444.       varsy     :   VarVal( varnam , v );
  445.       oparsy    :   BEGIN
  446.                        NextTok;
  447.                        Expression( formal, Iline, ipos, v );
  448.                        IF ErrorFlag THEN GOTO 99;
  449.                        IF Token <> cparsy THEN SynErr;
  450.                     END;
  451.       periodsy  : v := curval;
  452.       StdFuncsy : StdFunc( iStdFunc , v );
  453.       UserFuncsy: UserFunc( iUserFunc , v );
  454.       ELSE
  455.          SynErr;
  456.    END (* Case *);
  457.  
  458.    IF ( NOT ErrorFlag ) THEN NextTok;
  459.  
  460. 99:
  461. END (* Element *);
  462.  
  463. (*--------------------------------------------------------------------------*)
  464. (*               Factor -- pick up 'factor' in expression                   *)
  465. (*--------------------------------------------------------------------------*)
  466.  
  467. PROCEDURE Factor( VAR v: valuety );
  468.  
  469. VAR
  470.    w: valuety;
  471.  
  472. LABEL 99;
  473.  
  474. BEGIN (* Factor *)
  475.  
  476.          (*-------------------------------------*)
  477.          (* FACTOR  = ELEMENT < '**' ELEMENT >. *)
  478.          (*-------------------------------------*)
  479.  
  480.    Element( v );
  481.  
  482.    IF ErrorFlag THEN GOTO 99;
  483.  
  484.    WHILE Token = exponsy DO
  485.       BEGIN
  486.  
  487.          NextTok;
  488.  
  489.          Element( w );
  490.  
  491.          IF ErrorFlag THEN GOTO 99;
  492.  
  493.          Powvals( v , w );
  494.  
  495.       END;
  496.  
  497. 99:
  498.  
  499. END  (* Factor *);
  500.  
  501. (*--------------------------------------------------------------------------*)
  502. (*               Term -- pick up 'term' in expression                       *)
  503. (*--------------------------------------------------------------------------*)
  504.  
  505. PROCEDURE Term( VAR v: valuety );
  506.  
  507. VAR
  508.    op: Tokenty;
  509.    w:  valuety;
  510.  
  511. LABEL 99;
  512.  
  513. BEGIN  (* Term *)
  514.  
  515.          (*---------------------------------*)
  516.          (* TERM = FACTOR < MULOP FACTOR >. *)
  517.          (*---------------------------------*)
  518.  
  519.    Factor( v );
  520.  
  521.    IF ErrorFlag THEN GOTO 99;
  522.  
  523.    WHILE Token IN [starsy,slashsy,modsy,divsy] DO
  524.       BEGIN
  525.  
  526.          op := Token;
  527.  
  528.          NextTok;
  529.  
  530.          Factor( w );
  531.  
  532.          IF ErrorFlag THEN GOTO 99;
  533.  
  534.          CASE op OF
  535.             starsy:  MulVals ( v , w );
  536.             slashsy: RdivVals( v , w );
  537.             divsy:   IdivVals( v , w );
  538.             modsy:   ModVals ( v , w );
  539.          END;
  540.  
  541.       END;
  542.  
  543. 99:
  544. END  (* Term *);
  545.  
  546. (*--------------------------------------------------------------------------*)
  547.  
  548. BEGIN (* Expression *)
  549.  
  550.                                     (* Any errors before getting here? *)
  551.                                     (* If so, do nothing.              *)
  552.    IF ErrorFlag THEN GOTO 99;
  553.  
  554.          (*-----------------------------------*)
  555.          (* EXP = [SIGN] TERM < ADOP TERM >.  *)
  556.          (*-----------------------------------*)
  557.  
  558.                                     (* Check for and remember leading *)
  559.                                     (* sign                           *)
  560.    negate := FALSE;
  561.  
  562.    IF Token IN [plussy,minussy] THEN
  563.    BEGIN
  564.       negate := ( Token = minussy );
  565.       NextTok;
  566.    END;
  567.                                    (* Pick up leading expression value *)
  568.    Term( v );
  569.    IF ErrorFlag THEN GOTO 99;
  570.  
  571.                                    (* Apply negative sign if leading '-' *)
  572.    IF negate THEN
  573.       WITH v DO
  574.          BEGIN
  575.             r := -r;
  576.             IF typ = INT THEN i := -i;
  577.          END;
  578.  
  579.                                    (* Continue through rest of expression *)
  580.  
  581.    WHILE Token IN [plussy,minussy] DO
  582.       BEGIN
  583.  
  584.          op := Token;
  585.  
  586.          NextTok;
  587.  
  588.          Term( w );
  589.  
  590.          IF ErrorFlag THEN GOTO 99;
  591.  
  592.          CASE op OF
  593.             plussy:  addvals( v , w );
  594.             minussy: subvals( v , w );
  595.          END;
  596.  
  597.       END;
  598.  
  599. 99:
  600. END  (* EXPRESSION *);
  601.