Моя первая прога на VB.net ;-)

Обсуждение проектов наших жителей.
Вы можете выставить проект на тест или найти помощников для его реализации.

Модератор: BV

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Моя первая прога на VB.net ;-)

Сообщение tyomitch » 11.04.2005 (Пн) 21:34

(Ура, ура! Я пересилил себя!!)

Надеюсь, что то, что получислось - настоящий автомат (ака State Machine), потому что раньше я их никогда не писал :-)

Назначение: парсилка INI-файлов.

Код: Выделить всё
Option Explicit On
Option Strict On

Module Main
    Sub Main()
        Dim Section As INIParser.Section, Value As INIParser.Value
        For Each Section In New INIParser.INIParser(New IO.FileStream(Command(), IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
            Console.WriteLine("[" & Section.Name & "]")
            For Each Value In Section
                Console.WriteLine(Value.Name & CStr(IIf(Value.Value Is Nothing, "", "=" & Value.Value)))
            Next
        Next
    End Sub
End Module


Namespace Automata
    Friend Module General
        ''emulates operator= of C
        Friend Function Assign(ByRef LHS As Object, ByVal RHS As Object) As Object
            LHS = RHS
            Assign = LHS
        End Function
    End Module

    Class Automaton
        Structure TransitionEntry
            Public NextState As Integer
            Public Tag As Object
            Sub New(ByVal NextState As Integer, ByVal Tag As Object)
                Me.NextState = NextState : Me.Tag = Tag
            End Sub
        End Structure
        Public Delegate Function Group(ByVal _Byte As Integer) As Integer
        Private Shared Function DefaultGroup(ByVal _Byte As Integer) As Integer
            Return _Byte
        End Function
        Public Delegate Sub Transition(ByVal _Byte As Integer, ByVal OldState As Integer, ByVal NewState As Integer, ByVal TransitionTag As Object)
        Private Shared Sub DefaultTransition(ByVal _Byte As Integer, ByVal OldState As Integer, ByVal NewState As Integer, ByVal TransitionTag As Object)
        End Sub

        Private m_States(,) As TransitionEntry, m_Transition As Transition
        Private m_Group As Group, m_State As Integer
        Sub New(ByVal States(,) As TransitionEntry, Optional ByVal Group As Group = Nothing, Optional ByVal Transition As Transition = Nothing)
            : If Group Is Nothing Then Group = AddressOf DefaultGroup
            : If Transition Is Nothing Then Transition = AddressOf DefaultTransition
            If States.Rank <> 2 Then Throw New ArgumentException
            ReDim m_States(States.GetLength(0) - 1, States.GetLength(1) - 1)
            Array.Copy(States, m_States, States.GetLength(0) * States.GetLength(1))
            m_Group = Group
            m_Transition = Transition
            m_State = 0
        End Sub

        Sub Run(ByVal Stream As IO.Stream)
            Dim CurByte As Object, PrevState As Integer, TransitionEntry As TransitionEntry
            While CInt(Assign(CurByte, Stream.ReadByte)) >= 0
                PrevState = m_State
                TransitionEntry = m_States(m_State, m_Group(CInt(CurByte)))
                m_State = TransitionEntry.NextState
                m_Transition(CInt(CurByte), PrevState, m_State, TransitionEntry.Tag)
            End While
        End Sub
    End Class
End Namespace

Namespace INIParser
    Class Value
        Implements IComparable, ICloneable
        Public Overloads Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
            If TypeOf obj Is Value Then
                Dim RHS As Value = CType(obj, Value)
                Return m_Value.CompareTo(RHS.m_Value)
            End If
            Throw New ArgumentException
        End Function
        Public Function Clone() As Object Implements System.ICloneable.Clone
            Return New Value(m_Name, m_Value)
        End Function

        Private m_Name As String, m_Value As String
        Friend Sub New(ByVal Name As String, Optional ByVal Value As String = Nothing)
            m_Name = Name : m_Value = Value
        End Sub

        ReadOnly Property Name() As String
            Get
                Name = m_Name
            End Get
        End Property
        ReadOnly Property Value() As String
            Get
                Value = m_Value
            End Get
        End Property
    End Class

    Class Section
        Inherits System.Collections.ReadOnlyCollectionBase
        Implements ICloneable
        Public Function Clone() As Object Implements System.ICloneable.Clone
            Return New Section(m_Name, InnerList)
        End Function

        Private m_Name As String
        Friend Sub New(ByVal Name As String)
            m_Name = Name
        End Sub
        Friend Sub New(ByVal Name As String, ByVal Values As ArrayList)
            m_Name = Name : InnerList.AddRange(CType(Values.Clone, ArrayList))
        End Sub

        ReadOnly Property Name() As String
            Get
                Name = m_Name
            End Get
        End Property

        Friend Sub Add(ByVal Value As Value)
            InnerList.Add(Value)
        End Sub

        Default ReadOnly Property Value(ByVal Index As Integer) As Value
            Get
                Return CType(InnerList(Index), Value)
            End Get
        End Property
        Default ReadOnly Property Value(ByVal Name As String) As Value
            Get
                Return CType(InnerList(InnerList.BinarySearch(New Value(Name, Nothing))), Value)
            End Get
        End Property
    End Class

    Class INIParser
        Inherits System.Collections.ReadOnlyCollectionBase
        Implements ICloneable
        Public Function Clone() As Object Implements System.ICloneable.Clone
            Return New INIParser(InnerList)
        End Function

        Private Shared INIStates As Integer(,) = {{7, 0, 0, 0, 3, 1, 7, 4, 7}, _
                                                  {7, 1, 7, 7, 1, 7, 6, 7, 7}, _
                                                  {2, 2, 2, 0, 2, 2, 2, 2, 2}, _
                                                  {7, 5, 5, 0, 3, 7, 7, 4, 2}, _
                                                  {4, 4, 4, 0, 4, 4, 4, 4, 4}, _
                                                  {7, 5, 5, 0, 7, 7, 7, 4, 2}, _
                                                  {7, 6, 6, 0, 7, 7, 7, 4, 7}, _
                                                  {7, 7, 7, 7, 7, 7, 7, 7, 7}}
        Private States(,) As Automata.Automaton.TransitionEntry
        Private Shared Function INIGroup(ByVal _Byte As Integer) As Integer
            Select Case _Byte
                Case 32 : Return 1 'Space
                Case 9 : Return 2 'Tab
                Case 13, 10 : Return 3 'Eol
                Case 48 To 57, 65 To 90, 97 To 122, 95 : Return 4 'Alphanumeric, _
                Case 91 : Return 5 '[
                Case 93 : Return 6 ']
                Case 59 : Return 7 ';
                Case 61 : Return 8 '=
                Case Else : Return 0
            End Select
        End Function
        Private Shared Eol() As Byte = {10}

        Private SectionName, ValueName, Value As String
        Private CurSection As Section

        Private Delegate Sub Commit()
        Private Sub CommitSection()
            If Not (CurSection Is Nothing) Then InnerList.Add(CurSection)
            CurSection = New Section(SectionName)
        End Sub
        Private Sub CommitName() '''commits empty value
            If CurSection Is Nothing Then Throw New FormatException
            CurSection.Add(New Value(ValueName))
        End Sub
        Private Sub CommitValue()
            If CurSection Is Nothing Then Throw New FormatException
            CurSection.Add(New Value(ValueName, Value))
        End Sub
        Private Sub InitializeStates()
            ReDim States(UBound(INIStates, 1), UBound(INIStates, 2))
            Dim s, g As Integer : For s = 0 To UBound(INIStates, 1) : For g = 0 To UBound(INIStates, 2)
                    States(s, g).NextState = INIStates(s, g)
            Next g, s
            States(1, 6).Tag = CType(AddressOf CommitSection, Commit)
            States(2, 3).Tag = CType(AddressOf CommitValue, Commit)
            States(3, 3).Tag = CType(AddressOf CommitName, Commit)
            States(3, 7).Tag = CType(AddressOf CommitName, Commit)
            States(5, 3).Tag = CType(AddressOf CommitName, Commit)
            States(5, 7).Tag = CType(AddressOf CommitName, Commit)
        End Sub

        Private Sub INITransition(ByVal _Byte As Integer, ByVal OldState As Integer, ByVal NewState As Integer, ByVal TransitionTag As Object)
            Select Case NewState
                Case 1 : If OldState = NewState Then SectionName = SectionName & Chr(_Byte) Else SectionName = ""
                Case 2 : If OldState = NewState Then Value = Value & Chr(_Byte) Else Value = ""
                Case 3 : If OldState = NewState Then ValueName = ValueName & Chr(_Byte) Else ValueName = Chr(_Byte)
                Case 7 : Throw New FormatException
            End Select
            If Not (TransitionTag Is Nothing) Then CType(TransitionTag, Commit)()
        End Sub

        Sub New(ByVal Stream As IO.Stream)
            InitializeStates()
            With New Automata.Automaton(States, AddressOf INIGroup, AddressOf INITransition)
                .Run(Stream)
                .Run(New System.IO.MemoryStream(Eol)) 'eof treated as eol
                CommitSection()
            End With
        End Sub

        Private Sub New(ByVal Sections As ArrayList)
            InnerList.AddRange(CType(Sections.Clone, ArrayList))
        End Sub

        Default ReadOnly Property Section(ByVal Index As Integer) As Section
            Get
                Return CType(InnerList(Index), Section)
            End Get
        End Property
        Default ReadOnly Property Section(ByVal Name As String) As Section
            Get
                Return CType(InnerList(InnerList.BinarySearch(New Section(Name))), Section)
            End Get
        End Property
    End Class
End Namespace


Ещё есть то же самое на C#, может выложить в соответствующем ему разделе? ;-)

ЗЫ: правда что ли в C# нету опциональных параметров? :shock:
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 12.04.2005 (Вт) 6:05

tyomitch писал(а):ЗЫ: правда что ли в C# нету опциональных параметров? :shock:


:shock:
Щас пошёл и поглядел... :shock:
IDE Tooltip писал(а):Default parameter specifiers are not permitted

Получается, VB мощнее C :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Sebas
Неуловимый Джо
Неуловимый Джо
Аватара пользователя
 
Сообщения: 3626
Зарегистрирован: 12.02.2002 (Вт) 17:25
Откуда: столько наглости такие вопросы задавать

Сообщение Sebas » 12.04.2005 (Вт) 7:58

а мой примерчик, на сайте не смотрел?
- Я никогда не понимал, почему они приходят ко мне чтобы умирать?

sebas<-@->mail.ru


Вернуться в Наши проекты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17

    TopList