Search code examples
asp.netvb.netmathematical-expressions

How to insert values of string builder to an Integer Stack? (VB.Net)


This code basically takes a mathematical expression and evaluates it. The following code i have written in VB.net shamelessly taken from here : Expression Evaluation

which has been written in Java.

  Public Function evaluate(expression As [String]) As Integer
    Dim tokens As Char() = expression.ToCharArray()

    ' Stack for numbers: 'values'
    Dim values As New Stack(Of UInteger)()

    ' Stack for Operators: 'ops'
    Dim ops As New Stack(Of Char)()

    For i As Integer = 0 To tokens.Length - 1
        ' Current token is a whitespace, skip it
        If tokens(i) = " "c Then
            Continue For
        End If

        ' Current token is a number, push it to stack for numbers
        If tokens(i) >= "0"c AndAlso tokens(i) <= "9"c Then
            Dim sbuf As New StringBuilder(100)

            'Dim sbuf As New String("", 128)


            ' There may be more than one digits in number
            If i < tokens.Length AndAlso tokens(i) >= "0"c AndAlso tokens(i) <= "9"c Then
                sbuf.Append(tokens(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)))
            End If
            If sbuf Is Nothing AndAlso sbuf.ToString().Equals("") Then
            Else
                Dim intgr As Integer
                Dim accpt As Boolean = Integer.TryParse(sbuf.ToString(), intgr)
                If accpt = True Then
                    values.Push([Integer].Parse(sbuf.ToString()))
                Else
                    Dim space As String = " "
                    values.Push(space)
                End If


            End If


            ' Current token is an opening brace, push it to 'ops'
        ElseIf tokens(i) = "("c Then
            ops.Push(tokens(i))

            ' Closing brace encountered, solve entire brace
        ElseIf tokens(i) = ")"c Then
            While ops.Peek() <> "("c
                values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
            End While
            ops.Pop()

            ' Current token is an operator.
        ElseIf tokens(i) = "+"c OrElse tokens(i) = "-"c OrElse tokens(i) = "*"c OrElse tokens(i) = "/"c Then
            ' While top of 'ops' has same or greater precedence to current
            ' token, which is an operator. Apply operator on top of 'ops'
            ' to top two elements in values stack
            While Not ops.Count = 0 AndAlso hasPrecedence(tokens(i), ops.Peek())
                values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
            End While

            ' Push current token to 'ops'.
            ops.Push(tokens(i))
        End If
    Next

    ' Entire expression has been parsed at this point, apply remaining
    ' ops to remaining values
    While Not ops.Count = 0
        values.Push(applyOp(ops.Pop(), values.Pop(), values.Pop()))
    End While

    ' Top of 'values' contains result, return it
    Return values.Pop()
End Function

 Public Function hasPrecedence(op1 As Char, op2 As Char) As [Boolean]
    If op2 = "("c OrElse op2 = ")"c Then
        Return False
    End If
    If (op1 = "*"c OrElse op1 = "/"c) AndAlso (op2 = "+"c OrElse op2 = "-"c) Then
        Return False
    Else
        Return True
    End If
End Function

' A utility method to apply an operator 'op' on operands 'a'
' and 'b'. Return the result.
Public Function applyOp(op As Char, b As Integer, a As Integer) As Integer
    Select Case op
        Case "+"c
            Return a + b
        Case "-"c
            Return a - b
        Case "*"c
            Return a * b
        Case "/"c
            If b = 0 Then
                'Throw New UnsupportedOperationException("Cannot divide by zero")
            End If
            Return a \ b
    End Select
    Return 0
End Function

this is how im using the code :

 formula = "10 + 2 * 6"
                    Dim result As Double = evaluate(formula)

and i keep getting this following error:

Unhandled exception at line 885, column 13 in http:**** DEDOM5KzzVKtsL1tWZwgsquruscgqkpS5bZnMu2kotJDD8R38OukKT4TyG0z97U1A8ZC8o0wLOdVNYqHqQLlZ9egcY6AKpKRjQWMa4aBQG1Hz8t_HRmdQ39BUIKoCWPik5bv4Ej6LauiiQptjuzBMLowwYrLGpq6dAhVvZcB-4b-mV24vCqXJ3jbeKi0&t=6119e399

0x800a139e - Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Conversion from string " " to type 'UInteger' is not valid.

Im a beginner but i think that the error is occurring because its not able to covert space into integer.How to deal with the spaces?? Any help is much appreciated:).


Solution

  • VB.NET is strongly-typed, so you simply cannot push anything other than integers onto a Stack(Of Integer). Therefore this code:

    Dim space As String = " "
    values.Push(space)
    

    will always fail at runtime. (By the way, you want to set Option Explicit On and Option Strict On at the top of every module. If you do that, the line above will already be marked as an error at build time).

    I haven't tried executing your code, but why would you need to save the spaces if what you're building is an expression evaluator? It doesn't seem to add anything to the evaluation. Perhaps if you simply don't add the spaces to the stack it will work anyway.