Matheparser

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Noobody

Betreff: Matheparser

BeitragSo, Jun 28, 2009 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie der Titel schon andeutet, habe ich im Laufe der vergangenen Woche einen Algorithmus programmiert, der mathematische Ausdrücke, die als String vorliegen, berechnet (beispielsweise "4+2*3"). Er beherrscht die mathematischen Grundrechenarten Addition, Subtraktion, Multiplikation und Division, sowie Potenzrechnung (z.B. "4^3") und boolsche Operatoren ("23 >= 22").
Selbstverständlich können auch beliebig verschachtelte Klammern verwendet werden.

Das Rechensystem arbeitet der Genauigkeit zuliebe grundsätzlich mit Integern. Taucht aber im Term irgendwo eine Float - Zahl auf, wird von dort an mit Floats gerechnet.
Beispielsweise würde "3+24/5-6^2" ein Integer - Resultat liefern, "3+24/5.-6^2" hingegen liefert ein Float - Resultat.

Desweiteren beherrscht der Rechner Variablen, eine Berechnung der Form "(X/25.)^Variable" ist also ohne weiteres möglich. Der Wert der Variablen kann vor jeder Berechnung neu gesetzt werden, zusammen mit ihrem Typ (Int oder Float). Falls kein Wert gesetzt wurde, haben Variablen standardmässig den Typ Int und den Wert 0.

Die Bedienung gestaltet sich denkbar einfach:
Ein neuer Term wird durch TTerm.Tokenize erstellt; übergeben wird dabei der mathematische Ausdruck und zurückgeliefert wird ein TTerm - Objekt.
Durch die Methode Calculate berechnet das Objekt den mathematischen Ausdruck und liefert dabei entweder TTerm.SYM_INTEGER oder TTerm.SYM_FLOAT zurück - je nach dem, ob das Ergebnis ein Integer oder ein Float ist. Das Ergebnis kann dann in den Feldern ResultInt bzw. ResultFloat abgeholt werden.
Wert und Typ von Variablen lassen sich durch die Methoden SetInt bzw. SetFloat setzen. Der erste Parameter ist dabei der Name der Variable, der zweite Parameter der Wert, der der Variable zugewiesen werden soll. Man sollte dabei beachten, dass Variablen case sensitive sind - "Foo" und "foo" sind also nicht dasselbe!

Das erste Beispiel zeigt die grundlegende Verwendung sowie die Unterscheidung von Int bzw. Float - Resultaten Code: [AUSKLAPPEN]
SuperStrict

Local Term:TTerm = TTerm.Tokenize( "-( ( 2*4^3 > 0 )*34 + 1/( IntVariable - 3*FloatVariable ) + Pi*100 )" )

Term.SetInt( "IntVariable", 25 )
Term.SetFloat( "Pi", 3.14159 )
Term.SetFloat( "FloatVariable", 0.154 )

PrintResult( Term ) 'Das Resultat wird ein Float sein, da sowohl Pi als auch FloatVariable als Float festgelegt wurden

Term.SetInt( "IntVariable", 25 )
Term.SetInt( "Pi", 3 )
Term.SetInt( "FloatVariable", 1 ) 'Wenn man nun alle Variablen als Int festsetzt und im Term selbst keine Dezimalzahlen vorkommen, wird nur mit Ints gerechnet

PrintResult( Term ) 'Das Resultat wird also ein Integer sein

Term.PrintPrefixNotation() 'Um das ganze zu veranschaulichen, wird der Term in der erzeugten Präfixnotation ausgegeben.

End


Function PrintResult( Term:TTerm ) 'Beispielsfunktion, die einen Term ausrechnen lässt und das Resultat auswertet
   Local ResultType:Int = Term.Calculate()
   
   If ResultType = TTerm.SYM_INTEGER Then
      Print "Integer result: " + Term.ResultInt
   Else
      Print "Float result: " + Term.ResultFloat
   EndIf
End Function

'------------------------------------------------------------------------------

