Udostępnij przez


Gramatyka leksykalna

Najpierw kompilacja programu Visual Basic obejmuje tłumaczenie nieprzetworzonego strumienia znaków Unicode na uporządkowany zestaw tokenów leksykalnych. Ponieważ język Języka Visual Basic nie jest formatem wolnym, zestaw tokenów jest następnie dalej podzielony na serię wierszy logicznych. Linia logiczna rozciąga się od początku strumienia lub końcowego wiersza do następnego wiersza terminatora, który nie jest poprzedzony kontynuacją wiersza lub do końca strumienia.

Uwaga. Wraz z wprowadzeniem wyrażeń literału XML w wersji 9.0 języka język Visual Basic nie ma już odrębnej gramatyki leksykalnej w tym sensie, że kod języka Visual Basic może być tokenizowany bez względu na kontekst składniowy. Wynika to z faktu, że język XML i Visual Basic mają różne reguły leksykalne, a zestaw reguł leksykalnych używanych w dowolnym momencie zależy od tego, jaka konstrukcja składniowa jest przetwarzana w tej chwili. Ta specyfikacja zachowuje tę sekcję gramatyki leksykalnej jako przewodnik po regułach leksykalnych zwykłego kodu Języka Visual Basic.

LogicalLineStart
    : LogicalLine*
    ;

LogicalLine
    : LogicalLineElement* Comment? LineTerminator
    ;

LogicalLineElement
    : WhiteSpace
    | LineContinuation
    | Token
    ;

Token
    : Identifier
    | Keyword
    | Literal
    | Separator
    | Operator
    ;

Znaki i wiersze

Programy Visual Basic składają się z znaków z zestawu znaków Unicode.

Character:
    '<Any Unicode character except a LineTerminator>'
    ;

Terminatory wierszy

Znaki podziału wierszy Unicode oddzielają wiersze logiczne.

LineTerminator
    : '<Unicode 0x00D>'
    | '<Unicode 0x00A>'
    | '<CR>'
    | '<LF>'
    | '<Unicode 0x2028>'
    | '<Unicode 0x2029>'
    ;

Kontynuacja wiersza

Kontynuacja wiersza składa się z co najmniej jednego znaku odstępu, który bezpośrednio poprzedza pojedynczy znak podkreślenia jako ostatni znak (inny niż biały znak) w wierszu tekstu. Kontynuacja linii umożliwia linii logicznej obejmującej więcej niż jedną linię fizyczną. Kontynuacje linii są traktowane tak, jakby były białym znakiem, mimo że nie są.

LineContinuation
    : WhiteSpace '_' WhiteSpace* LineTerminator
    ;

W poniższym programie przedstawiono niektóre kontynuacje wierszy:

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

Niektóre miejsca w gramatyce składniowej umożliwiają niejawne kontynuacje wierszy. Po napotkaniu terminatora wiersza

  • po przecinkach (,(), otwórz nawias (), otwórz nawias klamrowy ({) lub otwórz osadzone wyrażenie (<%=)

  • po kwalifikatorze elementu członkowskiego (. lub .@...) pod warunkiem, że coś jest kwalifikowane (tj. nie używa kontekstu niejawnego With )

  • przed nawiasem zamykanym ()), zamknij nawias klamrowy (}) lub zamknij osadzone wyrażenie (%>)

  • po mniejszej niż (<) w kontekście atrybutu

  • przed wartością większą niż (>) w kontekście atrybutu

  • po wartości większej niż (>) w kontekście atrybutu innego niż plik

  • przed i po operatorach zapytań (Where, Order, Selectitp.)

  • po operatorach binarnych (+, -, /, *itp.) w kontekście wyrażenia

  • po operatorach przypisania (=, :=, +=, -=itp.) w dowolnym kontekście.

terminator wiersza jest traktowany tak, jakby był kontynuacją wiersza.

Comma
    : ',' LineTerminator?
    ;

Period
    : '.' LineTerminator?
    ;

OpenParenthesis
    : '(' LineTerminator?
    ;

CloseParenthesis
    : LineTerminator? ')'
    ;

OpenCurlyBrace
    : '{' LineTerminator?
    ;

CloseCurlyBrace
    : LineTerminator? '}'
    ;

