scanner.vb

来自「大名鼎鼎的mono是.NET平台的跨平台(支持linux」· VB 代码 · 共 1,307 行 · 第 1/4 页

VB
1,307
字号
' ' Visual Basic.Net Compiler' Copyright (C) 2004 - 2007 Rolf Bjarne Kvinge, RKvinge@novell.com' ' This library is free software; you can redistribute it and/or' modify it under the terms of the GNU Lesser General Public' License as published by the Free Software Foundation; either' version 2.1 of the License, or (at your option) any later version.' ' This library is distributed in the hope that it will be useful,' but WITHOUT ANY WARRANTY; without even the implied warranty of' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU' Lesser General Public License for more details.' ' You should have received a copy of the GNU Lesser General Public' License along with this library; if not, write to the Free Software' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA' #Const SUPPORT_CSTYLE_COMMENTS = 1#If DEBUG Then#Const DOEOFCHECK = 0#Const EXTENDEDDEBUG = 0#End If#Const EXTENDED = FalsePublic Class Scanner    Implements ITokenReader    ''' <summary>    ''' The total number of lines scanned.    ''' </summary>    ''' <remarks></remarks>    Private m_TotalLineCount As UInteger    ''' <summary>    ''' The total number of characters scanned.    ''' </summary>    ''' <remarks></remarks>    Private m_TotalCharCount As Integer    ''' <summary>    ''' The current line.    ''' </summary>    ''' <remarks></remarks>    Private m_CurrentLine As UInteger    ''' <summary>    ''' The current column.    ''' </summary>    ''' <remarks></remarks>    Private m_CurrentColumn As Byte    ''' <summary>    ''' The current code file.    ''' </summary>    ''' <remarks></remarks>    Private m_CodeFile As CodeFile    Private m_CodeFileIndex As UShort    Private m_PreviousChar As Char    Private m_CurrentChar As Char    Private m_PeekedChars As New Generic.Queue(Of Char)    Private m_Reader As System.IO.StreamReader    Private m_Builder As New System.Text.StringBuilder    ''' <summary>    ''' If any tokens has been found on this line.    ''' Reset by IncLine, set by NewToken    ''' </summary>    ''' <remarks></remarks>    Private m_TokensSeenOnLine As Integer    Private m_Files As Generic.Queue(Of CodeFile)    Private m_Compiler As Compiler    Private m_Peeked As Token    Private m_PeekedExact As Token    Private m_Current As Token    'Useful constants.    Private Const nl0 As Char = Microsoft.VisualBasic.ChrW(0)    Private Const nlA As Char = Microsoft.VisualBasic.ChrW(&HA)    Private Const nlD As Char = Microsoft.VisualBasic.ChrW(&HD)    Private Const nl2028 As Char = Microsoft.VisualBasic.ChrW(&H2028)    Private Const nl2029 As Char = Microsoft.VisualBasic.ChrW(&H2029)    Private Const nlTab As Char = Microsoft.VisualBasic.ChrW(9)    Private Const COMMENTCHAR1 As Char = "'"c    Private Const COMMENTCHAR2 As Char = Microsoft.VisualBasic.ChrW(&H2018)    Private Const COMMENTCHAR3 As Char = Microsoft.VisualBasic.ChrW(&H2019)    ReadOnly Property TotalLineCount() As UInteger        Get            Return m_TotalLineCount        End Get    End Property    ReadOnly Property TotalCharCount() As Integer        Get            Return m_TotalCharCount        End Get    End Property    ReadOnly Property Compiler() As Compiler        Get            Return m_Compiler        End Get    End Property    Private Function IsNewLine() As Boolean        Return IsNewLine(CurrentChar)    End Function    Private Function IsNewLine(ByVal chr As Char) As Boolean        Return chr = nlA OrElse chr = nlD OrElse chr = nl2028 OrElse chr = nl2029 OrElse chr = nl0    End Function    Private Function IsUnderscoreCharacter(ByVal chr As Char) As Boolean        'UnderscoreCharacter ::= < Unicode connection character (class Pc) >        Return Char.GetUnicodeCategory(chr) = Globalization.UnicodeCategory.ConnectorPunctuation    End Function    Private Function IsIdentifierCharacter(ByVal chr As Char) As Boolean        'IdentifierCharacter ::=        '   UnderscoreCharacter |        '   AlphaCharacter |        '   NumericCharacter |        '   CombiningCharacter |        '   FormattingCharacter        Return IsUnderscoreCharacter(chr) OrElse _                IsAlphaCharacter(chr) OrElse _                IsNumericCharacter(chr) OrElse _                IsCombiningCharacter(chr) OrElse _                IsFormattingCharacter(chr)    End Function    Private Function IsNumericCharacter(ByVal chr As Char) As Boolean        'NumericCharacter ::= < Unicode decimal digit character (class Nd) >        Return Char.GetUnicodeCategory(chr) = Globalization.UnicodeCategory.DecimalDigitNumber 'Nd    End Function    Private Function IsOperatorCharacter(ByVal chr As Char) As Boolean        'Operator ::= & * +  -  /  \  ^ <  =  >        Return chr = "&"c OrElse _                chr = "*"c OrElse _                chr = "+"c OrElse _                chr = "-"c OrElse _                chr = "/"c OrElse _                chr = "\"c OrElse _                chr = "^"c OrElse _                chr = "<"c OrElse _                chr = "="c OrElse _                chr = ">"c        chr = ":"c    End Function    Private Function IsSeparatorCharacter(ByVal chr As Char) As Boolean        'Separator ::= (  )  {  }  !  #  ,  .  :        Return chr = "("c OrElse _                chr = ")"c OrElse _                chr = "{"c OrElse _                chr = "}"c OrElse _                chr = "!"c OrElse _                chr = "#"c OrElse _                chr = ","c OrElse _                chr = "."c OrElse _                chr = ":"c    End Function    Private Function IsCombiningCharacter(ByVal chr As Char) As Boolean        'CombiningCharacter ::= < Unicode combining character (classes Mn, Mc) >        Select Case Char.GetUnicodeCategory(chr)            Case Globalization.UnicodeCategory.NonSpacingMark 'Mn                Return True            Case Globalization.UnicodeCategory.SpacingCombiningMark 'Mc                Return True            Case Else                Return False        End Select    End Function    Private Function IsFormattingCharacter(ByVal chr As Char) As Boolean        'FormattingCharacter ::= < Unicode formatting character (class Cf) >        Return Char.GetUnicodeCategory(chr) = Globalization.UnicodeCategory.Format 'Cf    End Function    Private Function IsAlphaCharacter(ByVal chr As Char) As Boolean        'AlphaCharacter ::= < Unicode alphabetic character (classes Lu, Ll, Lt, Lm, Lo, Nl) >        Select Case Char.GetUnicodeCategory(chr) 'Alpha Character            Case Globalization.UnicodeCategory.UppercaseLetter 'Lu                Return True            Case Globalization.UnicodeCategory.LowercaseLetter 'Ll                Return True            Case Globalization.UnicodeCategory.TitlecaseLetter  'Lt                Return True            Case Globalization.UnicodeCategory.ModifierLetter 'Lm                Return True            Case Globalization.UnicodeCategory.OtherLetter 'Lo                Return True            Case Globalization.UnicodeCategory.LetterNumber 'Nl                Return True            Case Else                Return False        End Select    End Function    Private Function IsLineContinuation() As Boolean        If Not (CurrentChar() = " "c AndAlso PeekChar() = "_"c) Then Return False        Dim i As Integer = 2        Do Until IsNewLine(PeekChars(i))            If IsWhiteSpace(PeekChars(i)) = False Then Return False            i += 1        Loop        Return True    End Function    Private Function IsWhiteSpace(ByVal chr As Char) As Boolean        Return chr = nlTab OrElse Char.GetUnicodeCategory(chr) = Globalization.UnicodeCategory.SpaceSeparator    End Function    Private Function IsWhiteSpace() As Boolean        Return IsWhiteSpace(CurrentChar())    End Function    Private Function IsComment(ByVal chr As Char) As Boolean        Return chr = COMMENTCHAR1 OrElse chr = COMMENTCHAR2 OrElse chr = COMMENTCHAR3    End Function    Private Function IsComment() As Boolean        Return IsComment(CurrentChar)    End Function    ''' <summary>    ''' Eat all characters until the newline character(s). Optionally eat the newline character(s) as well    ''' </summary>    ''' <param name="NewLineCharAlso"></param>    ''' <remarks></remarks>    Private Sub EatLine(ByVal NewLineCharAlso As Boolean)        'LineTerminator ::=        '  < Unicode carriage return character (0x000D) > |        '  < Unicode line feed character (0x000A) > |        '  < Unicode carriage return character > < Unicode line feed character > |        '  < Unicode line separator character (0x2028) > |        '  < Unicode paragraph separator character (0x2029) >        Dim ch As Char        Do            ch = NextChar()        Loop Until IsNewLine(ch)        If NewLineCharAlso Then            EatNewLine()        End If    End Sub    Private Sub EatNewLine()        Select Case CurrentChar()            Case nlD                NextChar()                If CurrentChar() = nlA Then                    NextChar()                End If                IncLine()            Case nlA, nl2029, nl2028                NextChar()                IncLine()            Case Else                Throw New InternalException("Current character is not a new line.")        End Select    End Sub    Private Sub EatComment()        Select Case CurrentChar()            Case COMMENTCHAR1, COMMENTCHAR2, COMMENTCHAR3 'Traditional VB comment                EatLine(False) 'do not eat newline, it needs to be added as a token                Return#If SUPPORT_CSTYLE_COMMENTS Then            Case "/"c 'C-style comment                NextChar()                Select Case CurrentChar()                    Case "/"c 'Single line comment                        EatLine(False) 'do not eat newline, it needs to be added as a token                        Return                    Case "*"c 'Nestable, multiline comment.                        Dim iNesting As Integer = 1                        NextChar()                        Do                            Select Case CurrentChar()                                Case "*"c                                    If PeekChar() = "/"c Then                                        'End of comment found (if iNesting is 0)                                        NextChar()                                        NextChar()                                        iNesting -= 1                                    Else                                        NextChar()                                    End If                                Case "/"c                                    If PeekChar() = "*"c Then                                        'a nested comment was found                                        NextChar()                                        iNesting += 1                                    ElseIf PeekChar() = "/"c Then                                        EatLine(True)                                    Else                                        NextChar()                                    End If                                Case nl0                                    Compiler.Report.ShowMessage(Messages.VBNC90022)                                    Return                                Case Else                                    If IsNewLine() Then                                        EatNewLine() 'To update the line variable                                    Else                                        NextChar()                                    End If                            End Select                        Loop While (iNesting <> 0)                    Case Else                        'Function should never be called if not a comment                        Throw New InternalException("EatComment called with no comment.")                End Select#End If

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?