Type TTerm
   Const SYM_PLUS:Int      = 1
   Const SYM_MINUS:Int      = 2
   Const SYM_TIMES:Int      = 3
   Const SYM_DIVIDE:Int      = 4
   Const SYM_POWEROF:Int      = 5
   Const SYM_LEFTPARAN:Int   = 6
   Const SYM_RIGHTPARAN:Int   = 7
   Const SYM_GREATER:Int      = 8
   Const SYM_SMALLER:Int      = 9
   Const SYM_EQUAL:Int      = 10
   Const SYM_GREATEREQUAL:Int   = 11
   Const SYM_SMALLEREQUAL:Int   = 12
   
   Const SYM_INTEGER:Int      = 128
   Const SYM_FLOAT:Int      = 129
   Const SYM_OPERATOR:Int      = 130
   Const SYM_IDENTIFIER:Int   = 131
   
   Global Precedence:Int[] = [ SYM_GREATER, SYM_SMALLER, SYM_EQUAL, SYM_GREATEREQUAL, SYM_SMALLEREQUAL, SYM_PLUS, SYM_MINUS, SYM_TIMES, SYM_DIVIDE, SYM_POWEROF ]
   
   Field TermPos:Int
   Field TermPrefix:Int[ 1024 ]
   
   Field TermIdentifier:String[ 64 ]
   Field TermIdentValue:Int[ 64, 2 ]
   
   Field ResultInt:Int
   Field ResultFloat:Float
   
   Function Tokenize:TTerm( SourceTerm:String )
      Local Term:TTerm = New TTerm
      
      Local SymbolIndex:Int, StringIndex:Int
      Local TermSymbol:Int[ 1024 ]
      
      While Term.TermPos < SourceTerm.Length
         Local SymbolType:Int = Term.GetSymbol( SourceTerm )
         
         TermSymbol[ SymbolIndex ] = SymbolType
         SymbolIndex :+ 1
         
         If SymbolType = SYM_INTEGER Then
            TermSymbol[ SymbolIndex ] = Term.GetInteger( SourceTerm )
            
            SymbolIndex :+ 1
         ElseIf SymbolType = SYM_FLOAT Then
            TermSymbol[ SymbolIndex ] = FloatToInt( Term.GetFloat( SourceTerm ) )
            
            SymbolIndex :+ 1
         ElseIf SymbolType = SYM_IDENTIFIER Then
            TermSymbol[ SymbolIndex ] = StringIndex
            Term.TermIdentifier[ StringIndex ] = Term.GetIdentifier( SourceTerm )
            Term.TermIdentValue[ StringIndex, 0 ] = SYM_INTEGER
            
            SymbolIndex :+ 1
            StringIndex :+ 1
         ElseIf SymbolIndex = 1 Or TermSymbol[ SymbolIndex - 2 ] = SYM_LEFTPARAN Then
            If SymbolType = SYM_MINUS Then 'Unäres Minus/Plus abfangen - führt sonst zur Endlosrekursion
               TermSymbol[ SymbolIndex - 1 ] = SYM_INTEGER
               TermSymbol[ SymbolIndex + 0 ] = 0
               TermSymbol[ SymbolIndex + 1 ] = SYM_MINUS
               
               SymbolIndex :+ 2
            ElseIf SymbolType = SYM_PLUS Then
               SymbolIndex :- 1
            EndIf
         EndIf
      Wend
      
      TermSymbol = TermSymbol[ .. SymbolIndex ]
      
      Term.TermPrefix = Term.ParseSymbols( TermSymbol )
      
      Return Term
   End Function
   
   Method ParseSymbols:Int[]( Symbols:Int[] )
      Local Prefix:Int[]
      
      For Local i:Int = 0 To Precedence.Length - 1
         Local Index:Int = FindSymbol( Symbols, Precedence[ i ] )
         
         If Index >= 0 Then
            Local Operand1:Int[] = Self.ParseSymbols( Symbols[ .. Index ] )
            Local Operand2:Int[] = Self.ParseSymbols( Symbols[ Index + 1 .. ] )
            
            Prefix = [ Precedence[ i ] ] + Operand1 + Operand2
            
            Symbols = Symbols[ Index + 1 + Operand2.Length .. ]
            
            Exit
         ElseIf i = Precedence.Length - 1
            If Symbols[ 0 ] = SYM_LEFTPARAN Then
               Return Self.ParseSymbols( Symbols[ 1 .. Symbols.Length - 1 ] )
            Else
               Return Symbols
            EndIf
         EndIf
      Next
      
      Return Prefix
   End Method
   
   Method GetSymbol:Int( SourceTerm:String )
      Local Char:String = Self.GetNextChar( SourceTerm )
      
      While Char = " "
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Select Char
         Case "+"
            Return SYM_PLUS
         Case "-"
            Return SYM_MINUS
         Case "*"
            Return SYM_TIMES
         Case "/"
            Return SYM_DIVIDE
         Case "("
            Return SYM_LEFTPARAN
         Case ")"
            Return SYM_RIGHTPARAN
         Case "^"
            Return SYM_POWEROF
         Case ">"
            If Self.GetNextChar( SourceTerm ) = "=" Then
               Return SYM_GREATEREQUAL
            Else
               Self.TermPos :- 1
               Return SYM_GREATER
            EndIf
         Case "<"
            If Self.GetNextChar( SourceTerm ) = "=" Then
               Return SYM_SMALLEREQUAL
            Else
               Self.TermPos :- 1
               Return SYM_SMALLER
            EndIf
         Case "="
            Select Self.GetNextChar( SourceTerm )
               Case ">"
                  Return SYM_GREATEREQUAL
               Case "<"
                  Return SYM_SMALLEREQUAL
               Default
                  Self.TermPos :- 1
                  Return SYM_EQUAL
            End Select
         Default
            Self.TermPos :- 1
            
            If IsChar( Char ) Then Return SYM_IDENTIFIER
            
            If IsDigit( Char ) Then
               If Self.CheckForFloat( SourceTerm ) Then
                  Return SYM_FLOAT
               Else
                  Return SYM_INTEGER
               EndIf
            EndIf
      End Select
   End Method
   
   Method GetIdentifier:String( SourceTerm:String )
      Local Output:String, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsChar( Char ) Or IsDigit( Char )
         Output = Output + Char
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetInteger:Int( SourceTerm:String )
      Local Output:Int, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Output = Output*10 + Char.ToInt()
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetFloat:Float( SourceTerm:String )
      Local Output:Float, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Output = Output*10 + Char.ToInt()
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Local Exponent:Float = 1
      While IsDigit( Char ) Or Char = "."
         Output = Output + Char.ToInt()*Exponent
         Exponent :/ 10
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetNextChar:String( SourceTerm:String )
      Local Char:String = SourceTerm[ Self.TermPos .. Self.TermPos + 1 ]
      Self.TermPos :+ 1
      
      Return Char
   End Method
   
   Method SetInt( Identifier:String, Value:Int )
      For Local i:Int = 0 To Self.TermIdentifier.Length - 1
         If Self.TermIdentifier[ i ] = Identifier Then
            Self.TermIdentValue[ i, 0 ] = SYM_INTEGER
            Self.TermIdentValue[ i, 1 ] = Value
            Return
         EndIf
      Next
      
      Throw "Identifier '" + Identifier + "' not contained in this term"
   End Method
   
   Method SetFloat( Identifier:String, Value:Float )
      For Local i:Int = 0 To Self.TermIdentifier.Length - 1
         If Self.TermIdentifier[ i ] = Identifier Then
            Self.TermIdentValue[ i, 0 ] = SYM_FLOAT
            Self.TermIdentValue[ i, 1 ] = FloatToInt( Value )
            Return
         EndIf
      Next
      
      Throw "Identifier '" + Identifier + "' not contained in this term"
   End Method
   
   Method CheckForFloat:Int( SourceTerm:String )
      Local OldPos:Int = Self.TermPos, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos = OldPos
      
      If Char = "." Then Return True Else Return False
   End Method
   
   Method Calculate:Int()
      Local Stack:Int[ 128 ], StackPointer:Int, OperandCount:Int
      
      Self.ResultInt = 0
      Self.ResultFloat = 0
      
      For Local i:Int = 0 To Self.TermPrefix.Length - 1
         If IsTerminal( Self.TermPrefix[ i ] ) Then
            OperandCount :+ 1
            
            If Self.TermPrefix[ i ] = SYM_INTEGER Or Self.TermPrefix[ i ] = SYM_FLOAT Then
               Stack[ StackPointer + 1 ] = Self.TermPrefix[ i + 1 ]
               Stack[ StackPointer ] = Self.TermPrefix[ i ]
            ElseIf Self.TermPrefix[ i ] = SYM_IDENTIFIER Then
               Stack[ StackPointer + 1 ] = Self.TermIdentValue[ Self.TermPrefix[ i + 1 ], 1 ]
               Stack[ StackPointer ] = Self.TermIdentValue[ Self.TermPrefix[ i + 1 ], 0 ]
            EndIf
            
            i :+ 1
            
            While OperandCount = 2
               Local SP:Int = StackPointer, ResultType:Int = SYM_INTEGER
               
               Select Stack[ StackPointer - 3 ]
                  Case SYM_PLUS
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] + Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) + Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] + IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) + IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_MINUS
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] - Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) - Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] - IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) - IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_TIMES
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] * Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) * Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] * IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) * IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_DIVIDE
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] / Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) / Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] / IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) / IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_POWEROF
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] ^ Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) ^ Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] ^ IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) ^ IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_GREATER
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] > Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) > Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] > IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) > IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_SMALLER
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] < Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) < Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] < IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) < IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_EQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] = Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) = Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] = IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) = IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_GREATEREQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] >= Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) >= Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] >= IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) >= IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_SMALLEREQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] <= Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) <= Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] <= IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) <= IntToFloat( Stack[ SP + 1 ] ) )
               End Select
               
               If Stack[ StackPointer ] = SYM_FLOAT Or Stack[ StackPointer - 2 ] = SYM_FLOAT Then
                  Stack[ StackPointer - 4 ] = SYM_FLOAT
               Else
                  Stack[ StackPointer - 4 ] = SYM_INTEGER
               EndIf
               
               StackPointer :- 4
               
               If StackPointer >= 2 And IsTerminal( Stack[ StackPointer - 2 ] ) Then OperandCount = 2 Else OperandCount = 1
            Wend
            
            StackPointer :+ 2
         Else
            Stack[ StackPointer ] = SYM_OPERATOR
            Stack[ StackPointer + 1 ] = Self.TermPrefix[ i ]
            StackPointer :+ 2
            OperandCount = 0
         EndIf
      Next
      
      If Stack[ 0 ] = SYM_INTEGER Then
         Self.ResultInt = Stack[ 1 ]
      Else
         Self.ResultFloat = IntToFloat( Stack[ 1 ] )
      EndIf
      
      Return Stack[ 0 ]
   End Method
   
   Function IsDigit:Int( Char:String )
      If Asc( Char ) >= 48 And Asc( Char ) <= 57 Then Return True
   End Function
   
   Function IsChar:Int( Char:String )
      If Asc( Char ) >=65 And Asc( Char ) <= 90 Then Return True
      If Asc( Char ) >=97 And Asc( Char ) <= 122 Then Return True
   End Function
   
   Function IsTerminal:Int( Symbol:Int )
      If Symbol = SYM_INTEGER Or Symbol = SYM_FLOAT Or Symbol = SYM_IDENTIFIER Then Return True
   End Function
   
   Function FindSymbol:Int( Symbols:Int[], SoughtSymbol:Int, StartIndex:Int = 0 )
      Local NestLevel:Int
      For Local i:Int = StartIndex To Symbols.Length - 1
         If Symbols[ i ] = SoughtSymbol And NestLevel = 0 Then
            Return i
         ElseIf IsTerminal( Symbols[ i ] ) Then
            i :+ 1
         ElseIf Symbols[ i ] = SYM_LEFTPARAN
            NestLevel :+ 1
         ElseIf Symbols[ i ] = SYM_RIGHTPARAN
            NestLevel :- 1
            If NestLevel < 0 Then Return -1
         EndIf
      Next
      
      Return -1
   End Function
   
   Function FloatToInt:Int( Source:Float )
      Return ( Int Ptr ( Varptr Source ) )[ 0 ]
   End Function

   Function IntToFloat:Float( Source:Int )
      Return ( Float Ptr ( Varptr Source ) )[ 0 ]
   End Function
   
   Method PrintPrefixNotation()
      For Local i:Int = 0 To Self.TermPrefix.Length - 1
         Select Self.TermPrefix[ i ]
            Case SYM_PLUS
               WriteStdout "+ "
            Case SYM_MINUS
               WriteStdout "- "
            Case SYM_TIMES
               WriteStdout "* "
            Case SYM_DIVIDE
               WriteStdout "/ "
            Case SYM_LEFTPARAN
               WriteStdout "( "
            Case SYM_RIGHTPARAN
               WriteStdout ") "
            Case SYM_POWEROF
               WriteStdout "^ "
            Case SYM_GREATER
               WriteStdout "> "
            Case SYM_SMALLER
               WriteStdout "< "
            Case SYM_EQUAL
               WriteStdout "= "
            Case SYM_GREATEREQUAL
               WriteStdout ">= "
            Case SYM_SMALLEREQUAL
               WriteStdout "<= "
            Case SYM_INTEGER
               i :+ 1
               WriteStdout Self.TermPrefix[ i ] + " "
            Case SYM_FLOAT
               i :+ 1
               WriteStdout IntToFloat( Self.TermPrefix[ i ] ) + " "
            Case SYM_IDENTIFIER
               i :+ 1
               WriteStdout Self.TermIdentifier[ Self.TermPrefix[ i ] ] + " "
         End Select
      Next
      
      Print ""
   End Method
