home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / tsetd2.zip / EXPR.S < prev    next >
Text File  |  1994-12-14  |  10KB  |  316 lines

  1. /*************************************************************************
  2.   Expr        Calculates the value of a specified mathematical expression.
  3.  
  4.   Author:     SemWare
  5.  
  6.   Date:       Mar 23, 1994
  7.  
  8.   Overview:
  9.  
  10.   This macro operates as a simple calculator, and handles decimal
  11.   or hexadecimal numbers.  For decimal numbers, only whole numbers
  12.   are accepted.
  13.  
  14.   Keys:       (none)
  15.  
  16.   Usage notes:
  17.  
  18.   This macro does not have any key assignments.  To use, simply
  19.   select it from the Potpourri menu.
  20.  
  21.   The following operations are available:
  22.  
  23.             >      SHR      (bitwise shift right)
  24.             <      SHL      (bitwise shift left)
  25.             ~      COMP     (2's complement)
  26.             %      MOD      (modulo division)
  27.             &      AND      (bitwise AND)
  28.             |      OR       (bitwise OR)
  29.             ^      XOR      (bitwise eXclusive-OR)
  30.             +      Addition
  31.             -      Subtraction
  32.             *      Multiplication
  33.             /      Division
  34.  
  35.   Precedence is as in SAL, but can be forced by using parenthesis.
  36.  
  37.   Hex number may be entered using C format, or ending with an 'h'
  38.   or '$'.  Regardless, the first character _must_ be numeric.
  39.  
  40.   Copyright 1992-1994 SemWare Corporation.  All Rights Reserved Worldwide.
  41.  
  42.   Use, modification, and distribution of this SAL macro is encouraged by
  43.   SemWare provided that this statement, including the above copyright
  44.   notice, is not removed; and provided that no fee or other remuneration
  45.   is received for distribution.  You may add your own copyright notice
  46.   to cover new matter you add to the macro, but SemWare Corporation will
  47.   neither support nor assume legal responsibility for any material added
  48.   or any changes made to the macro.
  49.  
  50. *************************************************************************/
  51.  
  52. HelpDef ExprHelp
  53.    "The following operators are available within an Expresson:"
  54.    ""
  55.    "Operator        Meaning                     Precedence"
  56.    ""
  57.    "    ()     Sub-expression                        1"
  58.    ""
  59.    "    ~      Bitwise 2's Complement                2"
  60.    ""
  61.    "    *      Multiplication                        3"
  62.    "    /      Division                              3"
  63.    "    %      Modulo Division                       3"
  64.    "    ^      Bitwise eXclusive-OR                  3"
  65.    "    >      Bitwise Shift Right                   3"
  66.    "    <      Bitwise Shift Left                    3"
  67.    "    &      Bitwise AND                           3"
  68.    ""
  69.    "    +      Addition                              4"
  70.    "    -      Subtraction                           4"
  71.    "    |      Bitwise OR                            4"
  72.    ""
  73.    "Hex number may be entered by beginning with '0x' or"
  74.    "ending with an 'h' or '$'.  Regardless, the first"
  75.    "character _must_ be numeric."
  76.    ""
  77. end
  78.  
  79.  
  80. /*
  81.    Work variables
  82. */
  83.  
  84. string  InputLine[80]
  85. integer Col             // current column in InputLine
  86. string  Token[15]       // currently parsed token from InputLine
  87. integer symbol          // numeric "code" representing what token is
  88. string  Ch[1]           // next Char from InputLine
  89.  
  90. integer hex             // is current symbol hex? used only by GetToken/isHex
  91.  
  92. forward integer proc SimpleExpression()
  93.  
  94. proc GetNextChar()
  95.     Ch = Upper(SubStr(inputline, col, 1))
  96.     col = col + 1
  97. end
  98.  
  99. integer proc isNumeric()
  100.     return (Ch >= '0' and Ch <= '9')
  101. end
  102.  
  103. integer proc isHexChar()
  104.     if Ch >= 'A' and Ch <= 'F'
  105.         hex = TRUE
  106.         return (TRUE)
  107.     endif
  108.     return (FALSE)
  109. end
  110.  
  111. /*
  112.    These are "magic" values that GetToken will store in the global variable
  113.    symbol, to indicate what is the next item coming.
  114. */
  115. constant
  116.     symNumber           = 0,
  117.     symAddition         = 1,
  118.     symSubtraction      = 2,
  119.     symMultiplication   = 3,
  120.     symDivision         = 4,
  121.     symLeftParen        = 5,
  122.     symRightParen       = 6,
  123.     symAND              = 7,
  124.     symOR               = 8,
  125.     symXOR              = 9,
  126.     symCOMP             = 10,
  127.     symMOD              = 11,
  128.     symSHR              = 12,
  129.     symSHL              = 13,
  130.     symEndOfString      = -1,
  131.     symError            = -2
  132.  
  133. // GetToken _must_ set hex to FALSE on startup and exit.
  134. proc GetToken()
  135.     while ch == " "                     //  Skip over any leading blanks
  136.         GetNextChar()
  137.     endwhile
  138.     token = Ch
  139.     case token
  140.         when ">"      symbol = symSHR
  141.         when "<"      symbol = symSHL
  142.         when "~"      symbol = symCOMP
  143.         when "%"      symbol = symMOD
  144.         when "&"      symbol = symAND
  145.         when "|"      symbol = symOR
  146.         when "^"      symbol = symXOR
  147.         when "+"      symbol = symAddition
  148.         when "-"      symbol = symSubtraction
  149.         when "*"      symbol = symMultiplication
  150.         when "/"      symbol = symDivision
  151.         when "("      symbol = symLeftParen
  152.         when ")"      symbol = symRightParen
  153.         when ""       symbol = symEndOfString
  154.         otherwise     // if token is numeric, collect rest of digits
  155.             hex = FALSE
  156.             if not isNumeric() and not isHexChar()
  157.                 symbol = symError
  158.             else
  159.                 symbol = symNumber          // Tag this as an integer value
  160.                 GetNextChar()
  161.                 if (Ch == "X")              // Allow c-style hex strings
  162.                     hex = TRUE
  163.                     GetNextChar()
  164.                 endif
  165.                 while isNumeric() or isHexChar()
  166.                     token = token + ch
  167.                     GetNextChar()
  168.                 endwhile
  169.                 if Ch == 'H' or Ch == '$'   // Allow assembly/Turbo Pascal hex strings
  170.                     hex = TRUE
  171.                     GetNextChar()
  172.                 endif
  173.                 if hex
  174.                     token = token + 'H'
  175.                 endif
  176.             endif
  177.             hex = FALSE
  178.             return ()
  179.     endcase
  180.     GetNextChar()
  181. end
  182.  
  183. //
  184. //  Set up globals so SimpleExpression starts off on the right foot
  185. //
  186. proc SyntaxError()
  187.     Warn("Expression syntax error")
  188.     Halt
  189. end
  190.  
  191. proc ParenError()
  192.     Warn("Missing right parenthesis")
  193.     Halt
  194. end
  195.  
  196. integer proc Factor()
  197.     integer result, base = 10
  198.  
  199.     case symbol
  200.         when symNumber                  // found a number
  201.             if token[Length(token)] == 'H'
  202.                 token = substr(token, 1, Length(token) - 1)
  203.                 base = 16
  204.             endif
  205.             result = Val(token, base)            // get its value
  206.             GetToken()                       // and skip to next
  207.         when symLeftParen               // found a left paren
  208.             GetToken()                       // skip over "("
  209.             result = SimpleExpression()
  210.             if  symbol <> symRightParen      // make sure the right paren exists
  211.                 ParenError()
  212.             endif
  213.             GetToken()                       // skip over ")"
  214.         when symCOMP
  215.             GetToken()
  216.             result = ~Factor()
  217.         otherwise
  218.             SyntaxError()                 // not number or paren--error
  219.     endcase
  220.     return  (result)
  221. end
  222.  
  223. integer proc Term()
  224.     integer result, sym
  225.  
  226.     result = Factor()
  227.     while  (symbol == symMultiplication) or     // "*" sign, or
  228.            (symbol == symDivision) or           // "/" sign...
  229.            (symbol == symMOD) or                // "%" sign...
  230.            (symbol == symXOR) or                // "^" sign...
  231.            (symbol == symSHR) or                // ">" sign...
  232.            (symbol == symSHL) or                // "<" sign...
  233.            (symbol == symAND)                   // "&" sign...
  234.         sym = symbol
  235.         GetToken()                      // skip over math op
  236.         case sym
  237.             when symMultiplication
  238.                 result = result * Factor()    // multiplication
  239.             when symDivision
  240.                 result = result / Factor()    // division
  241.             when symAND
  242.                 result = result & Factor()
  243.             when symXOR
  244.                 result = result ^ Factor()
  245.             when symMOD
  246.                 result = result mod Factor()
  247.             when symSHR
  248.                 result = result shr Factor()
  249.             when symSHL
  250.                 result = result shl Factor()
  251.         endcase
  252.     endwhile
  253.     if symbol == symError
  254.         SyntaxError()
  255.     endif
  256.     return (result)
  257. end
  258.  
  259. integer proc SimpleExpression()
  260.     integer result, sym
  261.  
  262.     result = Term()
  263.     while  (symbol == symNumber     ) or       // another integer coming, or
  264.            (symbol == symOR         ) or       // "|" sign, or
  265.            (symbol == symAddition   ) or       // "+" sign, or
  266.            (symbol == symSubtraction)          // "-" sign....
  267.         sym = symbol
  268.         if sym == symNumber            // if another integer came immediately
  269.             sym = symAddition          // then default to adding
  270.         else
  271.             GetToken()                   // else skip over the math op
  272.         endif
  273.         case sym
  274.             when symAddition
  275.                 result = result + Term()
  276.             when symSubtraction
  277.                 result = result - Term()
  278.             when symOR
  279.                 result = result | Term()
  280.         endcase
  281.     endwhile
  282.     if symbol == symError
  283.         SyntaxError()
  284.     endif
  285.     return (result)
  286. end
  287.  
  288. keydef ExprHelpKey
  289.     <F1>    QuickHelp(ExprHelp)
  290. end
  291.  
  292. proc PromptStartup()
  293.     Enable(ExprHelpKey)
  294.     UnHook(PromptStartup)
  295. end
  296.  
  297. proc Main()
  298.     integer result
  299.  
  300.     loop
  301.         Hook(_PROMPT_STARTUP_, PromptStartup)
  302.         if Ask("Enter Expression: (<F1> for help)", InputLine) and Length(InputLine)
  303.         // Prime the pump...
  304.             Col   = 1
  305.             Token = ''
  306.             GetNextChar()
  307.             GetToken()
  308.  
  309.             result = SimpleExpression()
  310.             Message("The result is: ", result, " (", str(result, 16), "h)")
  311.         else
  312.             break
  313.         endif
  314.     endloop
  315. end
  316.