Visual Basic 程式的編譯首先牽涉到將 Unicode 字元的原始數據流轉譯成一組已排序的語匯標記。 因為 Visual Basic 語言不是自由格式,因此令牌集接著會進一步分成一系列邏輯行。 邏輯行跨越從數據流開頭或行終止符到下一行終止符,前面沒有行接續或流結尾。
注意。 隨著語言 9.0 版的 XML 常值表達式的引進,Visual Basic 不再具有不同的語彙文法,也就是說,Visual Basic 程式代碼可以標記化,而不考慮語法內容。 這是因為 XML 和 Visual Basic 具有不同的語彙規則,而且在任何特定時間使用中的語彙規則集取決於目前正在處理的語法建構。 此規格會保留此語彙文法一節,作為一般Visual Basic程式碼語彙規則的指南。
LogicalLineStart
: LogicalLine*
;
LogicalLine
: LogicalLineElement* Comment? LineTerminator
;
LogicalLineElement
: WhiteSpace
| LineContinuation
| Token
;
Token
: Identifier
| Keyword
| Literal
| Separator
| Operator
;
字元和行
Visual Basic 程式是由 Unicode 字元集的字元所組成。
Character:
'<Any Unicode character except a LineTerminator>'
;
行終止符
Unicode 換行符分隔邏輯行。
LineTerminator
: '<Unicode 0x00D>'
| '<Unicode 0x00A>'
| '<CR>'
| '<LF>'
| '<Unicode 0x2028>'
| '<Unicode 0x2029>'
;
續行
行接續包含至少一個空格符,該字元緊接在單一底線字元前面做為文字行的最後一個字元(空格符以外的空格符)。 線條接續可讓邏輯行跨越多個實體行。 行接續會被視為空格符,即使不是。
LineContinuation
: WhiteSpace '_' WhiteSpace* LineTerminator
;
下列程式會顯示一些行接續:
Module Test
Sub Print( _
Param1 As Integer, _
Param2 As Integer )
If (Param1 < Param2) Or _
(Param1 > Param2) Then
Console.WriteLine("Not equal")
End If
End Function
End Module
語法文法中的某些位置允許 隱含行接續。 遇到行終止符時
在逗號 (
,), 左括弧 ((), 左大括弧 (), 或開啟內嵌運算式 ({<%=)在成員限定符 (或 或
.@...) 之後,.前提是某個專案已限定(亦即未使用隱含With內容)在右括弧之前 (
))、 緊大括弧 (), 或關閉內嵌運算式 (}%>)在屬性內容中小於 (
<) 之後在屬性內容中大於 (
>) 之前在非檔案層級屬性內容中大於 (
>) 之後查詢運算子前後(
Where、、OrderSelect等 )表達式內容中的二元運算符 (
+、-、/*等等) 之後在任何內容中,指派運算符 (
=、:=+=-=、 等等) 之後。
行終止符會被視為行接續。
Comma
: ',' LineTerminator?
;
Period
: '.' LineTerminator?
;
OpenParenthesis
: '(' LineTerminator?
;
CloseParenthesis
: LineTerminator? ')'
;
OpenCurlyBrace
: '{' LineTerminator?
;
CloseCurlyBrace
: LineTerminator? '}'
;
Equals
: '=' LineTerminator?
;
ColonEquals
: ':' '=' LineTerminator?
;
例如,上述範例也可以撰寫為:
Module Test
Sub Print(
Param1 As Integer,
Param2 As Integer)
If (Param1 < Param2) Or
(Param1 > Param2) Then
Console.WriteLine("Not equal")
End If
End Function
End Module
隱含行接續只會在指定的標記之前或之後直接推斷。 它們不會在行接續之前或之後推斷。 例如:
Dim y = 10
' Error: Expression expected for assignment to x
Dim x = _
y
行接續不會在條件式編譯內容中推斷。 (注意。 這是必要的最後一個限制,因為未編譯的條件式編譯區塊中的文字不必語法有效。因此,區塊中的文字可能會不小心被條件式編譯語句「挑選」,特別是隨著語言在未來的擴充而發生。
空格符
空格 元只能用於個別的令牌,否則會忽略。 只會忽略只包含空格符的邏輯行。 (注意。 行終止符不被視為空格符。
WhiteSpace
: '<Unicode class Zs>'
| '<Unicode Tab 0x0009>'
;
評論
註出開頭為單引號字元或關鍵字 REM。 單引號字元是 ASCII 單引號字元、Unicode 左單引號字元或 Unicode 右單引號字元。 批注可以從來源行的任何位置開始,而實體行結尾會結束批注。 編譯程式會忽略批注開頭與行終止符之間的字元。 因此,批注不能使用行接續跨多行延伸。
Comment
: CommentMarker Character*
;
CommentMarker
: SingleQuoteCharacter
| 'REM'
;
SingleQuoteCharacter
: '\''
| '<Unicode 0x2018>'
| '<Unicode 0x2019>'
;
識別碼
標識碼是名稱。 Visual Basic 識別符符合 Unicode 標準附件 15,但有一個例外:標識符開頭可能是底線(連接器)字元。 如果標識碼以底線開頭,它至少必須包含一個其他有效的標識符字元,才能從行接續中釐清它。
Identifier
: NonEscapedIdentifier TypeCharacter?
| Keyword TypeCharacter
| EscapedIdentifier
;
NonEscapedIdentifier
: '<Any IdentifierName but not Keyword>'
;
EscapedIdentifier
: '[' IdentifierName ']'
;
IdentifierName
: IdentifierStart IdentifierCharacter*
;
IdentifierStart
: AlphaCharacter
| UnderscoreCharacter IdentifierCharacter
;
IdentifierCharacter
: UnderscoreCharacter
| AlphaCharacter
| NumericCharacter
| CombiningCharacter
| FormattingCharacter
;
AlphaCharacter
: '<Unicode classes Lu,Ll,Lt,Lm,Lo,Nl>'
;
NumericCharacter
: '<Unicode decimal digit class Nd>'
;
CombiningCharacter
: '<Unicode combining character classes Mn, Mc>'
;
FormattingCharacter
: '<Unicode formatting character class Cf>'
;
UnderscoreCharacter
: '<Unicode connection character class Pc>'
;
IdentifierOrKeyword
: Identifier
| Keyword
;
一般標識碼可能不符合關鍵詞,但具有類型字元的逸出標識碼或標識碼可以。 逸出標識碼是以方括號分隔的標識碼。 逸出標識碼遵循與一般標識符相同的規則,不同之處在於它們可能符合關鍵詞,而且可能沒有類型字元。
此範例會使用名為 的共用方法定義名為 class 的類別,該方法會採用名為 booleanshared 的參數,然後呼叫 方法。
Class [class]
Shared Sub [shared]([boolean] As Boolean)
If [boolean] Then
Console.WriteLine("true")
Else
Console.WriteLine("false")
End If
End Sub
End Class
Module [module]
Sub Main()
[class].[shared](True)
End Sub
End Module
標識元不區分大小寫,因此兩個標識碼只有在大小寫時才會被視為相同的標識碼。 (注意。 比較標識符和任何地區設定特定案例對應時,會使用 Unicode 標準一對一案例對應。
類型字元
類型字元表示上述識別碼的類型。 類型字元不會被視為標識碼的一部分。
TypeCharacter
: IntegerTypeCharacter
| LongTypeCharacter
| DecimalTypeCharacter
| SingleTypeCharacter
| DoubleTypeCharacter
| StringTypeCharacter
;
IntegerTypeCharacter
: '%'
;
LongTypeCharacter
: '&'
;
DecimalTypeCharacter
: '@'
;
SingleTypeCharacter
: '!'
;
DoubleTypeCharacter
: '#'
;
StringTypeCharacter
: '$'
;
如果宣告包含類型字元,則類型字元必須與宣告本身中指定的類型一致;否則,會發生編譯時期錯誤。 如果宣告省略類型 (例如,如果它未指定 As 子句),則類型字元會隱含取代為宣告的類型。
標識元與其類型字元之間沒有空格符。 由於缺少適當的字元,所以、SByte、UShort、 ShortUInteger 或 ULong沒有類型字元Byte。
將類型字元附加至在概念上沒有型別的標識元(例如命名空間名稱)或類型與類型字元類型不符的標識符,會造成編譯時期錯誤。
下列範例顯示字元類型的用法:
' The follow line will cause an error: standard modules have no type.
Module Test1#
End Module
Module Test2
' This function takes a Long parameter and returns a String.
Function Func$(Param&)
' The following line causes an error because the type character
' conflicts with the declared type of Func and Param.
Func# = CStr(Param@)
' The following line is valid.
Func$ = CStr(Param&)
End Function
End Module
類型字元 ! 會呈現特殊問題,因為它可以同時做為類型字元和語言中的分隔符。 若要移除模棱兩可,只要後面的字元無法啟動標識符, ! 字元就是類型字元。 如果可以,則 ! 字元是分隔符,而不是類型字元。
關鍵字
關鍵詞是語言建構中具有特殊意義的單字。 所有關鍵詞都會由語言保留,而且除非逸出標識符,否則不得做為標識碼使用。 (注意.EndIf、、GoSub、 VariantLet和 Wend 會保留為關鍵詞,不過它們不再用於Visual Basic中。
Keyword
: 'AddHandler' | 'AddressOf' | 'Alias' | 'And'
| 'AndAlso' | 'As' | 'Boolean' | 'ByRef'
| 'Byte' | 'ByVal' | 'Call' | 'Case'
| 'Catch' | 'CBool' | 'CByte' | 'CChar'
| 'CDate' | 'CDbl' | 'CDec' | 'Char'
| 'CInt' | 'Class' | 'CLng' | 'CObj'
| 'Const' | 'Continue' | 'CSByte' | 'CShort'
| 'CSng' | 'CStr' | 'CType' | 'CUInt'
| 'CULng' | 'CUShort' | 'Date' | 'Decimal'
| 'Declare' | 'Default' | 'Delegate' | 'Dim'
| 'DirectCast' | 'Do' | 'Double' | 'Each'
| 'Else' | 'ElseIf' | 'End' | 'EndIf'
| 'Enum' | 'Erase' | 'Error' | 'Event'
| 'Exit' | 'False' | 'Finally' | 'For'
| 'Friend' | 'Function' | 'Get' | 'GetType'
| 'GetXmlNamespace' | 'Global' | 'GoSub' | 'GoTo'
| 'Handles' | 'If' | 'Implements' | 'Imports'
| 'In' | 'Inherits' | 'Integer' | 'Interface'
| 'Is' | 'IsNot' | 'Let' | 'Lib'
| 'Like' | 'Long' | 'Loop' | 'Me'
| 'Mod' | 'Module' | 'MustInherit' | 'MustOverride'
| 'MyBase' | 'MyClass' | 'Namespace' | 'Narrowing'
| 'New' | 'Next' | 'Not' | 'Nothing'
| 'NotInheritable' | 'NotOverridable' | 'Object' | 'Of'
| 'On' | 'Operator' | 'Option' | 'Optional'
| 'Or' | 'OrElse' | 'Overloads' | 'Overridable'
| 'Overrides' | 'ParamArray' | 'Partial' | 'Private'
| 'Property' | 'Protected' | 'Public' | 'RaiseEvent'
| 'ReadOnly' | 'ReDim' | 'REM' | 'RemoveHandler'
| 'Resume' | 'Return' | 'SByte' | 'Select'
| 'Set' | 'Shadows' | 'Shared' | 'Short'
| 'Single' | 'Static' | 'Step' | 'Stop'
| 'String' | 'Structure' | 'Sub' | 'SyncLock'
| 'Then' | 'Throw' | 'To' | 'True'
| 'Try' | 'TryCast' | 'TypeOf' | 'UInteger'
| 'ULong' | 'UShort' | 'Using' | 'Variant'
| 'Wend' | 'When' | 'While' | 'Widening'
| 'With' | 'WithEvents' | 'WriteOnly' | 'Xor'
;
字面意義
常值是型別特定值的文字表示法。 常值類型包括布爾值、整數、浮點數、字串、字元和日期。
Literal
: BooleanLiteral
| IntegerLiteral
| FloatingPointLiteral
| StringLiteral
| CharacterLiteral
| DateLiteral
| Nothing
;
布爾常值
True 和 False 是對應至 true 和 false 狀態之型別的 Boolean 常值。
BooleanLiteral
: 'True' | 'False'
;
整數常值
整數常值可以是十進位 (base 10)、十六進位 (base 16), 或八進制 (base 8)。 十進位整數常值是十進位數的字串(0-9)。 十六進位常值 &H 後面接著十六進位數位字串(0-9、A-F)。 八進位常值 &O 後面接著八進位數位字串 (0-7)。 十進位常值直接代表整數常值的十進位值,而八進位和十六進位常值則代表整數常值的二進位值(因此為 &H8000S -32768,而不是溢位錯誤)。
IntegerLiteral
: IntegralLiteralValue IntegralTypeCharacter?
;
IntegralLiteralValue
: IntLiteral
| HexLiteral
| OctalLiteral
;
IntegralTypeCharacter
: ShortCharacter
| UnsignedShortCharacter
| IntegerCharacter
| UnsignedIntegerCharacter
| LongCharacter
| UnsignedLongCharacter
| IntegerTypeCharacter
| LongTypeCharacter
;
ShortCharacter
: 'S'
;
UnsignedShortCharacter
: 'US'
;
IntegerCharacter
: 'I'
;
UnsignedIntegerCharacter
: 'UI'
;
LongCharacter
: 'L'
;
UnsignedLongCharacter
: 'UL'
;
IntLiteral
: Digit+
;
HexLiteral
: '&' 'H' HexDigit+
;
OctalLiteral
: '&' 'O' OctalDigit+
;
Digit
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
;
HexDigit
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
;
OctalDigit
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7'
;
常值的類型取決於其值或下列類型字元。 如果未指定類型字元,則類型範圍 Integer 中的值會輸入為 Integer;超出範圍 Integer 的值會輸入為 Long。 如果整數常值的類型大小不足而無法保存整數常值,則編譯時間錯誤會產生。 (注意。 沒有的類型字元,因為最自然的字元 Byte 會是 B,這是十六進位常值中的合法字元。
Floating-Point 常值
浮點常值是整數常值,後面接著選擇性小數點(ASCII 句號字元)和 mantissa,以及選擇性基底 10 指數。 根據預設,浮點常值的類型 Double為 。
Single如果指定、 Double或 Decimal 類型字元,則常值為該類型。 如果浮點常值的類型大小不足,無法保存浮點常值,則編譯時間錯誤會產生。
注意。 值得注意的是, Decimal 數據類型可以編碼值中的尾端零。 規格目前不會對常值中的 Decimal 尾端零是否應接受編譯程式批注。
FloatingPointLiteral
: FloatingPointLiteralValue FloatingPointTypeCharacter?
| IntLiteral FloatingPointTypeCharacter
;
FloatingPointTypeCharacter
: SingleCharacter
| DoubleCharacter
| DecimalCharacter
| SingleTypeCharacter
| DoubleTypeCharacter
| DecimalTypeCharacter
;
SingleCharacter
: 'F'
;
DoubleCharacter
: 'R'
;
DecimalCharacter
: 'D'
;
FloatingPointLiteralValue
: IntLiteral '.' IntLiteral Exponent?
| '.' IntLiteral Exponent?
| IntLiteral Exponent
;
Exponent
: 'E' Sign? IntLiteral
;
Sign
: '+'
| '-'
;
字串常值
字串常值是零個或多個 Unicode 字元序列,開頭和結尾為 ASCII 雙引號字元、Unicode 左雙引號字元或 Unicode 右雙引號字元。 在字串中,兩個雙引號字元的序列是代表字串中雙引號的逸出序列。
StringLiteral
: DoubleQuoteCharacter StringCharacter* DoubleQuoteCharacter
;
DoubleQuoteCharacter
: '"'
| '<unicode left double-quote 0x201c>'
| '<unicode right double-quote 0x201D>'
;
StringCharacter
: '<Any character except DoubleQuoteCharacter>'
| DoubleQuoteCharacter DoubleQuoteCharacter
;
字串常數的類型 String 為 。
Module Test
Sub Main()
' This prints out: ".
Console.WriteLine("""")
' This prints out: a"b.
Console.WriteLine("a""b")
' This causes a compile error due to mismatched double-quotes.
Console.WriteLine("a"b")
End Sub
End Module
編譯程式允許以字串常值取代常數位符串表達式。 每個字串常值不一定會導致新的字串實例。 當使用二進位比較語意的兩個或多個字串常值會根據字串相等運算符出現在相同的程式中時,這些字串常值可能會參考相同的字元串實例。 例如,下列程序的輸出可能會傳回 True ,因為兩個常值可能參考相同的字串實例。
Module Test
Sub Main()
Dim a As Object = "he" & "llo"
Dim b As Object = "hello"
Console.WriteLine(a Is b)
End Sub
End Module
字元常值
字元常值代表類型的單一 Unicode 字元 Char 。 兩個雙引號字元是代表雙引號字元的逸出序列。
CharacterLiteral
: DoubleQuoteCharacter StringCharacter DoubleQuoteCharacter 'C'
;
Module Test
Sub Main()
' This prints out: a.
Console.WriteLine("a"c)
' This prints out: ".
Console.WriteLine(""""c)
End Sub
End Module
日期常值
日期常值代表以型別值 Date 表示的特定時間刻度。
DateLiteral
: '#' WhiteSpace* DateOrTime WhiteSpace* '#'
;
DateOrTime
: DateValue WhiteSpace+ TimeValue
| DateValue
| TimeValue
;
DateValue
: MonthValue '/' DayValue '/' YearValue
| MonthValue '-' DayValue '-' YearValue
;
TimeValue
: HourValue ':' MinuteValue ( ':' SecondValue )? WhiteSpace* AMPM?
| HourValue WhiteSpace* AMPM
;
MonthValue
: IntLiteral
;
DayValue
: IntLiteral
;
YearValue
: IntLiteral
;
HourValue
: IntLiteral
;
MinuteValue
: IntLiteral
;
SecondValue
: IntLiteral
;
AMPM
: 'AM' | 'PM'
;
常值可以同時指定日期與時間、只指定日期或時間。 如果省略日期值,則會假設公曆中的年 1 月 1 日。 如果省略時間值,則會假設上午 12:00:00。
為了避免在日期值中解譯年份值時發生問題,年份值不能是兩位數。 在表示第一個世紀 AD/CE 中的日期時,必須指定前置零。
您可以使用 24 小時值或 12 小時值來指定時間值;省略 AM 或 PM 的時間值假設為24小時值。 如果時間值省略分鐘,預設會使用常值 0 。 如果時間值省略秒,則預設會使用常值 0 。 如果省略分鐘和秒,則必須 AM 指定 或 PM 。 如果指定的日期值超出型別的範圍 Date ,就會發生編譯時期錯誤。
下列範例包含數個日期常值。
Dim d As Date
d = # 8/23/1970 3:45:39AM #
d = # 8/23/1970 # ' Date value: 8/23/1970 12:00:00AM.
d = # 3:45:39AM # ' Date value: 1/1/1 3:45:39AM.
d = # 3:45:39 # ' Date value: 1/1/1 3:45:39AM.
d = # 13:45:39 # ' Date value: 1/1/1 1:45:39PM.
d = # 1AM # ' Date value: 1/1/1 1:00:00AM.
d = # 13:45:39PM # ' This date value is not valid.
無
Nothing 是特殊的常值;它沒有類型,而且可轉換成類型系統中的所有類型,包括類型參數。 轉換成特定類型時,它相當於該類型的預設值。
Nothing
: 'Nothing'
;
分隔符
下列 ASCII 字元是分隔符:
Separator
: '(' | ')' | '{' | '}' | '!' | '#' | ',' | '.' | ':' | '?'
;
運算符字元
下列 ASCII 字元或字元序列代表運算子:
Operator
: '&' | '*' | '+' | '-' | '/' | '\\' | '^' | '<' | '=' | '>'
;