End Type


Das zweite Beispiel macht einen kleinen Stresstest und zeichnet vier verschiedene Graphen mithilfe des Termsystems Code: [AUSKLAPPEN]
SuperStrict

Const GWIDTH:Int = 800
Const GHEIGHT:Int = 600

Graphics GWIDTH, GHEIGHT, 0, 2

Local Graph1:TTerm = TTerm.Tokenize( "-(((X-400)*Scale)^2-300)" ) 'Quadratische Funktion (x^2)
Local Graph2:TTerm = TTerm.Tokenize( "-(1/((X-400)*Scale)-300)" ) 'Reziproke Funktion (1/x)
Local Graph3:TTerm = TTerm.Tokenize( "-(2^((X-400)*Scale)-300)" ) 'Exponentielle Funktion (2^x)
Local Graph4:TTerm = TTerm.Tokenize( "-200*(X<=(800/2))+400" ) 'Boolsche Funktion (x<=400)

Graph1.SetFloat( "Scale", 0.05 )
Graph2.SetFloat( "Scale", 0.0001 )
Graph3.SetFloat( "Scale", 0.03 )

Local Timer:TTimer = CreateTimer( 60 )

While Not KeyHit( KEY_ESCAPE )
   Cls
   
   Local Counter:Int = MilliSecs()
   
   PlotGraph( Graph1, 5, 255, 0, 0 )
   PlotGraph( Graph2, 5, 0, 255, 0 )
   PlotGraph( Graph3, 5, 0, 0, 255 )
   PlotGraph( Graph4, 5, 255, 255, 0 )
   
   SetColor 255, 255, 255
   DrawText "Render/Rechenzeit: " + ( MilliSecs() - Counter ), 0, 0
   
   Flip 0
   WaitTimer Timer
