english: http://support.microsoft.com/kb/86688/en-us
german: http://support.microsoft.com/kb/86688/de
But can be usefull for your first steps in expression parsing
or as starting point for your own function plotter, game script engine, script language or what ever.
Joshy
Code: Select all
#ifdef __FB_WIN32__
#include "windows.bi"
#define MsgBox(msg) MessageBox(NULL, msg,"error:",0)
#else
#define MsgBox(msg) Print "error: " & msg
#endif
Dim shared e_input As String ' Expression input string.
Dim shared e_tok As String ' Current token kind.
Dim shared e_spelling As String ' Current token spelling.
Dim shared e_error As Integer ' Tells if syntax error occurred.
' e_function.
' Evaluate a function. This is a helper function to simplify
' e_prs.
Function e_function(fun As String, arg As Double) As Double
Dim n As Double
Select Case LCase$(fun)
Case "abs": n = Abs(arg)
Case "atn": n = Atn(arg)
Case "cos": n = Cos(arg)
Case "exp": n = Exp(arg)
Case "fix": n = Fix(arg)
Case "int": n = Int(arg)
Case "log": n = Log(arg)
Case "rnd": n = Rnd(arg)
Case "sgn": n = Sgn(arg)
Case "sin": n = Sin(arg)
Case "sqr": n = Sqr(arg)
Case "tan": n = Tan(arg)
Case Else
If Not e_error Then
MsgBox("undefined function '" + fun + "'")
e_error = -1
End If
End Select
e_function = n
End Function
' e_nxt
' Get the next token into e_tok and e_spelling and remove the
' token from e_input.
' This function groups the input into "words" like numbers,
' operators and function names.
Sub e_nxt()
Dim is_keyword As Integer
Dim c As String ' Current input character.
e_tok = ""
e_spelling = ""
' Skip whitespace.
Do
c = Left$(e_input, 1)
e_input = Mid$(e_input, 2)
Loop While c = " " Or c = Chr$(9) Or c = Chr$(13) Or c = Chr$(10)
Select Case LCase$(c)
' Number constant. Modify this to support hexadecimal, etc.
Case "0" To "9", "."
e_tok = "num"
Do
e_spelling = e_spelling + c
c = Left$(e_input, 1)
e_input = Mid$(e_input, 2)
Loop While (c >= "0" And c <= "9") Or c = "."
e_input = c + e_input
' Identifier or keyword.
Case "a" To "z", "_"
dim as integer is_id
e_tok = "id"
Do
e_spelling = e_spelling + c
c = LCase$(Left$(e_input, 1))
e_input = Mid$(e_input, 2)
is_id = (c >= "a" And c <= "z")
is_id = is_id Or c = "_" Or (c >= "0" And c <= "9")
Loop While is_id
e_input = c + e_input
' Check for keyword.
is_keyword = -1
Select Case LCase$(e_spelling)
Case "and"
Case "eqv"
Case "imp"
Case "mod"
Case "not"
Case "or"
Case "xor"
Case Else: is_keyword = 0
End Select
If is_keyword Then
e_tok = LCase$(e_spelling)
End If
' Check for <=, >=, <>.
Case "<", ">"
e_tok = c
c = Left$(e_input, 1)
If c = "=" Or c = ">" Then
e_tok = e_tok + c
e_input = Mid$(e_input, 2)
End If
' Single character token.
Case Else
e_tok = c
End Select
If e_spelling = "" Then
e_spelling = e_tok
End If
End Sub
' e_match
' Check the current token and skip past it.
' This function helps with syntax checking.
Sub e_match (token As String)
If Not e_error And e_tok <> token Then
MsgBox("expected " + token + ", got '" + e_spelling + "'")
e_error = -1
End If
e_nxt
End Sub
' e_prs
' Parse an expression, allowing operators of a specified
' precedence or higher. The lowest precedence is 1.
' This function gets tokens with e_nxt and recursively
' applies operator precedence rules.
Function e_prs (p As Integer) As Double
Dim n As Double ' Return value.
Dim fun As String ' Function name.
' Parse expression that begins with a token (precedence 12).
If e_tok = "num" Then
' number.
n = Val(e_spelling)
e_nxt
ElseIf e_tok = "-" Then
' unary minus.
e_nxt
n = -e_prs(11) ' Operand precedence 11.
ElseIf e_tok = "not" Then
' logical NOT.
e_nxt
n = Not e_prs(6) ' Operand precedence 6.
ElseIf e_tok = "(" Then
' parentheses.
e_nxt
n = e_prs(1)
e_match(")")
ElseIf e_tok = "id" Then
' Function call.
fun = e_spelling
e_nxt
e_match("(")
n = e_prs(1)
e_match(")")
n = e_function(fun, n)
Else
If Not e_error Then
MsgBox("syntax error, token = '" + e_spelling + "'")
e_error = -1
End If
End If
' Parse binary operators.
Do While Not e_error
If p <= 11 And e_tok = "^" Then
e_nxt: n = n ^ e_prs(12)
ElseIf p <= 10 And e_tok = "*" Then
e_nxt: n = n * e_prs(11)
ElseIf p <= 10 And e_tok = "/" Then
e_nxt: n = n / e_prs(11)
ElseIf p <= 9 And e_tok = "\" Then
e_nxt: n = n \ e_prs(10)
ElseIf p <= 8 And e_tok = "mod" Then
e_nxt: n = n Mod e_prs(9)
ElseIf p <= 7 And e_tok = "+" Then
e_nxt: n = n + e_prs(8)
ElseIf p <= 7 And e_tok = "-" Then
e_nxt: n = n - e_prs(8)
ElseIf p <= 6 And e_tok = "=" Then
e_nxt: n = n = e_prs(7)
ElseIf p <= 6 And e_tok = "<" Then
e_nxt: n = n < e_prs(7)
ElseIf p <= 6 And e_tok = ">" Then
e_nxt: n = n > e_prs(7)
ElseIf p <= 6 And e_tok = "<>" Then
e_nxt: n = n <> e_prs(7)
ElseIf p <= 6 And e_tok = "<=" Then
e_nxt: n = n <= e_prs(7)
ElseIf p <= 6 And e_tok = ">=" Then
e_nxt: n = n >= e_prs(7)
ElseIf p <= 5 And e_tok = "and" Then
e_nxt: n = n And e_prs(6)
ElseIf p <= 4 And e_tok = "or" Then
e_nxt: n = n Or e_prs(5)
ElseIf p <= 3 And e_tok = "xor" Then
e_nxt: n = n Xor e_prs(4)
ElseIf p <= 2 And e_tok = "eqv" Then
e_nxt: n = n Eqv e_prs(3)
ElseIf p <= 1 And e_tok = "imp" Then
e_nxt: n = n Imp e_prs(2)
Else
Exit Do
End If
Loop
e_prs = n
End Function
' e_eval
' Evaluate a string containing an infix numeric expression.
' If successful, return true and place result in <value>.
' This is the top-level function in the expression evaluator.
Function e_eval(ByVal s As String,byref value As Double) As Integer
' Initialize.
e_error = 0
e_input = s
e_nxt
' Evaluate.
value = e_prs(1)
' Check for unrecognized input.
If e_tok <> "" And Not e_error Then
MsgBox("syntax error, token = '" + e_spelling + "'")
e_error = -1
End If
e_eval = Not e_error
End Function
'
' main
'
dim as string Expression
dim as double Result
Expression = "1+2"
e_eval(Expression,Result)
print Expression & " = " & Result
Expression = "1+2*3"
e_eval(Expression,Result)
print Expression & " = " & Result
Expression = "(1+2)*3"
e_eval(Expression,Result)
print Expression & " = " & Result
Expression = "atn(1)*4"
e_eval(Expression,Result)
print "PI = " & Expression & " = " & Result
Expression = "abs((1+2+3) > (0+1+2)) * 100"
e_eval(Expression,Result)
print Expression & " = " & Result
sleep