none
Alternative to Val not RegEx RRS feed

  • Question

  • I am improving my JSON parser and so I need to parse a number from the beginning of a String. Currently, I have the following RegEx solution:

    Private Function Parse_Number(ByRef source As String) As XElement
        Dim m As Match = Regex.Match(source, "-?\d+((\.\d+)?((e|E)[+-]?\d+)?)")
        Dim t As XElement = Nothing
    
        If m.Success AndAlso m.Index = 0 Then
            t = New XElement("number", m.Value)
            source = source.Substring(m.Value.Length)
        End If
    
        Return t
    End Function

    And I also have a manual parsing Function created:

    Private Function Parse_Number(ByVal json As String, ByRef index As Integer) As XElement
      'Declare an XElement to return (the default is Nothing)
      Dim nonTerminal As XElement = Nothing
    
      'The EBNF for a JSON number is: number ::= ['-'], ('0' | digit_excluding_zero, {digit}), ['.', {digit}], [('e' | 'E'), ['+' | '-'], {digit}]
      'Declare a variable to hold the length of the value (more efficient to work with numbers)
      Dim valueIndex As Integer = 0
    
      'Check for the optional unary negative
      If json(0) = "-"c Then
        valueIndex += 1
      End If
    
      'Check for a zero or any other digit
      If valueIndex + index >= json.Length Then
        Throw New Exception("Invalid value. The number starts with a unary negative, but does not have anything afterwards.")
      ElseIf json(valueIndex + index) = "0"c Then
        valueIndex += 1
      ElseIf Char.IsDigit(json(valueIndex + index)) Then
        valueIndex += 1
    
        'Loop while the current char is a digit
        Do While valueIndex + index < json.Length AndAlso Char.IsDigit(json(valueIndex + index))
          valueIndex += 1
        Loop
      End If
    
      'Check for the optional fractional part
      If valueIndex + index < json.Length AndAlso json(valueIndex + index) = "."c Then
        valueIndex += 1
    
        'There needs to be one or more digits following the decimal (otherwise throw an exception)
        If valueIndex + index < json.Length AndAlso Char.IsDigit(json(valueIndex + index)) Then
          Do While valueIndex + index < json.Length AndAlso Char.IsDigit(json(valueIndex + index))
            valueIndex += 1
          Loop
        Else
          Throw New Exception("Invalid value. A number with a decimal requires one or more numbers after the decimal place.")
        End If            
      End If
    
      'Check for the optional exponent part
      If valueIndex + index < json.Length AndAlso json(valueIndex + index) = "e"c OrElse json(valueIndex + index) = "E"c Then
        valueIndex += 1
    
        'Check for the optional unary positive or negative sign
        If valueIndex + index < json.Length AndAlso (json(valueIndex + index) = "-"c OrElse json(valueIndex + index) = "+"c) Then
          valueIndex += 1
        End If
    
        'There needs to be one or more digits following the exponent e (otherwise throw an exception)
        If valueIndex + index < json.Length AndAlso Char.IsDigit(json(valueIndex + index)) Then
          Do While valueIndex + index < json.Length AndAlso Char.IsDigit(json(valueIndex + index))
            valueIndex += 1
          Loop
        Else
          Throw New Exception("Invalid value. A number with an exponent requires one or more numbers after the indicator.")
        End If
      End If
    
      'If there is a value then create the non-terminal and remove the length of the value
      If valueIndex > 0 Then
        'The XElement should look like this: <number>123</number>
        nonTerminal = New XElement("number", json.Substring(0, valueIndex))
        index += valueIndex
      End If
    
      Return nonTerminal
    End Function

    However, the Val() function found in the Microsoft.VisualBasic namespace would essentially do the same thing. The problem is that (call me a .NET purist), but I don't like using Microsoft.VisualBasic namespace methods. Aside from RegEx and my handwritten solution, is there anything else that I could use?


    • Edited by David_Day Monday, July 3, 2017 9:06 PM
    Monday, July 3, 2017 9:05 PM

Answers

  • Hi David_day,

    Through my search, in addition to using RegEx or manual parsing Function , I did not find other way to replace val () in .net, hope other person can help you.

    Best Regadrs,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by David_Day Monday, July 10, 2017 8:13 PM
    Thursday, July 6, 2017 6:58 AM
    Moderator

All replies

  • Hi David_day,

    Through my search, in addition to using RegEx or manual parsing Function , I did not find other way to replace val () in .net, hope other person can help you.

    Best Regadrs,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by David_Day Monday, July 10, 2017 8:13 PM
    Thursday, July 6, 2017 6:58 AM
    Moderator
  • Dear Cherry,

        This is what I was afraid of. For now, I'm going to mark the thread resolved unless somebody else is able to find a pure .NET alternative to the Val Function.

    Sincerely,

    -David

    • Edited by David_Day Monday, July 10, 2017 8:13 PM
    Monday, July 10, 2017 8:13 PM