Wend

Function PlotGraph( Term:TTerm, DrawStep:Int = 5, R:Int = 255, G:Int = 255, B:Int = 255 ) 'Beispielsfunktion, die einen Graph zeichnet
   Local OldY:Float, CurrentY:Float
   
   SetColor R, G, B
   
   For Local X:Int = 0 To GWIDTH/DrawStep
      Term.SetFloat( "X", X*DrawStep )
      
      Local ResultType:Int = Term.Calculate()
      
      If ResultType = TTerm.SYM_INTEGER
         CurrentY = Term.ResultInt
      Else
         CurrentY = Term.ResultFloat
      EndIf
      
      If X > 0 Then DrawLine ( X - 1 )*DrawStep, OldY, X*DrawStep, CurrentY
      
      OldY = CurrentY
   Next
End Function

'----------------------------------------------------------------------------

Type TTerm
   Const SYM_PLUS:Int      = 1
   Const SYM_MINUS:Int      = 2
   Const SYM_TIMES:Int      = 3
   Const SYM_DIVIDE:Int      = 4
   Const SYM_POWEROF:Int      = 5
   Const SYM_LEFTPARAN:Int   = 6
   Const SYM_RIGHTPARAN:Int   = 7
   Const SYM_GREATER:Int      = 8
   Const SYM_SMALLER:Int      = 9
   Const SYM_EQUAL:Int      = 10
   Const SYM_GREATEREQUAL:Int   = 11
   Const SYM_SMALLEREQUAL:Int   = 12
   
   Const SYM_INTEGER:Int      = 128
   Const SYM_FLOAT:Int      = 129
   Const SYM_OPERATOR:Int      = 130
   Const SYM_IDENTIFIER:Int   = 131
   
   Global Precedence:Int[] = [ SYM_GREATER, SYM_SMALLER, SYM_EQUAL, SYM_GREATEREQUAL, SYM_SMALLEREQUAL, SYM_PLUS, SYM_MINUS, SYM_TIMES, SYM_DIVIDE, SYM_POWEROF ]
   
   Field TermPos:Int
   Field TermPrefix:Int[ 1024 ]
   
   Field TermIdentifier:String[ 64 ]
   Field TermIdentValue:Int[ 64, 2 ]
   
   Field ResultInt:Int
   Field ResultFloat:Float
   
   Function Tokenize:TTerm( SourceTerm:String )
      Local Term:TTerm = New TTerm
      
      Local SymbolIndex:Int, StringIndex:Int
      Local TermSymbol:Int[ 1024 ]
      
      While Term.TermPos < SourceTerm.Length
         Local SymbolType:Int = Term.GetSymbol( SourceTerm )
         
         TermSymbol[ SymbolIndex ] = SymbolType
         SymbolIndex :+ 1
         
         If SymbolType = SYM_INTEGER Then
            TermSymbol[ SymbolIndex ] = Term.GetInteger( SourceTerm )
            
            SymbolIndex :+ 1
         ElseIf SymbolType = SYM_FLOAT Then
            TermSymbol[ SymbolIndex ] = FloatToInt( Term.GetFloat( SourceTerm ) )
            
            SymbolIndex :+ 1
         ElseIf SymbolType = SYM_IDENTIFIER Then
            TermSymbol[ SymbolIndex ] = StringIndex
            Term.TermIdentifier[ StringIndex ] = Term.GetIdentifier( SourceTerm )
            Term.TermIdentValue[ StringIndex, 0 ] = SYM_INTEGER
            
            SymbolIndex :+ 1
            StringIndex :+ 1
         ElseIf SymbolIndex = 1 Or TermSymbol[ SymbolIndex - 2 ] = SYM_LEFTPARAN Then
            If SymbolType = SYM_MINUS Then 'Unäres Minus/Plus abfangen - führt sonst zur Endlosrekursion
               TermSymbol[ SymbolIndex - 1 ] = SYM_INTEGER
               TermSymbol[ SymbolIndex + 0 ] = 0
               TermSymbol[ SymbolIndex + 1 ] = SYM_MINUS
               
               SymbolIndex :+ 2
            ElseIf SymbolType = SYM_PLUS Then
               SymbolIndex :- 1
            EndIf
         EndIf
      Wend
      
      TermSymbol = TermSymbol[ .. SymbolIndex ]
      
      Term.TermPrefix = Term.ParseSymbols( TermSymbol )
      
      Return Term
   End Function
   
   Method ParseSymbols:Int[]( Symbols:Int[] )
      Local Prefix:Int[]
      
      For Local i:Int = 0 To Precedence.Length - 1
         Local Index:Int = FindSymbol( Symbols, Precedence[ i ] )
         
         If Index >= 0 Then
            Local Operand1:Int[] = Self.ParseSymbols( Symbols[ .. Index ] )
            Local Operand2:Int[] = Self.ParseSymbols( Symbols[ Index + 1 .. ] )
            
            Prefix = [ Precedence[ i ] ] + Operand1 + Operand2
            
            Symbols = Symbols[ Index + 1 + Operand2.Length .. ]
            
            Exit
         ElseIf i = Precedence.Length - 1
            If Symbols[ 0 ] = SYM_LEFTPARAN Then
               Return Self.ParseSymbols( Symbols[ 1 .. Symbols.Length - 1 ] )
            Else
               Return Symbols
            EndIf
         EndIf
      Next
      
      Return Prefix
   End Method
   
   Method GetSymbol:Int( SourceTerm:String )
      Local Char:String = Self.GetNextChar( SourceTerm )
      
      While Char = " "
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Select Char
         Case "+"
            Return SYM_PLUS
         Case "-"
            Return SYM_MINUS
         Case "*"
            Return SYM_TIMES
         Case "/"
            Return SYM_DIVIDE
         Case "("
            Return SYM_LEFTPARAN
         Case ")"
            Return SYM_RIGHTPARAN
         Case "^"
            Return SYM_POWEROF
         Case ">"
            If Self.GetNextChar( SourceTerm ) = "=" Then
               Return SYM_GREATEREQUAL
            Else
               Self.TermPos :- 1
               Return SYM_GREATER
            EndIf
         Case "<"
            If Self.GetNextChar( SourceTerm ) = "=" Then
               Return SYM_SMALLEREQUAL
            Else
               Self.TermPos :- 1
               Return SYM_SMALLER
            EndIf
         Case "="
            Select Self.GetNextChar( SourceTerm )
               Case ">"
                  Return SYM_GREATEREQUAL
               Case "<"
                  Return SYM_SMALLEREQUAL
               Default
                  Self.TermPos :- 1
                  Return SYM_EQUAL
            End Select
         Default
            Self.TermPos :- 1
            
            If IsChar( Char ) Then Return SYM_IDENTIFIER
            
            If IsDigit( Char ) Then
               If Self.CheckForFloat( SourceTerm ) Then
                  Return SYM_FLOAT
               Else
                  Return SYM_INTEGER
               EndIf
            EndIf
      End Select
   End Method
   
   Method GetIdentifier:String( SourceTerm:String )
      Local Output:String, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsChar( Char ) Or IsDigit( Char )
         Output = Output + Char
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetInteger:Int( SourceTerm:String )
      Local Output:Int, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Output = Output*10 + Char.ToInt()
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetFloat:Float( SourceTerm:String )
      Local Output:Float, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Output = Output*10 + Char.ToInt()
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Local Exponent:Float = 1
      While IsDigit( Char ) Or Char = "."
         Output = Output + Char.ToInt()*Exponent
         Exponent :/ 10
         
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos :- 1
      
      Return Output
   End Method
   
   Method GetNextChar:String( SourceTerm:String )
      Local Char:String = SourceTerm[ Self.TermPos .. Self.TermPos + 1 ]
      Self.TermPos :+ 1
      
      Return Char
   End Method
   
   Method SetInt( Identifier:String, Value:Int )
      For Local i:Int = 0 To Self.TermIdentifier.Length - 1
         If Self.TermIdentifier[ i ] = Identifier Then
            Self.TermIdentValue[ i, 0 ] = SYM_INTEGER
            Self.TermIdentValue[ i, 1 ] = Value
            Return
         EndIf
      Next
      
      Throw "Identifier '" + Identifier + "' not contained in this term"
   End Method
   
   Method SetFloat( Identifier:String, Value:Float )
      For Local i:Int = 0 To Self.TermIdentifier.Length - 1
         If Self.TermIdentifier[ i ] = Identifier Then
            Self.TermIdentValue[ i, 0 ] = SYM_FLOAT
            Self.TermIdentValue[ i, 1 ] = FloatToInt( Value )
            Return
         EndIf
      Next
      
      Throw "Identifier '" + Identifier + "' not contained in this term"
   End Method
   
   Method CheckForFloat:Int( SourceTerm:String )
      Local OldPos:Int = Self.TermPos, Char:String = Self.GetNextChar( SourceTerm )
      
      While IsDigit( Char )
         Char = Self.GetNextChar( SourceTerm )
      Wend
      
      Self.TermPos = OldPos
      
      If Char = "." Then Return True Else Return False
   End Method
   
   Method Calculate:Int()
      Local Stack:Int[ 128 ], StackPointer:Int, OperandCount:Int
      
      Self.ResultInt = 0
      Self.ResultFloat = 0
      
      For Local i:Int = 0 To Self.TermPrefix.Length - 1
         If IsTerminal( Self.TermPrefix[ i ] ) Then
            OperandCount :+ 1
            
            If Self.TermPrefix[ i ] = SYM_INTEGER Or Self.TermPrefix[ i ] = SYM_FLOAT Then
               Stack[ StackPointer + 1 ] = Self.TermPrefix[ i + 1 ]
               Stack[ StackPointer ] = Self.TermPrefix[ i ]
            ElseIf Self.TermPrefix[ i ] = SYM_IDENTIFIER Then
               Stack[ StackPointer + 1 ] = Self.TermIdentValue[ Self.TermPrefix[ i + 1 ], 1 ]
               Stack[ StackPointer ] = Self.TermIdentValue[ Self.TermPrefix[ i + 1 ], 0 ]
            EndIf
            
            i :+ 1
            
            While OperandCount = 2
               Local SP:Int = StackPointer, ResultType:Int = SYM_INTEGER
               
               Select Stack[ StackPointer - 3 ]
                  Case SYM_PLUS
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] + Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) + Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] + IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) + IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_MINUS
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] - Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) - Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] - IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) - IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_TIMES
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] * Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) * Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] * IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) * IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_DIVIDE
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] / Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) / Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] / IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) / IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_POWEROF
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] ^ Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) ^ Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] ^ IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) ^ IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_GREATER
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] > Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) > Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] > IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) > IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_SMALLER
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] < Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) < Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] < IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) < IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_EQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] = Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) = Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] = IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) = IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_GREATEREQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] >= Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) >= Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] >= IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) >= IntToFloat( Stack[ SP + 1 ] ) )
                  Case SYM_SMALLEREQUAL
                     If Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = Stack[ SP - 1 ] <= Stack[ SP + 1 ] ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_INTEGER Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) <= Stack[ SP + 1 ] ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_INTEGER And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( Stack[ SP - 1 ] <= IntToFloat( Stack[ SP + 1 ] ) ) ..
                     ElseIf Stack[ SP - 2 ] = SYM_FLOAT And Stack[ SP ] = SYM_FLOAT Then Stack[ SP - 3 ] = FloatToInt( IntToFloat( Stack[ SP - 1 ] ) <= IntToFloat( Stack[ SP + 1 ] ) )
               End Select
               
               If Stack[ StackPointer ] = SYM_FLOAT Or Stack[ StackPointer - 2 ] = SYM_FLOAT Then
                  Stack[ StackPointer - 4 ] = SYM_FLOAT
               Else
                  Stack[ StackPointer - 4 ] = SYM_INTEGER
               EndIf
               
               StackPointer :- 4
               
               If StackPointer >= 2 And IsTerminal( Stack[ StackPointer - 2 ] ) Then OperandCount = 2 Else OperandCount = 1
            Wend
            
            StackPointer :+ 2
         Else
            Stack[ StackPointer ] = SYM_OPERATOR
            Stack[ StackPointer + 1 ] = Self.TermPrefix[ i ]
            StackPointer :+ 2
            OperandCount = 0
         EndIf
      Next
      
      If Stack[ 0 ] = SYM_INTEGER Then
         Self.ResultInt = Stack[ 1 ]
      Else
         Self.ResultFloat = IntToFloat( Stack[ 1 ] )
      EndIf
      
      Return Stack[ 0 ]
   End Method
   
   Function IsDigit:Int( Char:String )
      If Asc( Char ) >= 48 And Asc( Char ) <= 57 Then Return True
   End Function
   
   Function IsChar:Int( Char:String )
      If Asc( Char ) >=65 And Asc( Char ) <= 90 Then Return True
      If Asc( Char ) >=97 And Asc( Char ) <= 122 Then Return True
   End Function
   
   Function IsTerminal:Int( Symbol:Int )
      If Symbol = SYM_INTEGER Or Symbol = SYM_FLOAT Or Symbol = SYM_IDENTIFIER Then Return True
   End Function
   
   Function FindSymbol:Int( Symbols:Int[], SoughtSymbol:Int, StartIndex:Int = 0 )
      Local NestLevel:Int
      For Local i:Int = StartIndex To Symbols.Length - 1
         If Symbols[ i ] = SoughtSymbol And NestLevel = 0 Then
            Return i
         ElseIf IsTerminal( Symbols[ i ] ) Then
            i :+ 1
         ElseIf Symbols[ i ] = SYM_LEFTPARAN
            NestLevel :+ 1
         ElseIf Symbols[ i ] = SYM_RIGHTPARAN
            NestLevel :- 1
            If NestLevel < 0 Then Return -1
         EndIf
      Next
      
      Return -1
   End Function
   
   Function FloatToInt:Int( Source:Float )
      Return ( Int Ptr ( Varptr Source ) )[ 0 ]
   End Function

   Function IntToFloat:Float( Source:Int )
      Return ( Float Ptr ( Varptr Source ) )[ 0 ]
   End Function
   
   Method PrintPrefixNotation()
      For Local i:Int = 0 To Self.TermPrefix.Length - 1
         Select Self.TermPrefix[ i ]
            Case SYM_PLUS
               WriteStdout "+ "
            Case SYM_MINUS
               WriteStdout "- "
            Case SYM_TIMES
               WriteStdout "* "
            Case SYM_DIVIDE
               WriteStdout "/ "
            Case SYM_LEFTPARAN
               WriteStdout "( "
            Case SYM_RIGHTPARAN
               WriteStdout ") "
            Case SYM_POWEROF
               WriteStdout "^ "
            Case SYM_GREATER
               WriteStdout "> "
            Case SYM_SMALLER
               WriteStdout "< "
            Case SYM_EQUAL
               WriteStdout "= "
            Case SYM_GREATEREQUAL
               WriteStdout ">= "
            Case SYM_SMALLEREQUAL
               WriteStdout "<= "
            Case SYM_INTEGER
               i :+ 1
               WriteStdout Self.TermPrefix[ i ] + " "
            Case SYM_FLOAT
               i :+ 1
               WriteStdout IntToFloat( Self.TermPrefix[ i ] ) + " "
            Case SYM_IDENTIFIER
               i :+ 1
               WriteStdout Self.TermIdentifier[ Self.TermPrefix[ i ] ] + " "
         End Select
      Next
      
      Print ""
   End Method
End Type


Anders als meine damalige Umsetzung in BB basiert dieser Algorithmus auf der Präfixnotation und läuft daher um einiges schneller. Ausserdem macht die Berechnungsfunktion eine Unterscheidung von Int und Float, weswegen viel genauere Resultate möglich sind.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group