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

  1. (*--------------------------------------------------------------------------*)
  2. (*                  GetTok  --- Get Token from Command Line                 *)
  3. (*--------------------------------------------------------------------------*)
  4.  
  5. PROCEDURE GetTok( VAR Iline: AnyStr; VAR Ipos: INTEGER );
  6.  
  7. (*--------------------------------------------------------------------------*)
  8. (*                                                                          *)
  9. (*     Procedure:  GetTok                                                   *)
  10. (*                                                                          *)
  11. (*     Purpose:    Extracts a token from the command line.                  *)
  12. (*                                                                          *)
  13. (*     Calling Sequence:                                                    *)
  14. (*                                                                          *)
  15. (*        GetTok( VAR Iline: AnyStr; VAR Ipos: INTEGER );                   *)
  16. (*                                                                          *)
  17. (*           Iline  --- command line                                        *)
  18. (*           Ipos   --- current position in command line                    *)
  19. (*                                                                          *)
  20. (*     Calls:                                                               *)
  21. (*                                                                          *)
  22. (*        Lookahead                                                         *)
  23. (*        CrackWord                                                         *)
  24. (*        CrackReal                                                         *)
  25. (*        SynErr                                                            *)
  26. (*                                                                          *)
  27. (*--------------------------------------------------------------------------*)
  28.  
  29. (*--------------------------------------------------------------------------*)
  30. (*                  CrackNum --- Get number from command line               *)
  31. (*--------------------------------------------------------------------------*)
  32.  
  33. PROCEDURE CrackNum(      b:      INTEGER;
  34.                          digset: CharSetTy;
  35.                      VAR num:    REAL;
  36.                      VAR len:    INTEGER    );
  37.  
  38. (*--------------------------------------------------------------------------*)
  39. (*                                                                          *)
  40. (*     Procedure:  CrackNum                                                 *)
  41. (*                                                                          *)
  42. (*     Purpose:    Extracts a number from the command line.                 *)
  43. (*                                                                          *)
  44. (*     Calling Sequence:                                                    *)
  45. (*                                                                          *)
  46. (*        CrackNum(          b: INTEGER;                                    *)
  47. (*                      digset: CharSetTy;                                  *)
  48. (*                     VAR num: REAL        ;                               *)
  49. (*                     VAR len: INTEGER );                                  *)
  50. (*                                                                          *)
  51. (*            b      --- base for number                                    *)
  52. (*            digset --- set of legal characters for digits                 *)
  53. (*            num    --- resultant number (REAL!)                           *)
  54. (*            len    --- no. digits in number                               *)
  55. (*                                                                          *)
  56. (*     Calls:                                                               *)
  57. (*                                                                          *)
  58. (*        ORD                                                               *)
  59. (*                                                                          *)
  60. (*--------------------------------------------------------------------------*)
  61.  
  62. VAR
  63.    c: CHAR;
  64.  
  65. BEGIN  (* CrackNum *)
  66.  
  67.    num := 0.0;
  68.    len := 0;
  69.  
  70.    WHILE Iline[Ipos] IN digset DO
  71.       BEGIN
  72.  
  73.          c   := Iline[Ipos];
  74.          num := b * num;
  75.  
  76.          IF c IN ['0'..'9'] THEN
  77.             num := num + ORD(c) - ORD('0')
  78.          ELSE
  79.             num := num + ORD(c) - ORD('A') + 10;
  80.  
  81.          len  := len  + 1;
  82.          Ipos := Ipos + 1;
  83.  
  84.       END;
  85.  
  86. END    (* CrackNum *);
  87.  
  88. (*--------------------------------------------------------------------------*)
  89. (*                  CrackInt --- Get integer from command line              *)
  90. (*--------------------------------------------------------------------------*)
  91.  
  92. PROCEDURE CrackInt( b:       INTEGER;
  93.                     digset:  CharSetTy;
  94.                     flagset: CharSetTy );
  95.  
  96. (*--------------------------------------------------------------------------*)
  97. (*                                                                          *)
  98. (*     Procedure:  CrackInt                                                 *)
  99. (*                                                                          *)
  100. (*     Purpose:    Extracts an integer from the command line.               *)
  101. (*                                                                          *)
  102. (*     Calling Sequence:                                                    *)
  103. (*                                                                          *)
  104. (*        CrackInt( b:       INTEGER;                                       *)
  105. (*                  digset:  CharSetTy;                                     *)
  106. (*                  flagset: CharSetTy;                                     *)
  107. (*                                                                          *)
  108. (*            b       --- base for number                                   *)
  109. (*            digset  --- set of legal characters for digits                *)
  110. (*            flagset --- legal terminator for base                         *)
  111. (*                                                                          *)
  112. (*     Calls:                                                               *)
  113. (*                                                                          *)
  114. (*        CrackNum                                                          *)
  115. (*        SynErr                                                            *)
  116. (*                                                                          *)
  117. (*--------------------------------------------------------------------------*)
  118.  
  119. VAR
  120.    num:  REAL;
  121.    len:  INTEGER;
  122.  
  123. BEGIN (* CrackInt *)
  124.  
  125.    CrackNum( b, digset, num, len );
  126.  
  127.    IF len = 0 THEN SynErr
  128.    ELSE IF num > MaxLint THEN
  129.       Error('Number too big to be integer')
  130.    ELSE
  131.       BEGIN
  132.  
  133.          IF Iline[Ipos] IN flagset THEN Ipos := Ipos + 1;
  134.  
  135.          WITH constval DO
  136.             BEGIN
  137.                def := TRUE;
  138.                typ := INT;
  139.                i   := TRUNC( num );
  140.                r   := num;
  141.             END;
  142.  
  143.          Token := constsy;
  144.  
  145.       END;
  146.  
  147. END   (* CrackInt *);
  148.  
  149. (*--------------------------------------------------------------------------*)
  150. (*            CrackDec --- Get decimal integer from command line            *)
  151. (*--------------------------------------------------------------------------*)
  152.  
  153. PROCEDURE CrackDec;
  154.  
  155. BEGIN  (* CrackDec *)
  156.  
  157.    CrackInt( 10, ['0'..'9'], ['D'] );
  158.  
  159. END    (* CrackDec *);
  160.  
  161. (*--------------------------------------------------------------------------*)
  162. (*             CrackOct --- Get octal integer from command line             *)
  163. (*--------------------------------------------------------------------------*)
  164.  
  165. PROCEDURE CrackOct;
  166.  
  167. BEGIN  (* CrackOct *)
  168.  
  169.    CrackInt( 8, ['0'..'7'], ['B','O'] );
  170.  
  171. END    (* CrackOct *);
  172.  
  173. (*--------------------------------------------------------------------------*)
  174. (*             CrackHex --- Get hex integer from command line               *)
  175. (*--------------------------------------------------------------------------*)
  176.  
  177. PROCEDURE CrackHex;
  178.  
  179. BEGIN  (* CrackHex *)
  180.  
  181.    CrackInt( 16, ['0'..'9','A'..'F'], ['X'] );
  182.  
  183. END    (* CrackHex *);
  184.  
  185. (*--------------------------------------------------------------------------*)
  186. (*              CrackReal --- Get real number from command line             *)
  187. (*--------------------------------------------------------------------------*)
  188.  
  189. PROCEDURE CrackReal;
  190.  
  191. VAR
  192.    intpart:  REAL;
  193.    intlen:   INTEGER;
  194.    fracpart: REAL;
  195.    fraclen:  INTEGER;
  196.    expon:    REAL;
  197.    explen:   INTEGER;
  198.    expsign:  INTEGER;
  199.  
  200. LABEL 99;
  201.  
  202. BEGIN (* CrackReal *)
  203.                                    (* Get part up to '.' if any *)
  204.  
  205.    CrackNum(10, ['0'..'9'], intpart, intlen);
  206.  
  207.                                    (* Next char MUST be '.' *)
  208.    IF Iline[Ipos] <> '.' THEN
  209.       BEGIN
  210.          SynErr;
  211.          GOTO 99;
  212.       END;
  213.                                    (* Skip '.' *)
  214.    Ipos := Ipos + 1;
  215.                                    (* Get fractional part after '.' *)
  216.  
  217.    CrackNum(10, ['0'..'9'], fracpart, fraclen);
  218.  
  219.                                    (* If no digits found, error *)
  220.  
  221.    IF ( intlen + fraclen ) = 0 THEN
  222.       BEGIN
  223.          SynErr;
  224.          GOTO 99;
  225.       END;
  226.                                    (* Look for E -- signals exponent *)
  227.    expon   := 0;
  228.    expsign := +1;
  229.  
  230.    IF Iline[Ipos] = 'E' THEN
  231.       BEGIN
  232.                                    (* Skip past E *)
  233.          Ipos := Ipos + 1;
  234.                                    (* Pick up sign of exponent *)
  235.  
  236.          IF Iline[Ipos] IN ['+','-'] THEN
  237.             BEGIN
  238.                IF Iline[Ipos] = '-' THEN expsign := -1;
  239.                Ipos := Ipos + 1;
  240.             END;
  241.                                    (* Get numeric value of exponent *)
  242.  
  243.          CrackNum(10, ['0'..'9'], expon, explen);
  244.  
  245.                                    (* No digits -- syntax error *)
  246.          IF explen = 0 THEN
  247.             BEGIN
  248.                SynErr;
  249.                GOTO 99;
  250.             END;
  251.  
  252.       END;
  253.                                    (* Compose real result from parts *)
  254.       WITH constval DO
  255.          BEGIN
  256.             def := TRUE;
  257.             typ := rea;
  258.             i   := 0;
  259.             r   := ( intpart + fracpart * poweri( 10.0, -fraclen ) ) *
  260.                    poweri( 10.0, expsign * TRUNC( expon ) );
  261.          END;
  262.  
  263.       Token := constsy;
  264.  
  265. 99:
  266.  
  267. END   (* CrackReal *);
  268.  
  269. (*--------------------------------------------------------------------------*)
  270. (*                  CrackWord --- Get name from command line                *)
  271. (*--------------------------------------------------------------------------*)
  272.  
  273. PROCEDURE CrackWord;
  274.  
  275. LABEL
  276.    1;
  277.  
  278. VAR
  279.    kw:    Alfa;
  280.    i:     INTEGER;
  281.    found: BOOLEAN;
  282.  
  283. BEGIN  (* CrackWord *)
  284.  
  285.    i := 0;
  286.                                    (* Pick up name as letters, digits *)
  287.  
  288.    WHILE (i < 10 ) AND ( Iline[Ipos] IN ['A'..'Z','0'..'9'] ) DO
  289.       BEGIN
  290.          i     := i + 1;
  291.          kw[i] := Iline[Ipos];
  292.          Ipos  := Ipos + 1;
  293.       END;
  294.                                    (* Blank fill the keyword *)
  295.  
  296.    FOR i := i + 1 TO 10 DO kw[i] := ' ';
  297.  
  298.    found := FALSE;
  299.    i     := 0;
  300.                                    (* See if token a built-in name *)
  301.  
  302.    WHILE ( i < Maxtoknams ) AND ( NOT found ) DO
  303.       BEGIN
  304.          i     := i + 1;
  305.          found := ( kw = toknams[i].name );
  306.       END;
  307.                                    (* If found, save type in Token and *)
  308.                                    (* exit                             *)
  309.    IF found THEN
  310.       BEGIN
  311.          Token := toknams[i].tok;
  312.          GOTO 1;
  313.       END;
  314.  
  315.    i := 0;
  316.                                    (* Check user function names        *)
  317.  
  318.    WHILE ( i < Maxuserfuncs ) AND ( NOT found ) DO
  319.       BEGIN
  320.          i     := i + 1;
  321.          found := kw = userfuncs[i].name
  322.       END;
  323.                                    (* If found, remember which function *)
  324.                                    (* it was in 'iuserfunc'.            *)
  325.    IF found THEN
  326.       BEGIN
  327.          Token     := userfuncsy;
  328.          iuserfunc := i;
  329.          GOTO 1;
  330.       END;
  331.  
  332.                                    (* Now try single letter variable    *)
  333.                                    (* If it is, save variable name in   *)
  334.                                    (* 'varnam'.                         *)
  335.  
  336.    IF ( kw[1] IN ['A'..'Z'] ) AND ( kw[2] = ' ' ) THEN
  337.       BEGIN
  338.          Token  := varsy;
  339.          varnam := kw[1];
  340.          GOTO 1;
  341.       END;
  342.  
  343.    i := 0;
  344.                                    (* Last, try standard function names  *)
  345.  
  346.    WHILE (i < Maxstdfuncs) AND NOT found DO
  347.       BEGIN
  348.          i     := i + 1;
  349.          found := ( kw = stdfuncs[i].name );
  350.       END;
  351.                                    (* If found, remember which function  *)
  352.                                    (* in 'istdfunc'.                     *)
  353.    IF found THEN
  354.       BEGIN
  355.          Token    := stdfuncsy;
  356.          istdfunc := i;
  357.          GOTO 1;
  358.       END;
  359.                                    (* If none of the above, syntax error *)
  360.    SynErr;
  361.  
  362. 1:
  363.  
  364. END   (* CrackWord *);
  365.  
  366. (*--------------------------------------------------------------------------*)
  367. (*                  Lookahead -- Look ahead in command line                 *)
  368. (*--------------------------------------------------------------------------*)
  369.  
  370. PROCEDURE Lookahead;
  371.  
  372. (*--------------------------------------------------------------------------*)
  373. (*                                                                          *)
  374. (*     Procedure: Lookahead                                                 *)
  375. (*                                                                          *)
  376. (*     Purpose:   Look ahead in command line                                *)
  377. (*                                                                          *)
  378. (*     Calling sequence:                                                    *)
  379. (*                                                                          *)
  380. (*        Lookahead;                                                        *)
  381. (*                                                                          *)
  382. (*     Calls:                                                               *)
  383. (*                                                                          *)
  384. (*        CrackReal                                                         *)
  385. (*        CrackWord                                                         *)
  386. (*        CrackOct                                                          *)
  387. (*        CrackDec                                                          *)
  388. (*        CrackHex                                                          *)
  389. (*                                                                          *)
  390. (*     Remarks:                                                             *)
  391. (*                                                                          *)
  392. (*        When the default base is hexadecimal many ambiguities can arise.  *)
  393. (*        For example, the letters 'A' through 'F' could be either variable *)
  394. (*        names or hex constants. 'DEC' could be either a command or a      *)
  395. (*        hex constant, and '32B' could be either the octal constant        *)
  396. (*        (= 26 dec.) or the hex constant 32B.  The rule is that ALL SUCH   *)
  397. (*        AMBIGUITIES ARE RESOLVED IN FAVOR OF THE INTERPRETATION AS A HEX  *)
  398. (*        CONSTANT.  To override this rule a colon (:) may be used to       *)
  399. (*        prefix the construct.  For example, ':32B' always means the octal *)
  400. (*        constant 32 (=26 dec.), whatever the default base may be.         *)
  401. (*                                                                          *)
  402. (*--------------------------------------------------------------------------*)
  403.  
  404. VAR
  405.    spanset:  CharSetTy;
  406.    k:        INTEGER;
  407.    b:        basety;
  408.    lastchar: CHAR;
  409.    colon:    BOOLEAN;
  410.  
  411. BEGIN (* Lookahead *)
  412.  
  413.                                    (* See if colon found *)
  414.    colon := ( Iline[Ipos] = ':' );
  415.                                    (* Skip it if so *)
  416.    IF colon THEN Ipos := Ipos + 1;
  417.  
  418.    spanset := [];
  419.    k       := Ipos;
  420.    b       := base;
  421.                                    (* Scan assuming constant.    *)
  422.                                    (* 'b' is default base.       *)
  423.                                    (* 'k' is temporary Ipos      *)
  424.                                    (* 'lastchar' remembers last  *)
  425.                                    (* character in constant.     *)
  426.  
  427.    WHILE Iline[k] IN ['A'..'Z','0'..'9'] DO
  428.       BEGIN
  429.          IF k > Ipos THEN spanset := spanset + [lastchar];
  430.          lastchar := Iline[k];
  431.          k        := k + 1;
  432.       END;
  433.                                    (* Change base if last char was *)
  434.                                    (* B, O, X, or D                *)
  435.  
  436.    IF ( lastchar IN ['D','B','O','X'] ) AND ( ( base <> hex ) OR colon )
  437.       AND ( k > ( Ipos + 1 ) ) THEN
  438.          CASE lastchar OF
  439.             'D':      b := dec;
  440.             'B', 'O': b := oct;
  441.             'X':      b := hex
  442.          END
  443.       ELSE
  444.          spanset := spanset + [lastchar];
  445.  
  446.                                    (* If '.' stopped scan, try getting *)
  447.                                    (* real number                      *)
  448.  
  449.    IF Iline[k] = '.' THEN CrackReal
  450.  
  451.                                    (* Else try integer of appropriate  *)
  452.                                    (* base, if only digits/letters     *)
  453.  
  454.    ELSE IF ( b = dec ) AND ( spanset <= ['0'..'9'] ) THEN CrackDec
  455.    ELSE IF ( b = oct ) AND ( spanset <= ['0'..'7'] ) THEN CrackOct
  456.    ELSE IF ( b = hex ) AND ( spanset <= ['0'..'9','A'..'F'] ) AND
  457.          ( NOT colon ) THEN CrackHex
  458.  
  459.                                    (* Else must be name                *)
  460.    ELSE CrackWord;
  461.  
  462. END   (* Lookahead *);
  463.  
  464. (*--------------------------------------------------------------------------*)
  465.  
  466. BEGIN (* GetTok *)
  467.  
  468.                                    (* Skip blanks *)
  469.  
  470.    WHILE Iline[Ipos] = ' ' DO Ipos := Ipos + 1;
  471.  
  472.                                    (* Take action on next character  *)
  473.    CASE Iline[Ipos] OF
  474.                                    (* End of line marker encountered *)
  475.       COL: Token := eolsy;
  476.  
  477.                                    (* Name OR Constant           *)
  478.  
  479.       'A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9',
  480.       ':':  Lookahead;
  481.  
  482.                                    (* Name                       *)
  483.  
  484.       'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V',
  485.       'W','X','Y','Z': CrackWord;
  486.  
  487.       '+': Token := plussy;
  488.  
  489.       '-': Token := minussy;
  490.                                    (* *  = multiplication,     *)
  491.                                    (* ** = exponentation       *)
  492.       '*': BEGIN
  493.               IF Iline[ Ipos + 1 ] = '*' THEN
  494.                  Token := exponsy
  495.               ELSE
  496.                  Token := starsy;
  497.               IF Token = exponsy THEN Ipos := Ipos + 1;
  498.            END;
  499.  
  500.       '/': Token := slashsy;
  501.  
  502.       '(': Token := oparsy;
  503.  
  504.       ')': Token := cparsy;
  505.  
  506.       '=': Token := equalssy;
  507.  
  508.       ',': Token := commasy;
  509.  
  510.       '$': Token := dollarsy;
  511.  
  512.                                    (* '.' is accumulator OR start of   *)
  513.                                    (* real number if followed by digit *)
  514.  
  515.       '.': IF Iline[ Ipos + 1 ] IN ['0'..'9'] THEN
  516.               CrackReal
  517.            ELSE
  518.               Token := periodsy;
  519.  
  520.    ELSE
  521.       SynErr;
  522.  
  523.    END;
  524.                                    (* Skip those chars not yet skipped *)
  525.  
  526.    IF Token IN [plussy..periodsy] THEN Ipos := Ipos + 1;
  527.  
  528. END   (* GETTOK *);
  529.  
  530. (*--------------------------------------------------------------------------*)
  531. (*             NextTok --- Advance to next token in command line            *)
  532. (*--------------------------------------------------------------------------*)
  533.  
  534. PROCEDURE NextTok;
  535.  
  536. (*--------------------------------------------------------------------------*)
  537. (*                                                                          *)
  538. (*     Procedure:  NextTok                                                  *)
  539. (*                                                                          *)
  540. (*     Purpose:    Advance to next token in command line                    *)
  541. (*                                                                          *)
  542. (*     Calling sequence:                                                    *)
  543. (*                                                                          *)
  544. (*        NextTok;                                                          *)
  545. (*                                                                          *)
  546. (*     Calls:  GetTok                                                       *)
  547. (*                                                                          *)
  548. (*--------------------------------------------------------------------------*)
  549.  
  550. BEGIN (* NextTok *)
  551.  
  552.    GetTok( Iline , Ipos );
  553.  
  554. END   (* NextTok *);
  555.  
  556.