Results 1 to 3 of 3

Thread: Text Parser

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Text Parser

    I want to optimize this code in the following areas: internal error checking (not just try...catch, but if...then as well) and for speed. See below for code to be optimized. I'll post a reply that has some test code.

    VB Code:
    1. Public Function ParseText( _
    2.            ByVal TextToParse As String, _
    3.            ByVal ParseStartDelim As Char, _
    4.            ByVal ParseEndDelim As Char, _
    5.            ByVal ClassCollection As Collection, _
    6.            Optional ByVal ClassFieldSeparator As Char = ".", _
    7.            Optional ByVal DebugMode As Boolean = False, _
    8.            Optional ByVal DebugEndBlockPrefix As Char = "/", _
    9.            Optional ByVal StartTag As String = "[template start]", _
    10.            Optional ByVal EndTag As String = "[template end]") _
    11.     As String
    12.         'For use with web pages that need data access
    13.         '
    14.         'Parses text based on start and end delim char. Uses CallByName to determine
    15.         'what to replace parsed values with. Debug mode helps make debuging final
    16.         'output easier.
    17.         'Assuming that ClassCollection has an item that is a class with a field named
    18.         ''name' that was set to 'Jack Schitt' and said item's Key in the collection
    19.         'was 'Profile'. Also assume 'ParseStartDelim', 'ParseEndDelim',
    20.         ''ClassFieldSeperator' and are '[', ']', and '.', respectivly, then the
    21.         'samples can be shown as:
    22.         '
    23.         '"test test [profile.name] test"
    24.         '
    25.         'With DebugMode=False, this function would return
    26.         '"test test Jack Schitt test"
    27.         '
    28.         'With DebugMode=True, this function would return
    29.         '"test test [profile.name]Jack Schitt[/profile.name] test"
    30.         '
    31.         'Classes and/or members that don't exist raise an exception that is trapped
    32.         'internally, causeing the tag to be replaced with "". (This is useful for
    33.         'comments.) In debug mode, it will be replaced by the message of the exception.
    34.         '
    35.         'Last but not least, there are the 'StartTag' and 'EndTag' params. Basically,
    36.         'only text between those tags is returned. Text outside of those tags is
    37.         'removed prior to parsing.
    38.  
    39.         Dim Pos As Integer 'current position in string
    40.         Dim SubStringHolder As String 'Holds a substring between a particular [ and ]
    41.         '                              [ is shorthand for ParseStartDelim
    42.         '                              (and viceversa)
    43.         Dim ClassName As String
    44.         Dim FieldName As String
    45.         Dim [Class] As Object
    46.         Dim ReturnValue As Object
    47.  
    48.         'check for start tag
    49.         If TextToParse.IndexOf(StartTag) <> -1 Then
    50.             'remove everything before [template start]
    51.             TextToParse = TextToParse.Remove(0, TextToParse.IndexOf(StartTag) + StartTag.Length)
    52.         End If
    53.  
    54.         'check for end tag
    55.         If TextToParse.IndexOf(EndTag) <> -1 Then
    56.             'remove everything after end tag
    57.             TextToParse = TextToParse.Remove(TextToParse.IndexOf(EndTag), TextToParse.Length - TextToParse.IndexOf(EndTag))
    58.         End If
    59.  
    60.         While Pos < (TextToParse.Length)
    61.             'if [character at Pos] = ParseStartDelim
    62.             '...The complicated, but efficient way...
    63.             If (TextToParse.Substring(Pos, 1).Chars(0).Equals(ParseStartDelim)) Then
    64.                 'In Tag
    65.  
    66.                 Try
    67.                     'we need the substring from the current [ to the next ]
    68.                     'get everything from Pos on
    69.                     SubStringHolder = TextToParse.Substring(Pos + 1)
    70.                     'trim it to the next ]
    71.  
    72.                     If SubStringHolder.IndexOf(ParseEndDelim) = -1 Then
    73.                         Throw New ParseException("Reached end of file without closing delimiter.", True)
    74.                     End If
    75.  
    76.                     SubStringHolder = SubStringHolder.Substring(0, SubStringHolder.IndexOf(ParseEndDelim))
    77.  
    78.                     'remove the existing text
    79.                     TextToParse = TextToParse.Remove(Pos, SubStringHolder.Length + 2)
    80.  
    81.                     If SubStringHolder.IndexOf(ClassFieldSeparator) = -1 Then
    82.                         'contains no '.'
    83.                         ClassName = SubStringHolder
    84.                         Throw New ParseException("No class name specified", False)
    85.                     End If
    86.  
    87.                     ClassName = SubStringHolder.Substring(0, SubStringHolder.IndexOf(ClassFieldSeparator))
    88.  
    89.                     FieldName = SubStringHolder.Substring(SubStringHolder.IndexOf(ClassFieldSeparator) + 1)
    90.  
    91.                     If ClassName = "" Then
    92.                         '[.foo]
    93.                         Throw New ParseException("No class name specified", False)
    94.                     End If
    95.  
    96.                     If FieldName = "" Then
    97.                         '[foo.]
    98.                         Throw New ParseException("No field name specified", False)
    99.                     End If
    100.  
    101.                     [Class] = ClassCollection(ClassName)
    102.                     ReturnValue = CallByName([Class], FieldName, CallType.Get)
    103.  
    104.                     'this next block is required incase field is a sub or
    105.                     'otherwise doesn't return a value
    106.                     If ReturnValue Is Nothing Then
    107.                         If DebugMode Then
    108.                             SubStringHolder = "Field was called but returned 'Nothing'"
    109.                         Else
    110.                             SubStringHolder = ""
    111.                         End If
    112.                     Else
    113.                         SubStringHolder = ReturnValue.ToString
    114.                     End If
    115.                 Catch nope As MissingMemberException
    116.                     'CallByName throws this.
    117.                     '[foo.bar] 'bar' is not found
    118.                     If DebugMode Then
    119.                         SubStringHolder = "Field name not found"
    120.                     Else
    121.                         SubStringHolder = ""
    122.                     End If
    123.                 Catch nope As ArgumentException
    124.                     '[Class] = ClassCollection(ClassName) throws this
    125.                     '[foo.bar] 'foo' not found in collection
    126.                     If DebugMode Then
    127.                         SubStringHolder = "Class name not found"
    128.                     Else
    129.                         SubStringHolder = ""
    130.                     End If
    131.                 Catch nope As ParseException
    132.                     'Several If...Then blocks above throw this
    133.                     If DebugMode Then
    134.                         SubStringHolder = nope.Message
    135.                     Else
    136.                         SubStringHolder = ""
    137.                     End If
    138.  
    139.                     If nope.IsFatal Then
    140.                         Return TextToParse & " " & SubStringHolder
    141.                         Exit Function
    142.                     End If
    143.  
    144.                 Finally
    145.                     If DebugMode Then
    146.                         'if debug mode, wrap the string with tags
    147.  
    148.                         '[foo.bar]{value}
    149.                         SubStringHolder = ParseStartDelim & _
    150.                         ClassName & ClassFieldSeparator & FieldName & _
    151.                         ParseEndDelim & SubStringHolder
    152.  
    153.                         '+=[/foo.bar]
    154.                         SubStringHolder += ParseStartDelim & DebugEndBlockPrefix & _
    155.                         ClassName & ClassFieldSeparator & FieldName & _
    156.                         ParseEndDelim
    157.                     End If
    158.                 End Try
    159.  
    160.                 'insert the value into the main text where the tag originally
    161.                 'was. if DebugMode, the tags were wrapped above.
    162.                 TextToParse = TextToParse.Insert(Pos, SubStringHolder)
    163.  
    164.                 'increment the position by the length of the new value. -1 for
    165.                 'the statement after this one
    166.                 Pos += SubStringHolder.Length - 1
    167.             End If
    168.             Pos += 1
    169.             If Pos < 0 Then Exit While
    170.         End While
    171.  
    172.         Return TextToParse
    173.     End Function
    174.  
    175.     Public Class ParseException
    176.         'this exception used internally by the parser
    177.         '
    178.         ''message' is the text sent to the output when the parser's
    179.         ''debugmode' is true
    180.         '
    181.         ''IsFatal' tells the parser to stop parseing. If true, ''Message' is
    182.         'appended to the end of the output.
    183.  
    184.         Inherits Exception
    185.  
    186.         Sub New(ByVal message As String, ByVal IsFatal As Boolean)
    187.             MyBase.New(message)
    188.             _IsFatal = IsFatal
    189.         End Sub
    190.  
    191.         Private _IsFatal As Boolean 'private copy
    192.  
    193.         Public ReadOnly Property IsFatal() As Boolean
    194.             Get
    195.                 Return _IsFatal
    196.             End Get
    197.         End Property
    198.     End Class

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Re: Text Parser

    To test it
    VB Code:
    1. Public Sub testit()
    2.         Dim a As New Collection()
    3.         Dim DebugMode As Boolean
    4.         Dim TextToParse As String
    5.  
    6.         a.Add(New TesterClass(), "test")
    7.  
    8.         TextToParse = "blahblahblah...[template start]Hello my name is [test.name]. I live at [test.address] in the city of [test.city]. My favorite porno website[To test urls (and comments)] is [test.favepr0n]. [template end] blah blah blah, everything here is ignored."
    9.  
    10.         Debug.WriteLine("Param: DebugMode = False")
    11.         Debug.WriteLine(ParseText(TextToParse, "[", "]", a, , DebugMode))
    12.  
    13.         DebugMode = True
    14.  
    15.         Debug.WriteLine("Param: DebugMode = True")
    16.         Debug.WriteLine(ParseText(TextToParse, "[", "]", a, , DebugMode))
    17.     End Sub
    18.  
    19.     Public Class TesterClass
    20.         Public name As String = "Dr. Melora Vanhasian"
    21.         Public address As String = "11333 Roscoe Blvd., #318"
    22.  
    23.         Public ReadOnly Property city() As String
    24.             Get
    25.                 Return "Van Nuys, CA"
    26.             End Get
    27.         End Property
    28.  
    29.         Public Function favepr0n() As Uri
    30.             Return New Uri("http://www.mufftorrent.com")
    31.         End Function
    32.     End Class

    Output window should read:
    Code:
    Param: DebugMode = False
    Hello my name is Dr. Melora Vanhasian. I live at 11333 Roscoe Blvd., #318 in the city of Van Nuys, CA. My favorite porno website is http://www.mufftorrent.com/. 
    Param: DebugMode = True
    Hello my name is [test.name]Dr. Melora Vanhasian[/test.name]. I live at [test.address]11333 Roscoe Blvd., #318[/test.address] in the city of [test.city]Van Nuys, CA[/test.city]. My favorite porno website[To test urls (and comments).city]No class name specified[/To test urls (and comments).city] is [test.favepr0n]http://www.mufftorrent.com/[/test.favepr0n].

  3. #3
    Code Monkey wild_bill's Avatar
    Join Date
    Mar 2005
    Location
    Montana
    Posts
    2,993

    Re: Text Parser

    Have you looked into using regularexpressions?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width