Member 11450536 Ответов: 0

Пользовательский синтаксический анализ текста в VB.NET


Привет
Я собираюсь создать игру в ближайшее время, и я сделал конфигурационный файл для сервера. Сервер имеет редактор конфигурации, который позволяет пользователю просматривать и редактировать конфигурационный файл простым для понимания способом.

Он позволяет использовать следующие теги:

$c[r, g, b] (изменяет цвет текста)
$b (выделяет текст жирным шрифтом)
$i (выделяет текст курсивом)
$u (подчеркивает текст)
$s (вычеркивает текст)

Парсер работает, вытаскивая любые теги, изменяя формат текста, а затем рисуя его в событии ListViewDrawSubItem.

Например,
$bWelcome back, $c[128,255,255]$name
становится
Welcome back, <name>
(где-название-светло-голубое).

Как вы можете видеть на изображениях, любой тег разрешен непосредственно после $c[] или в начале слова, но ни в какой другой конфигурации.

Как я могу изменить свой код, чтобы разрешить любое количество тегов в любом месте строки, если синтаксис правильный? Например, "$Ц[0,255,0]х$бел$Ил$так" должна стать чэльло

Соответствующий код:

Private Sub configListView_DrawSubItem(sender As Object, e As DrawListViewSubItemEventArgs) Handles configListView.DrawSubItem

       If e.Item.Selected Then
           e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), e.Bounds)
       Else
           e.Graphics.FillRectangle(New SolidBrush(configListView.BackColor), e.Bounds)
       End If

       If e.ColumnIndex = 0 Then
           TextRenderer.DrawText(e.Graphics, e.SubItem.Text, New Font(Me.Font, Nothing), New Point(e.Bounds.Left + 3, e.Bounds.Top + 2), configListView.ForeColor)
           Return
       End If

       Dim textToDraw As Dictionary(Of Color, String) = Utils.getColorsFrom(e.SubItem.Text, configListView.ForeColor)

       Dim x As Integer = e.Bounds.Left + 3
       Dim y As Integer = e.Bounds.Top + 2

       For Each d As KeyValuePair(Of Color, String) In textToDraw

           Dim color As Color = d.Key
           Dim text As String = d.Value

           If text = "True" Then
               color = Color.FromArgb(128, 255, 128)
           ElseIf text = "False" Then
               color = Color.FromArgb(255, 128, 128)
           ElseIf Integer.TryParse(text, New Integer) Then
               color = Color.FromArgb(128, 128, 255)
           End If

           Dim font As Font = Me.Font

           If text.StartsWith("$b") Then
               font = New Font(Me.Font, FontStyle.Bold)
               text = text.Substring(2, text.Length - 2)
           ElseIf text.StartsWith("$i") Then
               font = New Font(Me.Font, FontStyle.Italic)
               text = text.Substring(2, text.Length - 2)
           ElseIf text.StartsWith("$u") Then
               font = New Font(Me.Font, FontStyle.Underline)
               text = text.Substring(2, text.Length - 2)
           ElseIf text.StartsWith("$s") Then
               font = New Font(Me.Font, FontStyle.Strikeout)
               text = text.Substring(2, text.Length - 2)
           End If

           text = text.Replace("$name", "<name>")

           TextRenderer.DrawText(e.Graphics, text, font, New Point(x, y), color)

           x += TextRenderer.MeasureText(text, Font).Width - 6

       Next

   End Sub


Утилитами.ВБ

Shared Function splitByWord(str As String, delimeterWord As String, allowEmpties As Boolean) As String()
        Return str.Split(New String() {delimeterWord}, IIf(allowEmpties, StringSplitOptions.None, StringSplitOptions.RemoveEmptyEntries))
    End Function

    Shared Function countOf(c As String, str As String) As Integer

        Dim count As Integer = 0

        For Each ch In str
            If c = ch Then count += 1
        Next

        Return count

    End Function

    Shared Function getColorsFrom(str As String, defaultColor As Color) As Dictionary(Of Color, String)

        Dim result As New Dictionary(Of Color, String)

        For Each s As String In Utils.splitByWord(str, "$c", False)

            If Not (s.Substring(0, 1) = "[" AndAlso s.Contains("]")) Then
                result.Add(defaultColor, s)
                Continue For
            End If

            Dim rgb As String = s.Substring(1, s.Length - 1).Split("]")(0)

            If Not Utils.countOf(",", rgb) = 2 Then
                result.Add(defaultColor, s)
                Continue For
            End If

            Dim text As String = s.Substring(rgb.Length + 2, s.Length - rgb.Length - 2)
            Dim r As Integer = 0
            Dim g As Integer = 0
            Dim b As Integer = 0

            Try
                r = rgb.Split(",")(0)
                g = rgb.Split(",")(1)
                b = rgb.Split(",")(2)

                result.Add(Color.FromArgb(r, g, b), text)
            Catch
                result.Add(defaultColor, s)
                Continue For
            End Try

        Next

        Return result

    End Function


http://dc773.4shared.com/img/BtucjLtOce/s23/15666a14bf0/scr1[^]

http://dc773.4shared.com/img/y_v8KfcVce/s23/15666a14fd8/scr2[^]

Что я уже пробовал:

Я пытался усовершенствовать вышеприведенный код в течение нескольких часов без посторонней помощи.

Member 11450536

Ударять. Я потратил на это много времени и не могу понять.

Kschuler

Я не могу ответить на этот вопрос прямо...но я почти уверен, что вам следует исследовать регулярные выражения.

0 Ответов