Direktif Praproscesing

Setelah file dianalisis secara leksikal, beberapa jenis pra-pemrosesan sumber terjadi. Yang paling penting, kompilasi bersyukur, menentukan sumber mana yang diproses oleh tata bahasa sintetis; dua jenis arahan lainnya -- arahan sumber eksternal dan arahan wilayah -- memberikan meta-information tentang sumber tetapi tidak berpengaruh pada kompilasi.

Kompilasi Kondisional

Kompilasi kondisional mengontrol apakah urutan baris logis diterjemahkan ke dalam kode aktual. Pada awal kompilasi kondisional, semua baris logis diaktifkan; namun, mengapit baris dalam pernyataan kompilasi bersyarat dapat secara selektif menonaktifkan baris tersebut dalam file, menyebabkannya diabaikan selama sisa proses kompilasi.

CCStart
    : CCStatement*
    ;

CCStatement
    : CCConstantDeclaration
    | CCIfGroup
    | LogicalLine
    ;

CCExpression
    : LiteralExpression
    | CCParenthesizedExpression
    | CCSimpleNameExpression
    | CCCastExpression
    | CCOperatorExpression
    | CCConditionalExpression
    ;

CCParenthesizedExpression
    : '(' CCExpression ')'
    ;

CCSimpleNameExpression
    : Identifier
    ;

CCCastExpression
    : 'DirectCast' '(' CCExpression ',' TypeName ')'
    | 'TryCast' '(' CCExpression ',' TypeName ')'
    | 'CType' '(' CCExpression ',' TypeName ')'
    | CastTarget '(' CCExpression ')'
    ;

CCOperatorExpression
    : CCUnaryOperator CCExpression
    | CCExpression CCBinaryOperator CCExpression
    ;

CCUnaryOperator
    : '+' | '-' | 'Not'
    ;

CCBinaryOperator
    : '+'     | '-'     | '*'   | '/'       | '\\'     | 'Mod' | '^' | '='
    | '<' '>' | '<'     | '>'   | '<' '='   | '>' '='  | '&'
    | 'And'   | 'Or'    | 'Xor' | 'AndAlso' | 'OrElse'
    | '<' '<' | '>' '>'
    ;

CCConditionalExpression
    : 'If' '(' CCExpression ',' CCExpression ',' CCExpression ')'
    | 'If' '(' CCExpression ',' CCExpression ')'
    ;

Misalnya, program

#Const A = True
#Const B = False

Class C

#If A Then
    Sub F()
    End Sub
#Else
    Sub G()
    End Sub
#End If

#If B Then
    Sub H()
    End Sub
#Else
    Sub I()
    End Sub
#End If

End Class

menghasilkan urutan token yang sama persis dengan program

Class C
    Sub F()
    End Sub

    Sub I()
    End Sub
End Class

Ekspresi konstanta yang diizinkan dalam direktif kompilasi bersyar adalah subset ekspresi konstanta umum.

Prapemrosedur memungkinkan spasi kosong dan kelanjutan baris eksplisit sebelum dan sesudah setiap token.

Direktif Konstanta Bersyarah

Pernyataan konstanta bersyarat menentukan konstanta yang ada dalam ruang deklarasi kompilasi bersyarat terpisah yang dilingkup ke file sumber.

CCConstantDeclaration
    : '#' 'Const' Identifier '=' CCExpression LineTerminator
    ;

Ruang deklarasi khusus karena tidak ada deklarasi eksplisit konstanta kompilasi bersyarat yang diperlukan -- konstanta bersyarat dapat didefinisikan secara implisit dalam arahan kompilasi bersyarat.

Sebelum diberi nilai, konstanta kompilasi bersyarah memiliki nilai Nothing. Ketika konstanta kompilasi bersyarah diberi nilai, yang harus berupa ekspresi konstanta, jenis konstanta menjadi jenis nilai yang ditetapkan untuknya. Konstanta kompilasi bersikala dapat didefinisikan ulang beberapa kali di seluruh file sumber.

Misalnya, kode berikut hanya mencetak string about to print value dan nilai Test.

Module M1
    Sub PrintValue(Test As Integer)

#Const DebugCode = True

#If DebugCode Then
        Console.WriteLine("about to print value")
#End If

#Const DebugCode = False

        Console.WriteLine(Test)

#If DebugCode Then
        Console.WriteLine("printed value")
#End If

    End Sub
End Module

Lingkungan kompilasi juga dapat menentukan konstanta bersyarat dalam ruang deklarasi kompilasi bersyarat.

Pengarah Kompilasi Bersyarat

Direktif kompilasi kondisional mengontrol kompilasi kondisional.

CCIfGroup
    : '#' 'If' CCExpression 'Then'? LineTerminator CCStatement*
    CCElseIfGroup* CCElseGroup? '#' 'End' 'If' LineTerminator
    ;

CCElseIfGroup
    : '#' ElseIf CCExpression 'Then'? LineTerminator CCStatement*
    ;

CCElseGroup
    : '#' 'Else' LineTerminator CCStatement*
    ;