Equals
    : '=' LineTerminator?
    ;

ColonEquals
    : ':' '=' LineTerminator?
    ;

Na przykład poprzedni przykład można również napisać jako:

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

Niejawne kontynuacje wierszy będą zawsze wnioskowane bezpośrednio przed określonym tokenem lub po nim. Nie zostaną one wywnioskowane przed ani po kontynuacji wiersza. Przykład:

Dim y = 10
' Error: Expression expected for assignment to x
Dim x = _

y

Kontynuacje wierszy nie zostaną wywnioskowane w kontekstach kompilacji warunkowej. (Uwaga. To ostatnie ograniczenie jest wymagane, ponieważ tekst w blokach kompilacji warunkowej, które nie są skompilowane, nie muszą być prawidłowe składniowo. W związku z tym tekst w bloku może zostać przypadkowo odebrany przez instrukcję kompilacji warunkowej, zwłaszcza gdy język zostanie rozszerzony w przyszłości.

Odstępu

Biały znak służy tylko do oddzielania tokenów i w przeciwnym razie jest ignorowany. Linie logiczne zawierające tylko białe znaki są ignorowane. (Uwaga. Terminatory wierszy nie są uznawane za białe znaki).

WhiteSpace
    : '<Unicode class Zs>'
    | '<Unicode Tab 0x0009>'
    ;

Komentarze

Komentarz zaczyna się od znaku pojedynczego cudzysłowu lub słowa kluczowego REM. Znak pojedynczego cudzysłowu jest znakiem pojedynczego cudzysłowu ASCII, znakiem pojedynczego cudzysłowu Unicode lub znakiem pojedynczego cudzysłowu Unicode. Komentarze mogą zaczynać się w dowolnym miejscu w wierszu źródłowym, a koniec linii fizycznej kończy komentarz. Kompilator ignoruje znaki między początkiem komentarza a terminatorem wiersza. W związku z tym komentarze nie mogą rozciągać się na wiele wierszy przy użyciu kontynuacji wierszy.

Comment
    : CommentMarker Character*
    ;

CommentMarker
    : SingleQuoteCharacter
    | 'REM'
    ;

SingleQuoteCharacter
    : '\''
    | '<Unicode 0x2018>'
    | '<Unicode 0x2019>'
    ;

Identyfikatory

Identyfikator jest nazwą. Identyfikatory języka Visual Basic są zgodne z załącznikiem Standard Unicode 15 z jednym wyjątkiem: identyfikatory mogą zaczynać się od znaku podkreślenia (łącznika). Jeśli identyfikator zaczyna się od podkreślenia, musi zawierać co najmniej jeden inny prawidłowy znak identyfikatora, aby uściślić go z kontynuacji wiersza.

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
    ;

Zwykłe identyfikatory mogą nie być zgodne ze słowami kluczowymi, ale identyfikatory lub identyfikatory z znakiem typu mogą. Identyfikator ucieczki jest identyfikatorem rozdzielonym nawiasami kwadratowymi. Identyfikatory ucieczki są zgodne z tymi samymi regułami co zwykłe identyfikatory, z tą różnicą, że mogą być zgodne ze słowami kluczowymi i mogą nie mieć znaków typu.

W tym przykładzie zdefiniowano klasę o nazwie z class udostępnioną metodą o nazwie shared , która przyjmuje parametr o nazwie boolean , a następnie wywołuje metodę.

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

Identyfikatory są niewrażliwe na wielkość liter, więc dwa identyfikatory są uważane za ten sam identyfikator, jeśli różnią się tylko w przypadku. (Uwaga. Mapowania przypadków w standardzie Unicode jeden do jednego są używane podczas porównywania identyfikatorów i mapowań przypadków specyficznych dla ustawień regionalnych są ignorowane).

Znaki typu

Znak typu określa typ poprzedniego identyfikatora. Znak typu nie jest uważany za część identyfikatora.

TypeCharacter
    : IntegerTypeCharacter
    | LongTypeCharacter
    | DecimalTypeCharacter
    | SingleTypeCharacter
    | DoubleTypeCharacter
    | StringTypeCharacter
    ;

IntegerTypeCharacter
    : '%'
    ;

LongTypeCharacter
    : '&'
    ;

DecimalTypeCharacter
    : '@'
    ;

SingleTypeCharacter
    : '!'
    ;

DoubleTypeCharacter
    : '#'
    ;

StringTypeCharacter
    : '$'
    ;

Jeśli deklaracja zawiera znak typu, znak typu musi być zgodny z typem określonym w samej deklaracji; w przeciwnym razie występuje błąd czasu kompilacji. Jeśli deklaracja pomija typ (na przykład jeśli nie określa As klauzuli), znak typu jest niejawnie zastępowany jako typ deklaracji.

Nie może występować odstęp między identyfikatorem a znakiem typu. Brak znaków typu dla Byteznaków , , SByteUShort, ShortUInteger lub , ULongz powodu braku odpowiednich znaków.

Dołączanie znaku typu do identyfikatora, który koncepcyjnie nie ma typu (na przykład nazwy przestrzeni nazw) lub identyfikatora, którego typ nie zgadza się z typem znaku typu powoduje błąd czasu kompilacji.

W poniższym przykładzie pokazano użycie znaków typu:

' 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

Znak ! typu przedstawia specjalny problem, ponieważ może być używany zarówno jako znak typu, jak i jako separator w języku. Aby usunąć niejednoznaczność, ! znak jest znakiem typu, o ile znak, który następuje po nim, nie może uruchomić identyfikatora. Jeśli to możliwe, ! znak jest separatorem, a nie znakiem typu.

Słowa kluczowe

Słowo kluczowe to słowo, które ma specjalne znaczenie w konstrukcji językowej. Wszystkie słowa kluczowe są zastrzeżone przez język i mogą nie być używane jako identyfikatory, chyba że identyfikatory zostaną uniknięci. (Uwaga.EndIf, , LetGoSub, Varianti Wend są zachowywane jako słowa kluczowe, chociaż nie są już używane w języku 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'         
    ;

Wartości stałe

Literał to tekstowa reprezentacja określonej wartości typu. Typy literałów obejmują wartość logiczną, liczbę całkowitą, zmiennoprzecinkową, ciąg, znak i datę.

Literal
    : BooleanLiteral
    | IntegerLiteral
    | FloatingPointLiteral
    | StringLiteral
    | CharacterLiteral
    | DateLiteral
    | Nothing
    ;

Literały logiczne

True i False są literałami Boolean typu, który mapuje odpowiednio na stan true i false.

BooleanLiteral
    : 'True' | 'False'
    ;

Literały liczb całkowitych

Literały liczb całkowitych mogą być dziesiętne (podstawa 10), szesnastkowe (podstawa 16) lub ósemkowe (podstawa 8). Literał liczb całkowitych dziesiętnych to ciąg cyfr dziesiętnych (0–9). Literał szesnastkowy następuje &H ciąg cyfr szesnastkowych (0–9, A-F). Literał ósemkowy następuje &O ciąg cyfr ósemkowych (0–7). Literały dziesiętne bezpośrednio reprezentują wartość dziesiętną literału całkowitego, natomiast literały ósemkowe i szesnastkowe reprezentują wartość binarną literału liczby całkowitej (w związku z tym &H8000S jest to -32768, a nie błąd przepełnienia).

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'
    ;

Typ literału jest określany przez jego wartość lub przez następujący znak typu. Jeśli nie określono znaku typu, wartości w zakresie Integer typu są wpisywane jako Integer; wartości spoza zakresu dla Integer są wpisywane jako Long. Jeśli typ literału liczby całkowitej jest niewystarczający do przechowywania literału liczby całkowitej, wynik błędu czasu kompilacji. (Uwaga. Nie ma znaku typu, Byte ponieważ najbardziej naturalny znak to B, który jest znakiem prawnym literału szesnastkowym).

literały Floating-Point

Literał zmiennoprzecinkowy to literał liczby całkowitej, po którym następuje opcjonalny punkt dziesiętny (znak kropki ASCII) i mantissa oraz opcjonalny wykładnik base 10. Domyślnie literał zmiennoprzecinkowa ma typ Double. SingleJeśli określono znak , Doublelub Decimal typu, literał jest tego typu. Jeśli typ literału zmiennoprzecinkowego jest niewystarczający do przechowywania literału zmiennoprzecinkowego, wynik błędu czasu kompilacji.

Uwaga. Warto zauważyć, że Decimal typ danych może kodować końcowe zera w wartości. Specyfikacja nie komentuje obecnie, czy końcowe zera w Decimal literału powinny być honorowane przez kompilator.

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
    : '+'
    | '-'
    ;

Literały tekstowe

Literał ciągu to sekwencja zero lub więcej znaków Unicode rozpoczynających się i kończących się znakiem podwójnego cudzysłowu ASCII, znakiem podwójnego cudzysłowu Unicode lub znakiem podwójnego cudzysłowu Unicode. W ciągu sekwencja dwóch znaków podwójnego cudzysłowu jest sekwencją ucieczki reprezentującą podwójny cudzysłów w ciągu.

StringLiteral
    : DoubleQuoteCharacter StringCharacter* DoubleQuoteCharacter
    ;

DoubleQuoteCharacter
    : '"'
    | '<unicode left double-quote 0x201c>'
    | '<unicode right double-quote 0x201D>'
    ;

StringCharacter
    : '<Any character except DoubleQuoteCharacter>'
    | DoubleQuoteCharacter DoubleQuoteCharacter
    ;

Stała ciągu jest typu 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

Kompilator może zastąpić wyrażenie ciągu stałego literałem ciągu. Każdy literał ciągu nie musi powodować wystąpienia nowego ciągu. Gdy co najmniej dwa literały ciągu, które są równoważne operatorowi równości ciągów przy użyciu semantyki porównania binarnego, te literały ciągu mogą odwoływać się do tego samego wystąpienia ciągu. Na przykład dane wyjściowe następującego programu mogą zostać zwrócone True , ponieważ dwa literały mogą odwoływać się do tego samego wystąpienia ciągu.

Module Test
    Sub Main()
        Dim a As Object = "he" & "llo"
        Dim b As Object = "hello"
        Console.WriteLine(a Is b)
    End Sub
End Module

Literały znaków

Literał znaku reprezentuje pojedynczy znak Char Unicode typu. Dwa znaki podwójnego cudzysłowu to sekwencja ucieczki reprezentująca znak podwójnego cudzysłowu.

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

Literały daty

Literał daty reprezentuje określony moment w czasie wyrażony jako wartość Date typu.

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'
    ;    

Literał może określać zarówno datę, jak i godzinę, tylko datę lub tylko godzinę. Jeśli wartość daty zostanie pominięta, zakłada się, że przyjmuje się 1 stycznia roku 1 w kalendarzu gregoriańskim. Jeśli wartość czasu zostanie pominięta, zakłada się, że przyjmuje się 12:00:00.

Aby uniknąć problemów z interpretowaniem wartości roku w wartości daty, wartość roku nie może być dwiema cyframi. Podczas wyrażania daty w pierwszym wieku AD/CE należy określić zera wiodące.

Wartość godziny można określić przy użyciu wartości 24-godzinnej lub 12-godzinnej; wartości czasu, które pomijają AM wartości lub PM są zakładane jako wartości 24-godzinne. Jeśli wartość godziny pomija minuty, literał 0 jest używany domyślnie. Jeśli wartość czasu pomija sekundy, literał 0 jest używany domyślnie. Jeśli pominięto zarówno minutę, jak i sekundę, AM należy określić wartość lub PM . Jeśli określona wartość daty znajduje się poza zakresem Date typu, wystąpi błąd czasu kompilacji.

Poniższy przykład zawiera kilka literałów daty.

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.

Nic

Nothing jest specjalnym literałem; nie ma typu i jest konwertowany na wszystkie typy w systemie typów, w tym parametry typu. Po przekonwertowaniu na określony typ jest odpowiednikiem wartości domyślnej tego typu.

Nothing
    : 'Nothing'
    ;

Separatory

Następujące znaki ASCII to separatory:

Separator
    : '(' | ')' | '{' | '}' | '!' | '#' | ',' | '.' | ':' | '?'
    ;

Znaki operatora

Następujące znaki ASCII lub sekwencje znaków oznaczają operatory:

Operator
    : '&' | '*' | '+' | '-' | '/' | '\\' | '^' | '<' | '=' | '>'
    ;