home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- Expr Calculates the value of a specified mathematical expression.
-
- Author: SemWare
-
- Date: Mar 23, 1994
-
- Overview:
-
- This macro operates as a simple calculator, and handles decimal
- or hexadecimal numbers. For decimal numbers, only whole numbers
- are accepted.
-
- Keys: (none)
-
- Usage notes:
-
- This macro does not have any key assignments. To use, simply
- select it from the Potpourri menu.
-
- The following operations are available:
-
- > SHR (bitwise shift right)
- < SHL (bitwise shift left)
- ~ COMP (2's complement)
- % MOD (modulo division)
- & AND (bitwise AND)
- | OR (bitwise OR)
- ^ XOR (bitwise eXclusive-OR)
- + Addition
- - Subtraction
- * Multiplication
- / Division
-
- Precedence is as in SAL, but can be forced by using parenthesis.
-
- Hex number may be entered using C format, or ending with an 'h'
- or '$'. Regardless, the first character _must_ be numeric.
-
- Copyright 1992-1994 SemWare Corporation. All Rights Reserved Worldwide.
-
- Use, modification, and distribution of this SAL macro is encouraged by
- SemWare provided that this statement, including the above copyright
- notice, is not removed; and provided that no fee or other remuneration
- is received for distribution. You may add your own copyright notice
- to cover new matter you add to the macro, but SemWare Corporation will
- neither support nor assume legal responsibility for any material added
- or any changes made to the macro.
-
- *************************************************************************/
-
- HelpDef ExprHelp
- "The following operators are available within an Expresson:"
- ""
- "Operator Meaning Precedence"
- ""
- " () Sub-expression 1"
- ""
- " ~ Bitwise 2's Complement 2"
- ""
- " * Multiplication 3"
- " / Division 3"
- " % Modulo Division 3"
- " ^ Bitwise eXclusive-OR 3"
- " > Bitwise Shift Right 3"
- " < Bitwise Shift Left 3"
- " & Bitwise AND 3"
- ""
- " + Addition 4"
- " - Subtraction 4"
- " | Bitwise OR 4"
- ""
- "Hex number may be entered by beginning with '0x' or"
- "ending with an 'h' or '$'. Regardless, the first"
- "character _must_ be numeric."
- ""
- end
-
-
- /*
- Work variables
- */
-
- string InputLine[80]
- integer Col // current column in InputLine
- string Token[15] // currently parsed token from InputLine
- integer symbol // numeric "code" representing what token is
- string Ch[1] // next Char from InputLine
-
- integer hex // is current symbol hex? used only by GetToken/isHex
-
- forward integer proc SimpleExpression()
-
- proc GetNextChar()
- Ch = Upper(SubStr(inputline, col, 1))
- col = col + 1
- end
-
- integer proc isNumeric()
- return (Ch >= '0' and Ch <= '9')
- end
-
- integer proc isHexChar()
- if Ch >= 'A' and Ch <= 'F'
- hex = TRUE
- return (TRUE)
- endif
- return (FALSE)
- end
-
- /*
- These are "magic" values that GetToken will store in the global variable
- symbol, to indicate what is the next item coming.
- */
- constant
- symNumber = 0,
- symAddition = 1,
- symSubtraction = 2,
- symMultiplication = 3,
- symDivision = 4,
- symLeftParen = 5,
- symRightParen = 6,
- symAND = 7,
- symOR = 8,
- symXOR = 9,
- symCOMP = 10,
- symMOD = 11,
- symSHR = 12,
- symSHL = 13,
- symEndOfString = -1,
- symError = -2
-
- // GetToken _must_ set hex to FALSE on startup and exit.
- proc GetToken()
- while ch == " " // Skip over any leading blanks
- GetNextChar()
- endwhile
- token = Ch
- case token
- when ">" symbol = symSHR
- when "<" symbol = symSHL
- when "~" symbol = symCOMP
- when "%" symbol = symMOD
- when "&" symbol = symAND
- when "|" symbol = symOR
- when "^" symbol = symXOR
- when "+" symbol = symAddition
- when "-" symbol = symSubtraction
- when "*" symbol = symMultiplication
- when "/" symbol = symDivision
- when "(" symbol = symLeftParen
- when ")" symbol = symRightParen
- when "" symbol = symEndOfString
- otherwise // if token is numeric, collect rest of digits
- hex = FALSE
- if not isNumeric() and not isHexChar()
- symbol = symError
- else
- symbol = symNumber // Tag this as an integer value
- GetNextChar()
- if (Ch == "X") // Allow c-style hex strings
- hex = TRUE
- GetNextChar()
- endif
- while isNumeric() or isHexChar()
- token = token + ch
- GetNextChar()
- endwhile
- if Ch == 'H' or Ch == '$' // Allow assembly/Turbo Pascal hex strings
- hex = TRUE
- GetNextChar()
- endif
- if hex
- token = token + 'H'
- endif
- endif
- hex = FALSE
- return ()
- endcase
- GetNextChar()
- end
-
- //
- // Set up globals so SimpleExpression starts off on the right foot
- //
- proc SyntaxError()
- Warn("Expression syntax error")
- Halt
- end
-
- proc ParenError()
- Warn("Missing right parenthesis")
- Halt
- end
-
- integer proc Factor()
- integer result, base = 10
-
- case symbol
- when symNumber // found a number
- if token[Length(token)] == 'H'
- token = substr(token, 1, Length(token) - 1)
- base = 16
- endif
- result = Val(token, base) // get its value
- GetToken() // and skip to next
- when symLeftParen // found a left paren
- GetToken() // skip over "("
- result = SimpleExpression()
- if symbol <> symRightParen // make sure the right paren exists
- ParenError()
- endif
- GetToken() // skip over ")"
- when symCOMP
- GetToken()
- result = ~Factor()
- otherwise
- SyntaxError() // not number or paren--error
- endcase
- return (result)
- end
-
- integer proc Term()
- integer result, sym
-
- result = Factor()
- while (symbol == symMultiplication) or // "*" sign, or
- (symbol == symDivision) or // "/" sign...
- (symbol == symMOD) or // "%" sign...
- (symbol == symXOR) or // "^" sign...
- (symbol == symSHR) or // ">" sign...
- (symbol == symSHL) or // "<" sign...
- (symbol == symAND) // "&" sign...
- sym = symbol
- GetToken() // skip over math op
- case sym
- when symMultiplication
- result = result * Factor() // multiplication
- when symDivision
- result = result / Factor() // division
- when symAND
- result = result & Factor()
- when symXOR
- result = result ^ Factor()
- when symMOD
- result = result mod Factor()
- when symSHR
- result = result shr Factor()
- when symSHL
- result = result shl Factor()
- endcase
- endwhile
- if symbol == symError
- SyntaxError()
- endif
- return (result)
- end
-
- integer proc SimpleExpression()
- integer result, sym
-
- result = Term()
- while (symbol == symNumber ) or // another integer coming, or
- (symbol == symOR ) or // "|" sign, or
- (symbol == symAddition ) or // "+" sign, or
- (symbol == symSubtraction) // "-" sign....
- sym = symbol
- if sym == symNumber // if another integer came immediately
- sym = symAddition // then default to adding
- else
- GetToken() // else skip over the math op
- endif
- case sym
- when symAddition
- result = result + Term()
- when symSubtraction
- result = result - Term()
- when symOR
- result = result | Term()
- endcase
- endwhile
- if symbol == symError
- SyntaxError()
- endif
- return (result)
- end
-
- keydef ExprHelpKey
- <F1> QuickHelp(ExprHelp)
- end
-
- proc PromptStartup()
- Enable(ExprHelpKey)
- UnHook(PromptStartup)
- end
-
- proc Main()
- integer result
-
- loop
- Hook(_PROMPT_STARTUP_, PromptStartup)
- if Ask("Enter Expression: (<F1> for help)", InputLine) and Length(InputLine)
- // Prime the pump...
- Col = 1
- Token = ''
- GetNextChar()
- GetToken()
-
- result = SimpleExpression()
- Message("The result is: ", result, " (", str(result, 16), "h)")
- else
- break
- endif
- endloop
- end
-