This is the Superstrict version:
' calculate.string.bmx by Daniel Wooden
' email: <a href=\"mailto:dan.wooden@gmail.com\">dan.wooden@...;
'
' Simple variable stuff added by fredborg
' Keep variable names to single letters, as "x" may be confused with ie. "xx" by the evaluator
' Use FlushVariables() to reset variables.
'
SuperStrict
Const STACKSIZE:Int = 25
Global VarIndex:Int
Global VarStack:String[ STACKSIZE, 2]
Global TermsStack:String[ STACKSIZE ]
Global MulDivStack:String[ STACKSIZE ]
Global AddSubStack:String[ STACKSIZE ]
'
' Example
SetVariable("x = 10")
SetVariable("y = x*x*2")
SetVariable("z = (x+y)/2")
SetVariable("x = x+1")
Print CalculateString("x+y+z")
Print "GetVariable(~qx~q) = "+GetVariable("x")
Local Result:Int
Local M:Int = MilliSecs()
For Local i:Int = 0 To 100
CalculateString("x+y+z")
Next
result = MilliSecs() - m
Print "Time took to perform 100 calculations:" + result
'
' Verify result
Local x:Float
Local y:Float
Local z:Float
x = 10
y = x*x*2
z = (x+y)/2
x = x+1
Print x+y+z
Function SetVariable( in:String )
in = in.trim()
Local va:String = String(in[..in.Find("=")]).Trim()
Local pa:String = in[in.Find("=")+1..]
'
' Test if variable already exists
For Local i:Int = 0 Until VarIndex
If VarStack[i,0] = va
VarStack[i,1] = CalculateString( pa )
Return
EndIf
Next
'
' It's a new variable
VarStack[VarIndex,0] = va
VarStack[VarIndex,1] = CalculateString( pa )
VarIndex :+ 1
End Function
Function GetVariable:Float( in:String )
For Local i:Int = 0 Until VarIndex
If VarStack[i,0] = in Return Float(VarStack[i,1])
Next
EndFunction
Function FlushVariables()
VarIndex = 0
End Function
Function InsertVariables:String( in:String )
For Local i:Int = 0 Until VarIndex
in = in.Replace(VarStack[i,0],String(VarStack[i,1]))
Next
Return in
End Function
Function CalculateString:Float( Line:String )
Line = InsertVariables(Line)
Local AnswerLine:String = ""
Local CurrentChr:String = ""
' Remove Spaces
For Local i:Int = 0 To Line.Length
CurrentChr = Chr( Line[ i ] )
If CurrentChr <> " " Then
AnswerLine :+ CurrentChr
End If
Next
Local PointA:Int = -1
Local PointB:Int = -1
While AnswerLine.Contains( "(" )
For Local i:Int = 0 To AnswerLine.Length
CurrentChr = Chr( AnswerLine[ i ] )
If CurrentChr = "(" Then
PointA = i
ElseIf CurrentChr = ")" Then
PointB = i
End If
If PointA => 0 And PointB => 0 Then
Local A:String = Mid( AnswerLine, PointA+2, PointB-PointA-1 )
A = CalculateScope( A )
Local B:String = Mid( AnswerLine, PointA+1, PointB-PointA+1 )
AnswerLine = AnswerLine.Replace( B, A )
Exit
End If
Next
'#NextCalcStep
PointA = -1
PointB = -1
Wend
AnswerLine = CalculateScope( AnswerLine )
Return AnswerLine.ToFloat()
End Function
Function CalculateScope:Float( Line:String )
SplitTerms( Line )
CalcTerms()
Local CalcValue:Float = 0.0
For Local i:Int = 0 To STACKSIZE-1
If TermsStack[ i ] <> "" Then
If i = 0 Then
CalcValue = TermsStack[ i ].ToFloat()
ElseIf TermsStack[ i ] = "+" Then
CalcValue :+ TermsStack[ i+1 ].ToFloat()
ElseIf TermsStack[ i ] = "-" Then
CalcValue :- TermsStack[ i+1 ].ToFloat()
End If
End If
Next
For Local i:Int = 0 To STACKSIZE-1
TermsStack[ i ] = ""
MulDivStack[ i ] = ""
AddSubStack[ i ] = ""
Next
Return CalcValue
End Function
Function SplitTerms( Line:String )
Local StackIndex:Int = 0
Local Value:String = ""
Local CurrentChr:String = ""
For Local i:Int = 0 To Line.Length
CurrentChr = Chr( Line[ i ] )
If CurrentChr = "+" Or CurrentChr = "-" Then
TermsStack[ StackIndex ] = Value
StackIndex :+ 1
TermsStack[ StackIndex ] = Chr( Line[ i ] )
StackIndex :+ 1
Value = ""
ElseIf i = Line.Length
TermsStack[ StackIndex ] = Value
Else
Value :+ Chr( Line[ i ] )
End If
Next
End Function
Function CalcTerms()
For Local i:Int = 0 To STACKSIZE-1
If TermsStack[ i ] <> "+" And TermsStack[ i ] <> "-" And TermsStack[ i ] <> "" Then
TermsStack[ i ] = MulDiv( TermsStack[ i ] )
End If
Next
End Function
Function MulDiv:Float( Line:String )
Local Value:String = ""
Local CurrentChr:String = ""
Local CalcValue:Float = 0.0
Local StackIndex:Int = 0
For Local i:Int = 0 To Line.Length
CurrentChr = Chr( Line[ i ] )
If CurrentChr = "*" Or CurrentChr = "/"
MulDivStack[ StackIndex ] = Value
Value = ""
StackIndex :+ 1
MulDivStack[ StackIndex ] = CurrentChr
StackIndex :+ 1
ElseIf i = Line.Length
Value :+ CurrentChr
MulDivStack[ StackIndex ] = Value
Else
Value :+ CurrentChr
End If
Next
For Local i:Int = 0 To STACKSIZE-1
If MulDivStack[ i ] <> "" Then
If i = 0 Then
CalcValue = MulDivStack[ i ].ToFloat()
ElseIf MulDivStack[ i ] = "*" Then
CalcValue :* MulDivStack[ i+1 ].ToFloat()
ElseIf MulDivStack[ i ] = "/" Then
CalcValue :/ MulDivStack[ i+1 ].ToFloat()
End If
End If
Next
Return CalcValue
End Function
|