Konstanta bersyar hanya dapat mereferensikan ekspresi konstanta dan konstanta kompilasi bersyar. Masing-masing ekspresi konstanta dalam satu grup kompilasi kondisional dievaluasi dan dikonversi ke Boolean jenis dalam urutan tekstual dari pertama hingga terakhir hingga salah satu ekspresi kondisional dievaluasi ke True. Jika ekspresi tidak dapat dikonversi ke Boolean, hasil kesalahan waktu kompilasi. Semantik permisif dan perbandingan string biner selalu digunakan saat mengevaluasi ekspresi konstanta kompilasi bersyarat, terlepas dari direktif atau pengaturan lingkungan kompilasi apa pun Option .

Semua baris yang diapit oleh grup, termasuk direktif kompilasi kondisional berlapis, dinonaktifkan kecuali untuk baris antara pernyataan yang berisi True ekspresi dan pernyataan kondisional grup berikutnya, atau baris antara Else pernyataan dan End If pernyataan jika Else muncul dalam grup dan semua ekspresi dievaluasi ke False.

Dalam contoh ini, panggilan ke WriteToLog dalam Trace arahan kompilasi kondisional tidak diproses karena arahan kompilasi kondisional di sekitarnya Debug mengevaluasi ke False.

#Const Debug = False   ' Debugging off
#Const Trace = True    ' Tracing on

Class PurchaseTransaction
    Sub Commit()

#If Debug Then
        CheckConsistency()
#If Trace Then
        WriteToLog(Me.ToString())
#End If
#End If
        ...
    End Sub
End Class

Arahan Sumber Eksternal

File sumber mungkin menyertakan arahan sumber eksternal yang menunjukkan pemetaan antara baris sumber dan teks di luar sumber.

ESDStart
    : ExternalSourceStatement*
    ;

ExternalSourceStatement
    : ExternalSourceGroup
    | LogicalLine
    ;

ExternalSourceGroup
    : '#' 'ExternalSource' '(' StringLiteral ',' IntLiteral ')' LineTerminator
      LogicalLine* '#' 'End' 'ExternalSource' LineTerminator
    ;

Arahan sumber eksternal tidak berpengaruh pada kompilasi dan mungkin tidak disarangkan. Contohnya:

Module Test
    Sub Main()

#ExternalSource("c:\wwwroot\inetpub\test.aspx", 30)
        Console.WriteLine("In test.aspx")
#End ExternalSource

    End Sub
End Module

Arahan Wilayah

Direktif wilayah mengelompokkan baris kode sumber tetapi tidak memiliki efek lain pada kompilasi. Seluruh grup dapat diciutkan dan disembunyikan, atau diperluas dan dilihat, di lingkungan pengembangan terintegrasi (IDE).

RegionStart
    : RegionStatement*
    ;

RegionStatement
    : RegionGroup
    | LogicalLine
    ;

RegionGroup
    : '#' 'Region' StringLiteral LineTerminator
      RegionStatement*
      '#' 'End' 'Region' LineTerminator
    ;

Wilayah dapat ditumpuk. Arahan wilayah istimewa karena mereka tidak dapat memulai atau mengakhiri dalam isi metode, dan mereka harus menghormati struktur blok program. Contohnya:

Module Test
#Region "Startup code - do not edit"
    Sub Main()
    End Sub
#End Region

End Module


' Error due to Region directives breaking the block structure
Class C
#Region "Fred"
End Class
#End Region

Direktif Checksum Eksternal

File sumber dapat mencakup arahan checksum eksternal yang menunjukkan checksum apa yang harus dikeluarkan untuk file yang direferensikan dalam arahan sumber eksternal. Dalam semua hal lain, arahan sumber eksternal tidak berpengaruh pada kompilasi.

ExternalChecksumStart
    : ExternalChecksumStatement*
    ;

ExternalChecksumStatement
    : '#' 'ExternalChecksum' '('
      StringLiteral ',' StringLiteral ',' StringLiteral
      ')' LineTerminator
    ;

Direktif checksum eksternal berisi nama file eksternal, pengidentifikasi unik global (GUID) yang terkait dengan file dan checksum untuk file tersebut. GUID ditentukan sebagai konstanta string formulir "{xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxx}", di mana x adalah digit heksadesimal. Checksum ditentukan sebagai konstanta string formulir "xxxx...", di mana x adalah digit heksadesimal. Jumlah digit dalam checksum harus berupa angka genap.

File eksternal mungkin memiliki beberapa arahan checksum eksternal yang terkait dengannya asalkan semua nilai GUID dan checksum sama persis. Jika nama file eksternal cocok dengan nama file yang sedang dikompilasi, checksum diabaikan demi perhitungan checksum kompilator.

Contohnya:

#ExternalChecksum("c:\wwwroot\inetpub\test.aspx", _
    "{12345678-1234-1234-1234-123456789abc}", _
    "1a2b3c4e5f617239a49b9a9c0391849d34950f923fab9484")

Module Test
    Sub Main()

#ExternalSource("c:\wwwroot\inetpub\test.aspx", 30)
        Console.WriteLine("In test.aspx")
#End ExternalSource

    End Sub
End Module