6 Sözcük yapısı
6.1 Programları
C# programı, derleme birimi (§14.2) olarak bilinen bir veya daha fazla kaynak dosyadan oluşur. Derleme biriminin dosya sistemindeki bir dosyayla birebir yazışması olsa da, bu tür bir yazışma gerekli değildir.
Kavramsal olarak bakıldığında, bir program üç adım kullanılarak derlenmiş:
- Dönüştürme, bir dosyayı belirli bir karakter repertuarından ve kodlama düzeninden Unicode karakter dizisine dönüştürür.
- Unicode giriş karakterleri akışını belirteç akışına çeviren sözcük temelli analiz.
- Belirteç akışını yürütülebilir koda çeviren bozulma analizi.
Uyumlu uygulamalar UTF-8 kodlama formuyla kodlanmış Unicode derleme birimlerini kabul edecektir (Unicode standardı tarafından tanımlandığı gibi) ve bunları unicode karakter dizisine dönüştürecektir. Uygulamalar ek karakter kodlama düzenlerini (UTF-16, UTF-32 veya Unicode olmayan karakter eşlemeleri gibi) kabul etmeyi ve dönüştürmeyi seçebilir.
Not: Unicode NULL karakterinin (U+0000) işlenmesi uygulama tanımlıdır. Geliştiricilerin hem taşınabilirlik hem de okunabilirlik açısından kaynak kodlarında bu karakteri kullanmaktan kaçınmaları kesinlikle önerilir. Karakter veya dize değişmez değeri içinde karakter gerekli olduğunda, kaçış dizileri
\0
veya\u0000
bunun yerine kullanılabilir. son not
Not: Unicode dışında bir karakter gösterimi kullanan bir dosyanın unicode karakter dizisine nasıl dönüştürülebileceğini tanımlamak bu belirtim kapsamının dışındadır. Ancak bu tür dönüştürme sırasında, diğer karakter kümesindeki normal satır ayırma karakterinin (veya sırasının), Unicode satır başı karakterinden (U+000D) ve ardından Unicode satır besleme karakterinden (U+000A) oluşan iki karakterli diziye çevrilmesi önerilir. Çoğunlukla bu dönüşümün görünür bir etkisi olmayacaktır; ancak, düz metin dize değişmez belirteçlerinin (§6.4.5.6) yorumlanmasını etkiler. Bu önerinin amacı, özellikle de satır ayrımı için farklı karakter dizileri kullanan farklı Unicode olmayan karakter kümelerini destekleyen sistemler arasında derleme birimi taşındığında, düz metin dizesi değişmez değerlerinin aynı karakter dizisini üretmesine izin vermektir. son not
6.2 Dil Bilgisi
6.2.1 Genel
Bu belirtim, iki dil bilgisi kullanarak C# programlama dilinin söz dizimini sunar. Sözcük temelli dil bilgisi (§6.2.3), Unicode karakterlerin satır sonlandırıcıları, boşluk, açıklamalar, belirteçler ve ön işleme yönergelerini oluşturmak için nasıl birleştirildiği tanımlar. İlgili dil bilgisi (§6.2.4), sözcük temelli dil bilgisinden kaynaklanan belirteçlerin C# programları oluşturmak için nasıl birleştirildiği tanımlar.
Tüm terminal karakterleri, diğer Unicode karakter aralıklarından benzer görünen karakterler yerine U+0020 ile U+007F aralığından uygun Unicode karakter olarak anlaşılmalıdır.
6.2.2 Dil bilgisi gösterimi
Sözcük temelli ve yazımsal dil bilgisi, ANTLR dil bilgisi aracının Genişletilmiş Backus-Naur formunda sunulur.
ANTLR gösterimi kullanılırken, bu belirtim C# için ANTLR'ye hazır tam bir "başvuru dil bilgisi" sunmaz; el ile veya ANTLR gibi bir araç kullanarak sözcük oluşturucu ve ayrıştırıcı yazma, dil belirtiminin kapsamı dışındadır. Bu nitelemeyle, bu belirtim belirtilen dil bilgisi ile ANTLR'de bir sözcük oluşturucu ve ayrıştırıcı oluşturmak için gereken arasındaki boşluğu en aza indirmeyi dener.
ANTLR, büyük harfle sözcüksel kurallar ve küçük harfli ayrıştırıcı kuralları başlatarak ANTLR tarafından terimleştirilmiş, antlr tarafından terimleştirilmiş ayrıştırıcı, gösterimindeki dil bilgisi değerlerini birbirinden ayırır.
Not: C# sözcüksel dil bilgisi (§6.2.3) ve bozulmamış dil bilgisi (§6.2.4), ANTLR'nin sözcük temelli ve ayrıştırıcı gramerlere bölünmesiyle tam olarak eşleşmez. Bu küçük uyuşmazlık, C# sözcük bilgisi belirtilirken bazı ANTLR ayrıştırıcı kurallarının kullanıldığı anlamına gelir. son not
6.2.3 Sözcük dil bilgisi
C# sözcüksel dil bilgisi §6.3, §6.4 ve §6.5'te sunulur. Sözcük temelli dil bilgisinin terminal simgeleri Unicode karakter kümesinin karakterleridir ve sözcük temelli dil bilgisi, karakterlerin belirteçler (§6.4), boşluk (§6.3.4), açıklamalar (§6.3.3) ve ön işleme yönergeleri (§6.5) oluşturmak için nasıl birleştirildiği belirtir.
Yazımsal dil bilgisinin terminal simgelerinden çoğu, sözcük temelli dil bilgisi içinde belirteç olarak açıkça tanımlanmaz. Bunun yerine, dilbilgisindeki değişmez dizelerin örtük sözcük temelli belirteçler olarak ayıklanması anTLR davranışından yararlanılır; bu, anahtar sözcüklerin, işleçlerin vb. dil bilgisi içinde belirteç adı yerine değişmez değer gösterimiyle temsil edilmesini sağlar.
Bir C# programındaki her derleme birimi, sözcük temelli dil bilgisinin (§6.3.1) giriş üretimine uygun olmalıdır.
6.2.4 Bozulmamış dil bilgisi
C# öğesinin söz dizimsel dil bilgisi, bu alt uyarıyı izleyen yan tümcelerde, alt tümcelerde ve eklerde sunulur. Söz dizimsel dil bilgisinin terminal simgeleri, sözcük temelli dil bilgisi tarafından açıkça tanımlanan ve dilbilgisinin kendisindeki değişmez dizelerle örtük olarak tanımlanan belirteçlerdir (§6.2.3). İlgili dil bilgisi, belirteçlerin C# programlarını oluşturmak için nasıl birleştirildiği belirtir.
C# programındaki her derleme birimi söz diziminin compilation_unit üretimine (§14.2) uygun olmalıdır.
6.2.5 Dil bilgisi belirsizlikleri
simple_name (§12.8.4) ve member_access (§12.8.7) üretimleri, ifadeler için dil bilgisi belirsizliği doğurabilir.
Örnek: Deyimi:
F(G<A, B>(7));
, ve
F
olmak üzere iki bağımsız değişkenleG < A
çağrısıB > (7)
olarak yorumlanabilir. Alternatif olarak, iki tür bağımsız değişken ve birF
normal bağımsız değişken içeren genel bir yöntemeG
yapılan çağrı olan bir bağımsız değişken ile çağrısı olarak yorumlanabilir.son örnek
Belirteç dizisi simple_name (§12.8.4), member_access (§12.8.7>
-
( ) ] } : ; , . ? == != | ^ && || & [
bunlardan biri veya - İlişkisel işleçlerden
< <= >= is as
biri ; veya - Sorgu ifadesinin içinde görünen bağlamsal sorgu anahtar sözcüğü; veya
- Belirli bağlamlarda tanımlayıcı, kesinleştirme belirteci olarak değerlendirilir. Bu bağlamlar, kesinleştirilmiş belirteç dizisinin hemen önce anahtar sözcüklerinden
is
case
biri veya veya olur ya daout
bir tanımlama grubu değişmez değerinin ilk öğesi ayrıştırılırken ortaya çıkar (bu durumda belirteçlerin başına(
veya tanımlayıcısı:
gelir) ya da,
bir demet değişmez değerinin sonraki bir öğesidir.
Aşağıdaki belirteç bu liste arasındaysa veya bu bağlamda bir tanımlayıcıysa, type_argument_list simple_name, member_access veya pointer_member erişimi kapsamında tutulur ve belirteç dizisinin diğer olası ayrıştırması atılır. Aksi takdirde, belirteç dizisinin başka bir olası ayrıştırması olmasa bile type_argument_list simple_name, member_access veya pointer_member_access parçası olarak kabul edilmez.
Not: Bu kurallar, namespace_or_type_name bir type_argument_listayrıştırılırken uygulanmaz (§7.8). son not
Örnek: Deyimi:
F(G<A, B>(7));
will, bu kurala göre, iki tür bağımsız değişken ve bir
F
normal bağımsız değişken içeren genel bir yöntemeG
yapılan çağrı olan bir bağımsız değişkenle çağrısı olarak yorumlanır. DeyimleriF(G<A, B>7); F(G<A, B>>7);
her bir çağrı olarak iki bağımsız değişkenle yorumlanır
F
. Deyimix = F<A> + y;
, deyimi yazılmış gibi küçüktür işleci, büyüktür işleci ve bire artı işleci olarak yorumlanır; bunun yerine, type_argument_list ve ardından ikili artı işleci olan bir simple_name
x = (F < A) > (+y)
olarak yazılır. deyimindex = y is C<T> && z;
belirteçler
C<T>
, type_argument_list sonra&&
olarak yorumlanır.İfade
(A < B, C > D)
, her biri bir karşılaştırma olmak üzere iki öğe içeren bir tanımlama grubudur.İfade
(A<B,C> D, E)
, ilki bildirim ifadesi olan iki öğe içeren bir tanımlama grubudur.Çağırmanın
M(A < B, C > D, E)
üç bağımsız değişkeni vardır.Çağırmanın
M(out A<B,C> D, E)
iki bağımsız değişkeni vardır ve bunlardan ilki birout
bildirimdir.İfade
e is A<B> C
bir bildirim deseni kullanır.Servis talebi etiketi
case A<B> C:
bir bildirim deseni kullanır.son örnek
Bir relational_expression tanınırken (§12.12.1) hem "relational_expression türü" hem de "relational_expression is
is
constant_pattern" alternatifleri geçerliyse ve tür erişilebilir bir türe çözümleniyorsa, "is
türü" alternatifi seçilmelidir.
6.3 Sözcük temelli analiz
6.3.1 Genel
Kolaylık sağlamak için sözcük temelli dil bilgisi aşağıdaki adlandırılmış lexer belirteçlerini tanımlar ve bunlara başvurur:
DEFAULT : 'default' ;
NULL : 'null' ;
TRUE : 'true' ;
FALSE : 'false' ;
ASTERISK : '*' ;
SLASH : '/' ;
Bunlar sözcük temelli kurallar olsa da, bu adlar normal sözcük denetleyicisi kural adlarından ayırt etmek için büyük harflerle yazılır.
Not: Bu kolaylık kuralları, değişmez değer dizeleri tarafından tanımlanan belirteçler için açık belirteç adları sağlamama normal uygulamasının özel durumlarıdır. son not
Giriş üretimi, C# derleme biriminin sözcüksel yapısını tanımlar.
input
: input_section?
;
input_section
: input_section_part+
;
input_section_part
: input_element* New_Line
| PP_Directive
;
input_element
: Whitespace
| Comment
| token
;
Not: Yukarıdaki dil bilgisi ANTLR ayrıştırma kuralları tarafından açıklanmıştır; sözcük temelli belirteçleri değil C# derleme biriminin sözcüksel yapısını tanımlar. son not
C# derleme biriminin sözcük temelli yapısını beş temel öğe oluşturur: Satır sonlandırıcıları (§6.3.2), boşluk (§6.3.4), açıklamalar (§6.3.3), belirteçler (§6.4) ve ön işleme yönergeleri (§6.5). Bu temel öğelerden yalnızca belirteçler C# programının söz diziminde (§6.2.4) önemlidir.
C# derleme biriminin sözcük temelli işlemesi, dosyanın söz dizimsel analizin girişi haline gelen bir belirteç dizisine indirgenmesini içerir. Satır sonlandırıcıları, boşluk ve açıklamalar ayrı belirteçlere hizmet edebilir ve ön işleme yönergeleri derleme biriminin bölümlerinin atlanmasına neden olabilir, ancak aksi takdirde bu sözcük öğeleri C# programının söz dizimi yapısını etkilemez.
Birkaç sözcük bilgisi üretimleri bir derleme birimindeki bir karakter dizisiyle eşleştiğinde, sözcük temelli işleme her zaman mümkün olan en uzun sözcük temelli öğeyi oluşturur.
Örnek: Sözcük temelli öğe tek bir belirteçten daha uzun olduğundan karakter dizisi
//
tek/
satırlı açıklamanın başlangıcı olarak işlenir. son örnek
Bazı belirteçler bir sözcük kuralları kümesi tarafından tanımlanır; bir ana kural ve bir veya daha fazla alt kural. İkincisi, kuralın başka bir belirtecin bir kısmını tanımladığı belirtmek için tarafından dil bilgisi fragment
içinde işaretlenir. Parça kuralları, sözcük temelli kuralların yukarıdan aşağıya sıralanmasında dikkate alınmaz.
Not: ANTLR'de
fragment
, burada tanımlanan davranışın aynısını üreten bir anahtar sözcüktür. son not
6.3.2 Çizgi sonlandırıcıları
Satır sonlandırıcıları, C# derleme biriminin karakterlerini satırlara böler.
New_Line
: New_Line_Character
| '\u000D\u000A' // carriage return, line feed
;
Dosya sonu işaretleyicileri ekleyen kaynak kodu düzenleme araçlarıyla uyumluluk sağlamak ve bir derleme biriminin düzgün şekilde sonlandırılan satır dizisi olarak görüntülenmesini sağlamak için, C# programındaki her derleme birimine sırayla aşağıdaki dönüştürmeler uygulanır:
- Derleme biriminin son karakteri bir Control-Z karakteri (U+001A) ise, bu karakter silinir.
- Derleme birimi boş değilse ve derleme biriminin son karakteri satır başı (U+000D), satır beslemesi (U+000A), sonraki satır karakteri (U+0085), satır ayırıcısı (U+2028) veya paragraf ayırıcısı (U+2029) değilse, derleme biriminin sonuna satır başı karakteri (U+000D) eklenir.
Not: Ek satır başı, programın sonlandırıcı New_Line olmayan bir PP_Directive (§6.5) ile bitmesini sağlar. son not
6.3.3 Yorumlar
İki açıklama biçimi desteklenir: sınırlandırılmış açıklamalar ve tek satırlı açıklamalar.
Sınırlandırılmış bir açıklama karakterlerle /*
başlar ve karakterleriyle */
biter. Sınırlandırılmış açıklamalar bir satırın bir bölümünü, tek bir satırı veya birden çok satırı kaplayabilir.
Örnek: Örnek
/* Hello, world program This program writes "hello, world" to the console */ class Hello { static void Main() { System.Console.WriteLine("hello, world"); } }
sınırlandırılmış bir açıklama içerir.
son örnek
Tek satırlı açıklama karakterlerle //
başlar ve satırın sonuna kadar uzanır.
Örnek: Örnek
// Hello, world program // This program writes "hello, world" to the console // class Hello // any name will do for this class { static void Main() // this method must be named "Main" { System.Console.WriteLine("hello, world"); } }
birkaç tek satırlı açıklama gösterir.
son örnek
Comment
: Single_Line_Comment
| Delimited_Comment
;
fragment Single_Line_Comment
: '//' Input_Character*
;
fragment Input_Character
// anything but New_Line_Character
: ~('\u000D' | '\u000A' | '\u0085' | '\u2028' | '\u2029')
;
fragment New_Line_Character
: '\u000D' // carriage return
| '\u000A' // line feed
| '\u0085' // next line
| '\u2028' // line separator
| '\u2029' // paragraph separator
;
fragment Delimited_Comment
: '/*' Delimited_Comment_Section* ASTERISK+ '/'
;
fragment Delimited_Comment_Section
: SLASH
| ASTERISK* Not_Slash_Or_Asterisk
;
fragment Not_Slash_Or_Asterisk
: ~('/' | '*') // Any except SLASH or ASTERISK
;
Açıklamalar iç içe yerleştirilmiyor.
/*
ile */
karakter dizilerinin tek satırlı bir açıklama içinde ve //
ile /*
karakter dizilerinin de sınırlandırılmış bir açıklama içinde özel bir anlamı yoktur.
Açıklamalar karakter ve dize değişmez değerleri içinde işlenmez.
Not: Bu kurallar dikkatle yorumlanmalıdır. Örneğin, aşağıdaki örnekte, ile
A
arasındaB
bitmeden önceC()
başlayan sınırlandırılmış açıklama. Nedeni şudur:// B */ C();
aslında tek satırlı bir açıklama değildir, çünkü
//
sınırlandırılmış bir açıklama içinde özel bir anlamı yoktur ve bu satırda*/
her zamanki özel anlamı vardır.Benzer şekilde, öncesinden başlayan sınırlandırılmış açıklama da tarihinden önce
D
E
sona erer. Bunun nedeni"D */ "
aslında bir dize değişmez değeri olmamasıdır çünkü ilk çift tırnak karakteri sınırlandırılmış bir açıklama içinde görünür.Tek satırlı bir açıklama içinde özel bir anlamı olmamasının
/*
ve*/
bunun yararlı bir sonucu, kaynak kod satırları bloğunun her satırın başına yerleştirilerek//
açıklama çıkarılabilmesidir. Genel olarak, bloktaki sınırlandırılmış açıklamaları düzgün bir şekilde kapsüllemediğinden ve genel olarak bu sınırlandırılmış açıklamaların yapısını tamamen değiştireediğinden, bu satırların önüne ve/*
arkasına koymak*/
işe yaramaz.Örnek kod:
static void Main() { /* A // B */ C(); Console.WriteLine(/* "D */ "E"); }
son not
Single_Line_Comment ve Delimited_Commentbelirli biçimlere sahip olması , belge açıklamaları olarak §D'de açıklandığı gibi kullanılabilir.
6.3.4 Boşluk
Boşluk, Unicode sınıf Z'leri (boşluk karakterini içeren) ve yatay sekme karakteri, dikey sekme karakteri ve form akışı karakteri olan herhangi bir karakter olarak tanımlanır.
Whitespace
: [\p{Zs}] // any character with Unicode class Zs
| '\u0009' // horizontal tab
| '\u000B' // vertical tab
| '\u000C' // form feed
;
6.4 Belirteçleri
6.4.1 Genel
Çeşitli belirteç türleri vardır: tanımlayıcılar, anahtar sözcükler, değişmez değerler, işleçler ve noktalama işaretleri. Boşluk ve açıklamalar belirteç değildir, ancak belirteçler için ayırıcı görevi görür.
token
: identifier
| keyword
| Integer_Literal
| Real_Literal
| Character_Literal
| String_Literal
| operator_or_punctuator
;
Not: Bu bir ANTLR ayrıştırıcı kuralıdır, sözcük temelli bir belirteç tanımlamaz, belirteç türlerinin koleksiyonudur. son not
6.4.2 Unicode karakter kaçış dizileri
Unicode kaçış dizisi bir Unicode kod noktasını temsil eder. Unicode kaçış dizileri tanımlayıcılar (§6.4.3), karakter değişmez değerleri (§6.4.5.5), normal dize değişmez değerleri (§6.4.5.6) ve ilişkilendirilmiş normal dize ifadeleri (§12.8.3) olarak işlenir. Unicode kaçış dizisi başka bir konumda (örneğin, bir işleç, noktalama işareti veya anahtar sözcük oluşturmak için) işlenmez.
fragment Unicode_Escape_Sequence
: '\\u' Hex_Digit Hex_Digit Hex_Digit Hex_Digit
| '\\U' Hex_Digit Hex_Digit Hex_Digit Hex_Digit
Hex_Digit Hex_Digit Hex_Digit Hex_Digit
;
Unicode karakter kaçış dizisi, "\u" veya "\U" karakterlerini izleyen onaltılık sayı tarafından oluşturulan tek Bir Unicode kod noktasını temsil eder. C# karakter ve dize değerlerinde Unicode kod noktalarının 16 bit kodlamasını kullandığından, için U+10000
aralığındaki U+10FFFF
bir Unicode kod noktası iki Unicode vekil kod birimi kullanılarak temsil edilir. Yukarıdaki U+FFFF
Unicode kod noktalarına karakter değişmez değerlerinde izin verilmez. Yukarıdaki U+10FFFF
Unicode kod noktaları geçersiz ve desteklenmiyor.
Birden çok çeviri gerçekleştirilmiyor. Örneğin, dize değişmez değeri "\u005Cu005C"
yerine "\u005C"
ile "\"
eşdeğerdir.
Not: Unicode değeri
\u005C
"\
" karakteridir. son not
Örnek: Örnek
class Class1 { static void Test(bool \u0066) { char c = '\u0066'; if (\u0066) { System.Console.WriteLine(c.ToString()); } } }
, "
\u0066
" harfinin kaçış dizisi olan çeşitli kullanımlarınıf
gösterir. Program,class Class1 { static void Test(bool f) { char c = 'f'; if (f) { System.Console.WriteLine(c.ToString()); } } }
son örnek
6.4.3 Tanımlayıcıları
Bu alt kodda verilen tanımlayıcıların kuralları, alt çizginin ilk karakter olarak izin verilmesi (C programlama dilinde geleneksel olduğu gibi), tanımlayıcılarda Unicode kaçış sıralarına izin verilmesi ve anahtar sözcüklerin tanımlayıcı olarak kullanılmasını sağlamak için ön ek olarak "@
" karakterine izin verilmesi dışında Unicode Standart Ek 15 tarafından önerilenlere tam olarak karşılık gelir.
identifier
: Simple_Identifier
| contextual_keyword
;
Simple_Identifier
: Available_Identifier
| Escaped_Identifier
;
fragment Available_Identifier
// excluding keywords or contextual keywords, see note below
: Basic_Identifier
;
fragment Escaped_Identifier
// Includes keywords and contextual keywords prefixed by '@'.
// See note below.
: '@' Basic_Identifier
;
fragment Basic_Identifier
: Identifier_Start_Character Identifier_Part_Character*
;
fragment Identifier_Start_Character
: Letter_Character
| Underscore_Character
;
fragment Underscore_Character
: '_' // underscore
| '\\u005' [fF] // Unicode_Escape_Sequence for underscore
| '\\U0000005' [fF] // Unicode_Escape_Sequence for underscore
;
fragment Identifier_Part_Character
: Letter_Character
| Decimal_Digit_Character
| Connecting_Character
| Combining_Character
| Formatting_Character
;
fragment Letter_Character
// Category Letter, all subcategories; category Number, subcategory letter.
: [\p{L}\p{Nl}]
// Only escapes for categories L & Nl allowed. See note below.
| Unicode_Escape_Sequence
;
fragment Combining_Character
// Category Mark, subcategories non-spacing and spacing combining.
: [\p{Mn}\p{Mc}]
// Only escapes for categories Mn & Mc allowed. See note below.
| Unicode_Escape_Sequence
;
fragment Decimal_Digit_Character
// Category Number, subcategory decimal digit.
: [\p{Nd}]
// Only escapes for category Nd allowed. See note below.
| Unicode_Escape_Sequence
;
fragment Connecting_Character
// Category Punctuation, subcategory connector.
: [\p{Pc}]
// Only escapes for category Pc allowed. See note below.
| Unicode_Escape_Sequence
;
fragment Formatting_Character
// Category Other, subcategory format.
: [\p{Cf}]
// Only escapes for category Cf allowed, see note below.
| Unicode_Escape_Sequence
;
Not:
- Yukarıda bahsedilen Unicode karakter sınıfları hakkında bilgi için bkz . Unicode Standardı.
- Parça Available_Identifier , anahtar sözcüklerin ve bağlamsal anahtar sözcüklerin dışlanmasını gerektirir. Bu belirtimdeki dil bilgisi ANTLR ile işlenirse, bu dışlama ANTLR semantiği tarafından otomatik olarak işlenir:
- Anahtar sözcükler ve bağlamsal anahtar sözcükler, dil bilgisinde değişmez değer dizeleri olarak gerçekleşir.
- ANTLR, bu değişmez değer dizelerinden örtük sözcük temelli belirteç kuralları oluşturur.
- ANTLR, bu örtük kuralları dil bilgisindeki açık sözcük kurallarından önce dikkate alır.
- Bu nedenle parça Available_Identifier , anahtar sözcüklerle veya bağlamsal anahtar sözcüklerle eşleşmez. Bu nedenle, öncekiler için sözcük kuralları kullanılır.
- Parça Escaped_Identifier , kaçış anahtar sözcükleri ve bağlamsal anahtar sözcükleri içerir. Bu anahtar sözcükler, bir ve sözcük temelli işleme ile başlayan uzun belirtecin parçası
@
olarak her zaman mümkün olan en uzun sözcük temelli öğeyi (§6.3.1) oluşturur.- Bir uygulamanın izin verilen Unicode_Escape_Sequence değerleri üzerindeki kısıtlamaları nasıl zorunlu kılması bir uygulama sorunudur.
son not
Örnek: Geçerli tanımlayıcılara örnek olarak
identifier1
,_identifier2
ve@if
verilebilir. son örnek
Uyumlu bir programdaki tanımlayıcı, Unicode Standart Ek 15 tarafından tanımlandığı gibi Unicode Normalleştirme Formu C tarafından tanımlanan kurallı biçimde olmalıdır. C Normalleştirme Formu'nda olmayan bir tanımlayıcıyla karşılaşıldığında davranış uygulama tanımlıdır; ancak tanılama gerekli değildir.
"@
" ön eki, anahtar sözcüklerin tanımlayıcı olarak kullanılmasını sağlar. Bu, diğer programlama dilleriyle birlikte çalışırken kullanışlıdır. Karakter @
aslında tanımlayıcının bir parçası olmadığından, tanımlayıcı diğer dillerde ön ek olmadan normal bir tanımlayıcı olarak görülebilir. Ön eki olan bir @
tanımlayıcıya ayrıntılı tanımlayıcı adı verilir.
Not: Anahtar sözcük olmayan tanımlayıcılar için ön ekin kullanılmasına
@
izin verilir, ancak stil açısından kesinlikle önerilmez. son not
Örnek: Örnek:
class @class { public static void @static(bool @bool) { if (@bool) { System.Console.WriteLine("true"); } else { System.Console.WriteLine("false"); } } } class Class1 { static void M() { cl\u0061ss.st\u0061tic(true); } }
"" adlı bir parametre alan "
class
static
" adlı statik yöntemle "bool
" adlı bir sınıf tanımlar. Anahtar sözcüklerde Unicode kaçışlarına izin verilmediğinden, "cl\u0061ss
" belirtecinin bir tanımlayıcı olduğunu ve "@class
" ile aynı tanımlayıcı olduğunu unutmayın.son örnek
Aşağıdaki dönüştürmeler uygulandıktan sonra sırasıyla aynı olan iki tanımlayıcı aynı kabul edilir:
- "
@
" ön eki kullanılırsa kaldırılır. - Her Unicode_Escape_Sequence karşılık gelen Unicode karakterine dönüştürülür.
- Tüm Formatting_Characterkaldırılır.
adlı _
bir tanımlayıcının semantiği, göründüğü bağlama bağlıdır:
- Değişken, sınıf veya yöntem gibi adlandırılmış bir program öğesini gösterebilir veya
- Bir atmayı anlamına gelebilir (§9.2.9.2).
Ardışık iki alt çizgi karakteri (U+005F
) içeren tanımlayıcılar uygulama tarafından kullanılmak üzere ayrılır; ancak böyle bir tanımlayıcı tanımlanırsa tanılama gerekmez.
Not: Örneğin, bir uygulama iki alt çizgiyle başlayan genişletilmiş anahtar sözcükler sağlayabilir. son not
6.4.4 Anahtar Sözcükler
Anahtar sözcük , ayrılmış olan tanımlayıcı benzeri bir karakter dizisidir ve karakterin başına @
geçtiği durumlar dışında tanımlayıcı olarak kullanılamaz.
keyword
: 'abstract' | 'as' | 'base' | 'bool' | 'break'
| 'byte' | 'case' | 'catch' | 'char' | 'checked'
| 'class' | 'const' | 'continue' | 'decimal' | DEFAULT
| 'delegate' | 'do' | 'double' | 'else' | 'enum'
| 'event' | 'explicit' | 'extern' | FALSE | 'finally'
| 'fixed' | 'float' | 'for' | 'foreach' | 'goto'
| 'if' | 'implicit' | 'in' | 'int' | 'interface'
| 'internal' | 'is' | 'lock' | 'long' | 'namespace'
| 'new' | NULL | 'object' | 'operator' | 'out'
| 'override' | 'params' | 'private' | 'protected' | 'public'
| 'readonly' | 'ref' | 'return' | 'sbyte' | 'sealed'
| 'short' | 'sizeof' | 'stackalloc' | 'static' | 'string'
| 'struct' | 'switch' | 'this' | 'throw' | TRUE
| 'try' | 'typeof' | 'uint' | 'ulong' | 'unchecked'
| 'unsafe' | 'ushort' | 'using' | 'virtual' | 'void'
| 'volatile' | 'while'
;
Bağlamsal anahtar sözcük, belirli bağlamlarda özel anlamı olan, ancak ayrılmamış olan tanımlayıcı benzeri bir karakter dizisidir ve hem bu bağlamların dışında hem de karakterin başına @
geldiğinde tanımlayıcı olarak kullanılabilir.
contextual_keyword
: 'add' | 'alias' | 'ascending' | 'async' | 'await'
| 'by' | 'descending' | 'dynamic' | 'equals' | 'from'
| 'get' | 'global' | 'group' | 'into' | 'join'
| 'let' | 'nameof' | 'on' | 'orderby' | 'partial'
| 'remove' | 'select' | 'set' | 'unmanaged' | 'value'
| 'var' | 'when' | 'where' | 'yield'
;
Not: Rules anahtar sözcüğü ve contextual_keyword , yeni belirteç türleri eklemedikleri için ayrıştırıcı kurallarıdır. Tüm anahtar sözcükler ve bağlamsal anahtar sözcükler, dilbilgisinde değişmez değer dizeleri (§6.2.3) olarak gerçekleştiğinden örtük sözcük kurallarıyla tanımlanır. son not
Çoğu durumda bağlamsal anahtar sözcüklerin söz dizimsel konumu, normal tanımlayıcı kullanımıyla karıştırılamayacak şekildedir. Örneğin, bir özellik bildirimi içinde get
ve set
tanımlayıcılarının özel anlamı vardır (§15.7.3). Bu konumlarda veya dışında hiçbir zaman izin verilmeyen bir tanımlayıcı get
set
olduğundan, bu kullanım bu sözcüklerin tanımlayıcı olarak kullanılmasıyla çakışmaz.
Bazı durumlarda dil bilgisi, bağlamsal anahtar sözcük kullanımını tanımlayıcılardan ayırt etmek için yeterli değildir. Bu gibi durumlarda ikisi arasında nasıl disambiguate olacağı belirtilir. Örneğin, örtük olarak yazılan yerel değişken bildirimlerindeki bağlamsal anahtar sözcük var
(§13.6.2) adlı var
bildirilen bir türle çakışabilir. Bu durumda, bildirilen ad tanımlayıcının bağlamsal anahtar sözcük olarak kullanılmasından önceliklidir.
Bu tür bir kesinleştirme örneği, yalnızca bildirilen await
bir yöntemin içinde anahtar sözcük olarak kabul edilen ancak başka bir yerde tanımlayıcı olarak kullanılabilen bağlamsal anahtar sözcüktür (async
).
Anahtar sözcüklerde olduğu gibi bağlamsal anahtar sözcükler de karakterin önüne eklenerek @
normal tanımlayıcılar olarak kullanılabilir.
Not: Bağlamsal anahtar sözcükler olarak kullanıldığında, bu tanımlayıcılar Unicode_Escape_Sequenceiçeremez. son not
6.4.5 Değişmez Değerler
6.4.5.1 Genel
Değişmez değer (§12.8.2), bir değerin kaynak kodu gösterimidir.
literal
: boolean_literal
| Integer_Literal
| Real_Literal
| Character_Literal
| String_Literal
| null_literal
;
Not: Değişmez değer , diğer belirteç türlerini gruplandırdığından ve yeni bir belirteç türü eklemediğinden ayrıştırıcı kuralıdır. son not
6.4.5.2 Boole değişmez değerleri
İki Boole değişmez değeri vardır: true
ve false
.
boolean_literal
: TRUE
| FALSE
;
Not: boolean_literal , diğer belirteç türlerini gruplandırdığından ve yeni bir belirteç türü eklemediğinden ayrıştırıcı kuralıdır. son not
boolean_literal türüdür.bool
6.4.5.3 Tamsayı değişmez değerleri
Tamsayı değişmez değerleri , , int
uint
ve long
türlerinin ulong
değerlerini yazmak için kullanılır. Tamsayı değişmez değerlerinin üç olası biçimi vardır: ondalık, onaltılık ve ikili.
Integer_Literal
: Decimal_Integer_Literal
| Hexadecimal_Integer_Literal
| Binary_Integer_Literal
;
fragment Decimal_Integer_Literal
: Decimal_Digit Decorated_Decimal_Digit* Integer_Type_Suffix?
;
fragment Decorated_Decimal_Digit
: '_'* Decimal_Digit
;
fragment Decimal_Digit
: '0'..'9'
;
fragment Integer_Type_Suffix
: 'U' | 'u' | 'L' | 'l' |
'UL' | 'Ul' | 'uL' | 'ul' | 'LU' | 'Lu' | 'lU' | 'lu'
;
fragment Hexadecimal_Integer_Literal
: ('0x' | '0X') Decorated_Hex_Digit+ Integer_Type_Suffix?
;
fragment Decorated_Hex_Digit
: '_'* Hex_Digit
;
fragment Hex_Digit
: '0'..'9' | 'A'..'F' | 'a'..'f'
;
fragment Binary_Integer_Literal
: ('0b' | '0B') Decorated_Binary_Digit+ Integer_Type_Suffix?
;
fragment Decorated_Binary_Digit
: '_'* Binary_Digit
;
fragment Binary_Digit
: '0' | '1'
;
Tamsayı değişmez değeri türü aşağıdaki gibi belirlenir:
- Değişmez değerde sonek yoksa, değerinin temsil edilebileceği bu türlerden ilki vardır:
int
,uint
, ,long
ulong
. - Değişmez değer veya
U
tarafındanu
soneklenmişse, değerinin temsil edilebileceği bu türlerden ilki vardır:uint
,ulong
. - Değişmez değer veya
L
tarafındanl
soneklenmişse, değerinin temsil edilebileceği bu türlerden ilki vardır:long
,ulong
. - Değişmez değer , ,
UL
, ,Ul
,uL
,ul
,LU
,Lu
veyalU
ilelu
soneklenmişse, türündedirulong
.
Tamsayı değişmez değeriyle temsil edilen değer türün aralığının ulong
dışındaysa, derleme zamanı hatası oluşur.
Not: Stil açısından, türündeki değişmez değerleri
L
yazarken "l
" yerine "long
" kullanılması önerilir, çünkü "" harfini "l
1
" rakamıyla karıştırmak kolaydır. son not
Mümkün int
olan en küçük değere ve long
değerlerin tamsayı değişmez değerleri olarak yazılmasına izin vermek için aşağıdaki iki kural vardır:
- Değeri temsil eden bir
2147483648
(2³¹) ve hiçbir Integer_Type_Suffix bir tek eksi işleci belirtecinin (§12.9.3) hemen ardından belirteç olarak göründüğünde, sonuç (her iki belirtecin de) değeri−2147483648
olan int türünde bir sabittir (−2³¹). Diğer tüm durumlarda, böyle bir Integer_Literal türündediruint
. - Değeri (2⁶³) temsil eden ve Integer_Type_Suffix veya Integer_Type_Suffix olmayan
L
birli eksi işleci belirtecinin hemen ardından belirteç olarak göründüğünde (l
), sonuç (her iki belirtecin de) değeri olan bir türlong
sabitidir (−2⁶³).−9223372036854775808
Diğer tüm durumlarda, böyle bir Integer_Literal türündedirulong
.
Örnek:
123 // decimal, int 10_543_765Lu // decimal, ulong 1_2__3___4____5 // decimal, int _123 // not a numeric literal; identifier due to leading _ 123_ // invalid; no trailing _allowed 0xFf // hex, int 0X1b_a0_44_fEL // hex, long 0x1ade_3FE1_29AaUL // hex, ulong 0x_abc // hex, int _0x123 // not a numeric literal; identifier due to leading _ 0xabc_ // invalid; no trailing _ allowed 0b101 // binary, int 0B1001_1010u // binary, uint 0b1111_1111_0000UL // binary, ulong 0B__111 // binary, int __0B111 // not a numeric literal; identifier due to leading _ 0B111__ // invalid; no trailing _ allowed
son örnek
6.4.5.4 Gerçek değişmez değerler
Gerçek değişmez değerler, , float
ve double
türlerinin decimal
değerlerini yazmak için kullanılır.
Real_Literal
: Decimal_Digit Decorated_Decimal_Digit* '.'
Decimal_Digit Decorated_Decimal_Digit* Exponent_Part? Real_Type_Suffix?
| '.' Decimal_Digit Decorated_Decimal_Digit* Exponent_Part? Real_Type_Suffix?
| Decimal_Digit Decorated_Decimal_Digit* Exponent_Part Real_Type_Suffix?
| Decimal_Digit Decorated_Decimal_Digit* Real_Type_Suffix
;
fragment Exponent_Part
: ('e' | 'E') Sign? Decimal_Digit Decorated_Decimal_Digit*
;
fragment Sign
: '+' | '-'
;
fragment Real_Type_Suffix
: 'F' | 'f' | 'D' | 'd' | 'M' | 'm'
;
Real_Type_Suffix belirtilmezse, Real_Literal türü olurdouble
. Aksi takdirde, Real_Type_Suffix gerçek değişmez değerin türünü aşağıdaki gibi belirler:
- veya
F
türündef
gerçek bir değişmez değer sonekifloat
.Örnek: , ,
1f
1.5f
ve1e10f
değişmez değerlerinin123.456F
tümü türündedirfloat
. son örnek - veya
D
türünded
gerçek bir değişmez değer sonekidouble
.Örnek: , ,
1d
1.5d
ve1e10d
değişmez değerlerinin123.456D
tümü türündedirdouble
. son örnek - veya
M
türündem
gerçek bir değişmez değer sonekidecimal
.Örnek: , ,
1m
1.5m
ve1e10m
değişmez değerlerinin123.456M
tümü türündedirdecimal
. son örnek
Bu değişmez değer, tam değer alınarak birdecimal
değere dönüştürülür ve gerekirse bankacı yuvarlama (§8.3.8) kullanılarak en yakın temsil edilebilir değere yuvarlama yapılır. Değer yuvarlanmadığı sürece değişmez değerde görünen tüm ölçekler korunur. Not: Bu nedenle, değişmez değer2.900m
işaretidecimal
, katsayısı0
ve ölçek2900
ile oluşturmak3
için ayrıştırılır. son not
Belirtilen değişmez değerin büyüklüğü belirtilen türde temsil edilemeyecek kadar büyükse, derleme zamanı hatası oluşur.
Not: Özellikle, bir Real_Literal hiçbir zaman kayan nokta sonsuzluğu üretmez. Ancak sıfır olmayan bir Real_Literal sıfıra yuvarlanabilir. son not
Türün float
veya double
gerçek değişmez değerinin değeri, "eşit" olarak (en az önemli bit sıfır olan bir değer) ve tüm basamakların önemli olarak kabul edildiği IEC 60559 "en yakına yuvarla" modu kullanılarak belirlenir.
Not: Gerçek değişmez değerde ondalık basamaklar her zaman ondalık ayırıcıdan sonra gereklidir. Örneğin,
1.3F
gerçek bir değişmez değerdir ancak1.F
değildir. son notÖrnek:
1.234_567 // double .3e5f // float 2_345E-2_0 // double 15D // double 19.73M // decimal 1.F // parsed as a member access of F due to non-digit after . 1_.2F // invalid; no trailing _ allowed in integer part 1._234 // parsed as a member access of _234 due to non-digit after . 1.234_ // invalid; no trailing _ allowed in fraction .3e_5F // invalid; no leading _ allowed in exponent .3e5_F // invalid; no trailing _ allowed in exponent
son örnek
6.4.5.5 Karakter değişmez değerleri
Karakter değişmez değeri tek bir karakteri temsil eder ve içinde olduğu gibi 'a'
tırnak içinde bir karakterden oluşur.
Character_Literal
: '\'' Character '\''
;
fragment Character
: Single_Character
| Simple_Escape_Sequence
| Hexadecimal_Escape_Sequence
| Unicode_Escape_Sequence
;
fragment Single_Character
// anything but ', \, and New_Line_Character
: ~['\\\u000D\u000A\u0085\u2028\u2029]
;
fragment Simple_Escape_Sequence
: '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' |
'\\f' | '\\n' | '\\r' | '\\t' | '\\v'
;
fragment Hexadecimal_Escape_Sequence
: '\\x' Hex_Digit Hex_Digit? Hex_Digit? Hex_Digit?
;
Not: Karakterde ters eğik çizgi karakterinden (
\
) sonra gelen bir karakter şu karakterlerden biri olmalıdır:'
,"
,\
, ,0
,a
, ,b
,f
,n
,r
,t
u
U
x
, .v
Aksi takdirde derleme zamanı hatası oluşur. son not
Not: Hexadecimal_Escape_Sequence üretiminin
\x
kullanımı hataya açık olabilir ve değerini izleyen\x
onaltılık basamakların değişken sayısı nedeniyle zor okunabilir. Örneğin, kodda:string good = "\x9Good text"; string bad = "\x9Bad text";
başta, baştaki karakterin her iki dizede de aynı (
U+0009
sekme karakteri) olduğu görünebilir. Aslında ikinci dize ileU+9BAD
başlar ve "Hatalı" sözcüğündeki üç harfin tümü geçerli onaltılık basamaklardır. Stil açısından, belirli kaçış dizileri (\x
bu örnekte) veya sabit uzunlukta\t
kaçış dizisinin kullanılmasından kaçınılması önerilir\u
.son not
Onaltılık kaçış dizisi, tek bir Unicode UTF-16 kod birimini temsil eder ve değeri onaltılık sayı tarafından oluşturulan "\x
".
Karakter değişmez değeriyle gösterilen değer değerinden U+FFFF
büyükse, derleme zamanı hatası oluşur.
Karakter değişmez değeri içindeki Unicode kaçış dizisi (§6.4.2) ile aralığında U+0000
U+FFFF
olmalıdır.
Basit çıkış dizisi, aşağıdaki tabloda açıklandığı gibi bir Unicode karakterini temsil eder.
Kaçış dizisi | Karakter adı | Unicode kod noktası |
---|---|---|
\' |
Tek tırnak | U+0027 |
\" |
Çift tırnak | U+0022 |
\\ |
Ters eğik çizgi | U+005C |
\0 |
Boş | U+0000 |
\a |
Uyarı | U+0007 |
\b |
Geri Al tuşu | U+0008 |
\f |
Form akışı | U+000C |
\n |
Yeni satır | U+000A |
\r |
Satır başı | U+000D |
\t |
Yatay sekme | U+0009 |
\v |
Dikey sekme | U+000B |
Character_Literal türü şeklindedirchar
.
6.4.5.6 Dize değişmez değerleri
C# iki dize değişmez değerini destekler: normal dize değişmez değerleri ve düz metin dize değişmez değerleri. Normal dize değişmez değeri, içinde "hello"
olduğu gibi çift tırnak içine alınmış sıfır veya daha fazla karakterden oluşur ve hem basit kaçış dizilerini (sekme karakteri gibi \t
) hem de onaltılık ve Unicode kaçış dizilerini içerebilir.
Düz metin dizesi değişmez değeri, bir @
karakterin ardından çift tırnak karakteri, sıfır veya daha fazla karakter ve kapanış çift tırnak karakterinden oluşur.
Örnek: Basit bir örnektir
@"hello"
. son örnek
Düz metin dize değişmez değerde, sınırlayıcılar arasındaki karakterler tamsayı olarak yorumlanır ve tek özel durum bir çift tırnak karakterini temsil eden bir Quote_Escape_Sequence olur. Özellikle, basit kaçış dizileri ve onaltılık ve Unicode kaçış dizileri tam dize değişmez değerlerinde işlenmez. Düz metin dizesi değişmez değeri birden çok satıra yayılabilir.
String_Literal
: Regular_String_Literal
| Verbatim_String_Literal
;
fragment Regular_String_Literal
: '"' Regular_String_Literal_Character* '"'
;
fragment Regular_String_Literal_Character
: Single_Regular_String_Literal_Character
| Simple_Escape_Sequence
| Hexadecimal_Escape_Sequence
| Unicode_Escape_Sequence
;
fragment Single_Regular_String_Literal_Character
// anything but ", \, and New_Line_Character
: ~["\\\u000D\u000A\u0085\u2028\u2029]
;
fragment Verbatim_String_Literal
: '@"' Verbatim_String_Literal_Character* '"'
;
fragment Verbatim_String_Literal_Character
: Single_Verbatim_String_Literal_Character
| Quote_Escape_Sequence
;
fragment Single_Verbatim_String_Literal_Character
: ~["] // anything but quotation mark (U+0022)
;
fragment Quote_Escape_Sequence
: '""'
;
Örnek: Örnek
string a = "Happy birthday, Joel"; // Happy birthday, Joel string b = @"Happy birthday, Joel"; // Happy birthday, Joel string c = "hello \t world"; // hello world string d = @"hello \t world"; // hello \t world string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt string h = @"\\server\share\file.txt"; // \\server\share\file.txt string i = "one\r\ntwo\r\nthree"; string j = @"one two three";
çeşitli dize değişmez değerleri gösterir. Son dize değişmez değeri olan ,
j
birden çok satıra yayılan bir düz metin dizesi değişmez değeridir. Yeni satır karakterleri gibi boşluklar da dahil olmak üzere tırnak işaretleri arasındaki karakterler tam olarak korunur ve her çift tırnak karakteri çifti böyle bir karakterle değiştirilir.son örnek
Not: Tam dize değişmez değerleri içindeki tüm satır sonları, sonuçta elde edilen dizenin bir parçasıdır. Satır sonlarını oluşturmak için kullanılan tam karakterler bir uygulamayla ilgiliyse, kaynak koddaki satır sonlarını farklı biçimlere çeviren tüm araçlar (örneğin, "
\n
" ile "\r\n
" arasında) uygulama davranışını değiştirir. Geliştiriciler bu gibi durumlarda dikkatli olmalıdır. son not
Not: Onaltılık bir kaçış dizisinin değişken sayıda onaltılık basamakları olabileceğinden, dize değişmez değeri
"\x123"
onaltılık değere123
sahip tek bir karakter içerir. Onaltılık değere12
ve ardından karakterine sahip karakteri3
içeren bir dize oluşturmak için, bir dize yazabilir"\x00123"
veya"\x12"
+"3"
yazabilir. son not
String_Literal türüdür.string
Her dize değişmez değeri mutlaka yeni bir dize örneğine neden olmaz. Dize eşitliği işlecine (§12.12.8) göre eşdeğer olan iki veya daha fazla dize değişmez değeri aynı derlemede göründüğünde, bu dize değişmez değerleri aynı dize örneğine başvurur.
Örnek: Örneğin,
class Test { static void Main() { object a = "hello"; object b = "hello"; System.Console.WriteLine(a == b); } }
bunun nedeni, iki değişmez değerin aynı dize örneğine başvurmasıdır
True
.son örnek
6.4.5.7 Null değişmez değer
null_literal
: NULL
;
Not: null_literal , yeni bir belirteç türü tanıtmadığından ayrıştırıcı kuralıdır. son not
null_literal bir null
değeri temsil eder. Türü yoktur, ancak null değişmez değer dönüştürmesi (§10.2.7) aracılığıyla herhangi bir başvuru türüne veya null değer türüne dönüştürülebilir.
6.4.6 İşleçler ve noktalama işaretleri
Çeşitli işleçler ve noktalama işaretleri vardır. İşleçler, bir veya daha fazla işlenen içeren işlemleri açıklamak için ifadelerde kullanılır.
Örnek: İfade
a + b
, ve adlı iki işleneni+
a
eklemek için işlecini kullanırb
. son örnek
Noktalama işaretleri gruplandırma ve ayırmaya yöneliktir.
operator_or_punctuator
: '{' | '}' | '[' | ']' | '(' | ')' | '.' | ',' | ':' | ';'
| '+' | '-' | ASTERISK | SLASH | '%' | '&' | '|' | '^' | '!' | '~'
| '=' | '<' | '>' | '?' | '??' | '::' | '++' | '--' | '&&' | '||'
| '->' | '==' | '!=' | '<=' | '>=' | '+=' | '-=' | '*=' | '/=' | '%='
| '&=' | '|=' | '^=' | '<<' | '<<=' | '=>'
;
right_shift
: '>' '>'
;
right_shift_assignment
: '>' '>='
;
Not: right_shift ve right_shift_assignment ayrıştırıcı kurallarıdır, yeni bir belirteç türü sunmaz ancak iki belirteç sırasını temsil eder. operator_or_punctuator kuralı yalnızca açıklayıcı amaçlarla mevcuttur ve dil bilgisinin başka bir yerinde kullanılmaz. son not
right_shift iki belirteçten >
oluşur ve >
. Benzer şekilde, right_shift_assignment ve iki belirteçten >
>=
oluşur. Söz dizimindeki diğer üretimlerden farklı olarak, bu üretimlerin her birinde iki belirteç arasında herhangi bir türde karaktere (boşluk bile yoktur) izin verilmez. Bu üretimler, type_parameter_lists (§15.2.3) doğru şekilde işlenmesini sağlamak için özel olarak ele alınır.
Not: C#
>>
öğesine genel değerler eklenmeden önce ve>>=
her ikisi de tek belirteçti. Ancak, genel türlerin söz dizimi, tür parametrelerini ve tür bağımsız değişkenlerini sınırlandırmak için ve<
karakterlerini kullanır>
. genellikle gibiList<Dictionary<string, int>>
iç içe yerleştirilmiş türlerin kullanılması tercih edilir. Programcının ve>
öğesini bir boşlukla ayırmasını>
gerektirmek yerine, iki operator_or_punctuatortanımı değiştirildi. son not
6.5 Ön işleme yönergeleri
6.5.1 Genel
Ön işleme yönergeleri, derleme birimlerinin bölümlerini koşullu olarak atlama, hata ve uyarı koşullarını raporlama, kaynak kodun farklı bölgelerini ayırma ve null atanabilir bağlamı ayarlama olanağı sağlar.
Not: "Ön işleme yönergeleri" terimi yalnızca C ve C++ programlama dilleri ile tutarlılık için kullanılır. C# dilinde ayrı bir ön işleme adımı yoktur; ön işleme yönergeleri, sözcük temelli analiz aşamasının bir parçası olarak işlenir. son not
PP_Directive
: PP_Start PP_Kind PP_New_Line
;
fragment PP_Kind
: PP_Declaration
| PP_Conditional
| PP_Line
| PP_Diagnostic
| PP_Region
| PP_Pragma
| PP_Nullable
;
// Only recognised at the beginning of a line
fragment PP_Start
// See note below.
: { getCharPositionInLine() == 0 }? PP_Whitespace? '#' PP_Whitespace?
;
fragment PP_Whitespace
: ( [\p{Zs}] // any character with Unicode class Zs
| '\u0009' // horizontal tab
| '\u000B' // vertical tab
| '\u000C' // form feed
)+
;
fragment PP_New_Line
: PP_Whitespace? Single_Line_Comment? New_Line
;
Not:
- ön işlemci dil bilgisi, tüm ön işleme yönergeleri için kullanılan tek bir sözcük temelli belirteci
PP_Directive
tanımlar. Ön işleme yönergelerinin her birinin semantiği bu dil belirtiminde tanımlanır, ancak bunların nasıl uygulandığını tanımlamaz.- Parçanın
PP_Start
yalnızca bir satırın başında tanınması gerekir.getCharPositionInLine() == 0
Yukarıdaki ANTLR sözcük temelli koşulu, bunun elde edilebileceği tek bir yolu önerir ve yalnızca bilgilendiricidir, bir uygulama farklı bir strateji kullanabilir.son not
Aşağıdaki ön işleme yönergeleri kullanılabilir:
-
#define
ve#undef
, koşullu derleme sembollerini (§6.5.4) tanımlamak ve tanımlamak için kullanılır. -
#if
,#elif
,#else
ve#endif
, kaynak kodun koşullu bölümlerini atlamak için kullanılır (§6.5.5). -
#line
, hata ve uyarılarda (§6.5.8) yayılan satır numaralarını denetlemek için kullanılır. -
#error
, hata vermek için kullanılır (§6.5.6). -
#region
ve#endregion
, kaynak kodun (§6.5.7) bölümlerini açıkça işaretlemek için kullanılır. -
#nullable
, null atanabilir bağlamı (§6.5.9) belirtmek için kullanılır. -
#pragma
, derleyiciye isteğe bağlı bağlamsal bilgileri belirtmek için kullanılır (§6.5.10).
Ön işleme yönergesi her zaman ayrı bir kaynak kodu satırını kaplar ve her zaman bir #
karakter ve bir ön işleme yönerge adı ile başlar. Karakterden önce #
ve karakter ile yönerge adı arasında #
boşluk oluşabilir.
, , , , #define
, , #undef
, #if
#elif
, #else
#endif
, veya #line
yönergesi içeren bir #endregion
kaynak satırı tek satırlı bir açıklamayla bitebilir. #nullable
Ön işleme yönergelerini içeren kaynak satırlarda sınırlandırılmış açıklamalara ( /* */
açıklama stili) izin verilmez.
Ön işleme yönergeleri, C# dilinin sözdizimi dil bilgisinin bir parçası değildir. Ancak, ön işleme yönergeleri belirteç dizilerini dahil etmek veya dışlamak için kullanılabilir ve bu şekilde bir C# programının anlamını etkileyebilir.
Örnek: Derlendiğinde, program
#define A #undef B class C { #if A void F() {} #else void G() {} #endif #if B void H() {} #else void I() {} #endif }
programla tam olarak aynı belirteç dizisiyle sonuçlanmıştır
class C { void F() {} void I() {} }
Bu nedenle, sözcüksel olarak, iki program oldukça farklıdır, bozulmadan, aynıdır.
son örnek
6.5.2 Koşullu derleme simgeleri
, , #if
#elif
ve #else
yönergeleri tarafından #endif
sağlanan koşullu derleme işlevselliği, ön işleme ifadeleri (§6.5.3) ve koşullu derleme simgeleri aracılığıyla denetlenmektedir.
fragment PP_Conditional_Symbol
// Must not be equal to tokens TRUE or FALSE. See note below.
: Basic_Identifier
;
Not Bir uygulamanın izin verilen Basic_Identifier değerleri üzerindeki kısıtlamayı nasıl zorunlu kılması bir uygulama sorunudur. son not
Aşağıdaki dönüştürmeler uygulandıktan sonra sırasıyla aynı olan iki koşullu derleme simgesi aynı kabul edilir:
- Her Unicode_Escape_Sequence karşılık gelen Unicode karakterine dönüştürülür.
- Tüm Formatting_Characters kaldırılır.
Koşullu derleme simgesinin iki olası durumu vardır: tanımlı veya tanımsız. Derleme biriminin sözcük temelli işlenmesinin başında, bir dış mekanizma (komut satırı derleyici seçeneği gibi) tarafından açıkça tanımlanmadığı sürece koşullu derleme simgesi tanımlanmamıştır. Bir #define
yönerge işlendiğinde, bu yönergede adlı koşullu derleme simgesi bu derleme biriminde tanımlanır. Sembol, aynı simge için bir #undef
yönerge işlenene kadar veya derleme biriminin sonuna ulaşılana kadar tanımlı kalır. Bunun bir etkisi, bir derleme birimindeki ve #define
yönergelerinin aynı programdaki diğer derleme birimleri üzerinde hiçbir etkisi olmamasıdır#undef
.
Ön işleme ifadesinde (§6.5.3) başvurulduğunda, tanımlı bir koşullu derleme simgesi Boole değerine true
ve tanımsız bir koşullu derleme simgesi boole değerine false
sahiptir. Koşullu derleme simgelerinin ön işleme ifadelerinde başvurulmadan önce açıkça bildirilmesi gerekmez. Bunun yerine, bildirilmemiş simgeler yalnızca tanımlanmamıştır ve bu nedenle değerine false
sahiptir.
Koşullu derleme simgelerinin ad alanı, C# programındaki diğer tüm adlandırılmış varlıklardan farklıdır. Koşullu derleme simgelerine yalnızca ve #define
yönergelerinde #undef
ve ön işleme ifadelerinde başvurulabilir.
6.5.3 Ön işleme ifadeleri
ön işleme ifadeleri ve #if
yönergelerinde #elif
oluşabilir. İşleçler !
(yalnızca ön ek mantıksal olumsuzlama), ==
, !=
, &&
ve ||
ön işleme ifadelerinde izin verilir ve gruplandırma için parantezler kullanılabilir.
fragment PP_Expression
: PP_Whitespace? PP_Or_Expression PP_Whitespace?
;
fragment PP_Or_Expression
: PP_And_Expression (PP_Whitespace? '||' PP_Whitespace? PP_And_Expression)*
;
fragment PP_And_Expression
: PP_Equality_Expression (PP_Whitespace? '&&' PP_Whitespace?
PP_Equality_Expression)*
;
fragment PP_Equality_Expression
: PP_Unary_Expression (PP_Whitespace? ('==' | '!=') PP_Whitespace?
PP_Unary_Expression)*
;
fragment PP_Unary_Expression
: PP_Primary_Expression
| '!' PP_Whitespace? PP_Unary_Expression
;
fragment PP_Primary_Expression
: TRUE
| FALSE
| PP_Conditional_Symbol
| '(' PP_Whitespace? PP_Expression PP_Whitespace? ')'
;
Bir ön işleme ifadesinde başvurulduğunda, tanımlı bir koşullu derleme simgesi Boole değerine true
ve tanımsız bir koşullu derleme simgesi boole değerine false
sahiptir.
Ön işleme ifadesinin değerlendirilmesi her zaman bir Boole değeri verir. Ön işleme ifadesi için değerlendirme kuralları, bir sabit ifadenin (§12.23) kurallarıyla aynıdır, ancak başvurulabilen tek kullanıcı tanımlı varlıklar koşullu derleme simgeleridir.
6.5.4 Tanım yönergeleri
Tanım yönergeleri, koşullu derleme simgelerini tanımlamak veya tanımlamak için kullanılır.
fragment PP_Declaration
: 'define' PP_Whitespace PP_Conditional_Symbol
| 'undef' PP_Whitespace PP_Conditional_Symbol
;
Yönergenin #define
işlenmesi, yönergeyi izleyen kaynak satırdan başlayarak verilen koşullu derleme simgesinin tanımlanmasına neden olur. Benzer şekilde, yönergenin #undef
işlenmesi, yönergeyi izleyen kaynak satırdan başlayarak verilen koşullu derleme simgesinin tanımsız hale gelmesine neden olur.
Derleme birimindeki ve #define
#undef
yönergeleri, derleme ünitesindeki ilk belirteç (§6.4) öncesinde gerçekleşir; aksi takdirde derleme zamanı hatası oluşur. Sezgisel anlamda ve #define
yönergeleri derleme #undef
ünitesindeki tüm "gerçek kodlardan" önce gelir.
Örnek: Örnek:
#define Enterprise #if Professional || Enterprise #define Advanced #endif namespace Megacorp.Data { #if Advanced class PivotTable {...} #endif }
geçerli çünkü
#define
yönergeler derleme birimindeki ilk belirtecin (namespace
anahtar sözcük) önüne geçer.son örnek
Örnek: Aşağıdaki örnek, bir #define gerçek kodu izlediğinden derleme zamanı hatasıyla sonuçlanır:
#define A namespace N { #define B #if B class Class1 {} #endif }
son örnek
, #define
bu simgeye herhangi bir araya #undef
gelmeden önceden tanımlanmış bir koşullu derleme simgesi tanımlayabilir.
Örnek: Aşağıdaki örnek, A koşullu derleme simgesini tanımlar ve sonra yeniden tanımlar.
#define A #define A
Koşullu derleme simgelerinin derleme seçenekleri olarak tanımlanmasına izin veren derleyiciler için, bu tür bir yeniden tanımlamanın gerçekleşmesinin alternatif bir yolu, simgeyi hem derleyici seçeneği olarak hem de kaynakta tanımlamaktır.
son örnek
, #undef
tanımlanmamış bir koşullu derleme simgesini "tanımsız" yapabilir.
Örnek: Aşağıdaki örnek bir koşullu derleme simgesi
A
tanımlar ve ardından iki kez tanımlarını kaldırmıştır; ikincisinin#undef
etkisi olmasa da, yine de geçerlidir.#define A #undef A #undef A
son örnek
6.5.5 Koşullu derleme yönergeleri
Koşullu derleme yönergeleri, bir derleme biriminin bölümlerini koşullu olarak dahil etmek veya hariç tutmak için kullanılır.
fragment PP_Conditional
: PP_If_Section
| PP_Elif_Section
| PP_Else_Section
| PP_Endif
;
fragment PP_If_Section
: 'if' PP_Whitespace PP_Expression
;
fragment PP_Elif_Section
: 'elif' PP_Whitespace PP_Expression
;
fragment PP_Else_Section
: 'else'
;
fragment PP_Endif
: 'endif'
;
Koşullu derleme yönergeleri, sırasıyla bir #if
yönerge, sıfır veya daha fazla #elif
yönerge, sıfır veya bir #else
yönerge ve bir #endif
yönergeden oluşan gruplar halinde yazılmalıdır. Yönergeleri arasında kaynak kodun koşullu bölümleri yer alır. Her bölüm, hemen önceki yönerge tarafından denetlenmektedir. Koşullu bölüm, bu yönergelerin eksiksiz gruplar oluşturması koşuluyla iç içe geçmiş koşullu derleme yönergeleri içerebilir.
Normal sözcük temelli işleme için kapsanan koşullu bölümlerden en az biri seçilir:
-
#elif
biri verenetrue
kadar sırayla değerlendirilir. bir ifadenin verimini verirsetrue
, ilgili yönergeyi izleyen koşullu bölüm seçilir. - Tüm
#else
koşullu bölüm seçilir. - Aksi takdirde, koşullu bölüm seçilmez.
Varsa, seçilen koşullu bölüm normal bir input_section olarak işlenir: bölümde yer alan kaynak kodu sözcüksel dil bilgisine uymalıdır; bölümdeki kaynak kodundan belirteçler oluşturulur ve bölümdeki ön işleme yönergelerinin önceden belirlenmiş etkileri vardır.
Kalan tüm koşullu bölümler atlanır ve ön işleme yönergeleri dışındaki belirteçler kaynak koddan oluşturulmaz. Bu nedenle ön işleme yönergeleri dışında atlanan kaynak kodu sözcüksel olarak yanlış olabilir. Atlanan ön işleme yönergeleri sözcüksel olarak doğru olmalıdır, ancak başka türlü işlenmez. Atlanan bir koşullu bölüm içinde, iç içe geçmiş tüm koşullu bölümler (iç içe #if...#endif
geçmiş yapılarda bulunur) da atlanır.
Not: Yukarıdaki dil bilgisi, ön işleme yönergeleri arasındaki koşullu bölümlerin sözcüksel olarak yanlış biçimlendirilmiş olabileceği iznini yakalamaz. Bu nedenle dil bilgisi ANTLR'ye hazır değildir, yalnızca sözcüksel olarak doğru girişi destekler. son not
Örnek: Aşağıdaki örnekte koşullu derleme yönergelerinin iç içe nasıl yerleştirilebileceği gösterilmektedir:
#define Debug // Debugging on #undef Trace // Tracing off class PurchaseTransaction { void Commit() { #if Debug CheckConsistency(); #if Trace WriteToLog(this.ToString()); #endif #endif CommitHelper(); } ... }
Ön işleme yönergeleri dışında, atlanan kaynak kodu sözcük temelli analize tabi değildir. Örneğin, bölümdeki sonlandırılmamış açıklamaya rağmen aşağıdakiler
#else
geçerlidir:#define Debug // Debugging on class PurchaseTransaction { void Commit() { #if Debug CheckConsistency(); #else /* Do something else #endif } ... }
Ancak, ön işleme yönergelerinin kaynak kodun atlanan bölümlerinde bile sözcüksel olarak doğru olması gerektiğini unutmayın.
Ön işleme yönergeleri, çok satırlı giriş öğeleri içinde göründüklerinde işlenmez. Örneğin, program:
class Hello { static void Main() { System.Console.WriteLine(@"hello, #if Debug world #else Nebraska #endif "); } }
sonuç olarak şu çıktıyı elde edin:
hello, #if Debug world #else Nebraska #endif
Tuhaf durumlarda, işlenen ön işleme yönergeleri kümesi pp_expression değerlendirmesine bağlı olabilir. Örnek:
#if X /* #else /* */ class Q { } #endif
tanımlanıp tanımlanmadığına bakılmaksızın her zaman aynı belirteç akışını (
class
Q
{
}
) üretir.X
TanımlanırsaX
, çok satırlı açıklama nedeniyle yalnızca ve#if
işlenen yönergelerdir#endif
. TanımlanmamışsaX
, yönerge kümesinin üç yönergesi (#if
,#else
,#endif
) bir parçasıdır.son örnek
6.5.6 Tanılama yönergeleri
Tanılama yönergeleri, diğer derleme zamanı hataları ve uyarılarıyla aynı şekilde bildirilen açıkça hata ve uyarı iletileri oluşturmak için kullanılır.
fragment PP_Diagnostic
: 'error' PP_Message?
| 'warning' PP_Message?
;
fragment PP_Message
: PP_Whitespace Input_Character*
;
Örnek: Örnek
#if Debug && Retail #error A build can't be both debug and retail #endif class Test {...}
, koşullu derleme simgeleri
Debug
Retail
ve her ikisi de tanımlanmışsa derleme zamanı hatası ("Derleme hem hata ayıklama hem de perakende olamaz") oluşturur. bir PP_Message rastgele metin içerebileceğini, özellikle de sözcüğündekican't
tek tırnakta gösterildiği gibi iyi biçimlendirilmiş belirteçler içermemesi gerektiğini unutmayın.son örnek
6.5.7 Bölge yönergeleri
Bölge yönergeleri, kaynak kodun bölgelerini açıkça işaretlemek için kullanılır.
fragment PP_Region
: PP_Start_Region
| PP_End_Region
;
fragment PP_Start_Region
: 'region' PP_Message?
;
fragment PP_End_Region
: 'endregion' PP_Message?
;
Bir bölgeye semantik anlam eklenmez; bölgeleri, programcı veya kaynak kodun bir bölümünü işaretlemek için otomatik araçlar tarafından kullanılmak üzere tasarlanmıştır. Her #endregion
yönergeye uyan bir #region
yönerge olacaktır. Aynı şekilde bir #region
veya #endregion
yönergesinde belirtilen iletinin anlamsal bir anlamı yoktur; yalnızca bölgeyi tanımlamaya hizmet eder. Eşleştirme #region
ve #endregion
yönergelerin farklı PP_Messageolabilir.
Bir bölgenin sözcük temelli işlenmesi:
#region
...
#endregion
formun koşullu derleme yönergesinin sözcük temelli işlenmesine tam olarak karşılık gelir:
#if true
...
#endif
Not: Bu, bir bölgenin bir veya daha fazla
#if
/.../#endif
içerebileceği veya bir /.../#if
içindeki#endif
koşullu bölümle kapsanabileceği anlamına gelir; ancak bir bölge /.../#if
öğesinin#endif
yalnızca bir bölümüyle çakışamaz veya farklı koşullu bölümlerde başlatılamaz ve sonlandırılamaz. son not
6.5.8 Satır yönergeleri
Satır yönergeleri, çıkışta bir derleyici tarafından bildirilen satır numaralarını ve derleme birimi adlarını (uyarılar ve hatalar gibi) değiştirmek için kullanılabilir. Bu değerler, çağıran-bilgi öznitelikleri (§22.5.6) tarafından da kullanılır.
Not: Satır yönergeleri en yaygın olarak başka bir metin girişinden C# kaynak kodu oluşturan meta programlama araçlarında kullanılır. son not
fragment PP_Line
: 'line' PP_Whitespace PP_Line_Indicator
;
fragment PP_Line_Indicator
: Decimal_Digit+ PP_Whitespace PP_Compilation_Unit_Name
| Decimal_Digit+
| DEFAULT
| 'hidden'
;
fragment PP_Compilation_Unit_Name
: '"' PP_Compilation_Unit_Name_Character* '"'
;
fragment PP_Compilation_Unit_Name_Character
// Any Input_Character except "
: ~('\u000D' | '\u000A' | '\u0085' | '\u2028' | '\u2029' | '"')
;
hiçbir #line
yönergesi olmadığında, derleyici çıktısında gerçek satır numaralarını ve derleme birimi adlarını bildirir.
için Decimal_Digit+
izin verilen en yüksek değer uygulama tanımlıdır.
Yönerge #line default
, önceki #line
tüm yönergelerin etkisini geri alır. Derleyici, sonraki satırlar için doğru satır bilgilerini, sanki hiçbir #line
yönergesi işlenmemiş gibi, tam olarak bildirir.
Yönergenin#line hidden
, hata iletilerinde bildirilen veya (CallerLineNumberAttribute
) ile üretilen derleme birimi ve satır numaraları üzerinde hiçbir etkisi yoktur. Kaynak düzeyinde hata ayıklama araçlarını etkilemek için tasarlanmıştır; böylece hata ayıklarken, bir #line hidden
yönerge ile sonraki #line
yönerge (yani) #line hidden
arasındaki tüm satırlarda satır numarası bilgisi yoktur ve kodda ilerlerken tamamen atlanır.
Not: bir PP_Compilation_Unit_Name kaçış dizisi gibi görünen bir metin içerse de, bu tür metin bir kaçış dizisi değildir; bu bağlamda '
\
' karakteri yalnızca sıradan bir ters eğik çizgi karakteri belirtir. son not
6.5.9 Null atanabilir yönergesi
Null atanabilir yönergesi, aşağıda açıklandığı gibi null atanabilir bağlamı denetler.
fragment PP_Nullable
: 'nullable' PP_Whitespace PP_Nullable_Action
(PP_Whitespace PP_Nullable_Target)?
;
fragment PP_Nullable_Action
: 'disable'
| 'enable'
| 'restore'
;
fragment PP_Nullable_Target
: 'warnings'
| 'annotations'
;
Null atanabilir yönerge, başka bir null atanabilir yönerge geçersiz kılana kadar veya derleme _unit sonuna ulaşılana kadar sonraki kod satırları için kullanılabilir bayrakları ayarlar. Null atanabilir bağlam iki bayrak içerir: ek açıklamalar ve uyarılar. Null atanabilir yönergenin her biçiminin etkisi aşağıdaki gibidir:
-
#nullable disable
: Hem null atanabilir ek açıklamaları hem de null atanabilir uyarı bayraklarını devre dışı bırakır. -
#nullable enable
: Hem null atanabilir ek açıklamaları hem de null atanabilir uyarı bayraklarını etkinleştirir. -
#nullable restore
: Varsa, hem ek açıklamaları hem de uyarı bayraklarını dış mekanizma tarafından belirtilen duruma geri yükler. -
#nullable disable annotations
: Null atanabilir ek açıklamalar bayrağını devre dışı bırakır. Null atanabilir uyarılar bayrağı etkilenmez. -
#nullable enable annotations
: Null atanabilir ek açıklamalar bayrağını etkinleştirir. Null atanabilir uyarılar bayrağı etkilenmez. -
#nullable restore annotations
: Boş değer atanabilir ek açıklamalar bayrağını varsa dış mekanizma tarafından belirtilen duruma geri yükler. Null atanabilir uyarılar bayrağı etkilenmez. -
#nullable disable warnings
: Null atanabilir uyarılar bayrağını devre dışı bırakır. Null atanabilir ek açıklamalar bayrağı etkilenmez. -
#nullable enable warnings
: Null atanabilir uyarılar bayrağını etkinleştirir. Null atanabilir ek açıklamalar bayrağı etkilenmez. -
#nullable restore warnings
: Varsa, null atanabilir uyarılar bayrağını dış mekanizma tarafından belirtilen duruma geri yükler. Null atanabilir ek açıklamalar bayrağı etkilenmez.
İfadelerin null atanabilir durumu her zaman izlenir. Ek açıklama bayrağının durumu ve null atanabilir bir ek açıklamanın varlığı veya yokluğu, ?
değişken bildiriminin ilk null durumunu belirler. Uyarılar yalnızca uyarı bayrağı etkinleştirildiğinde verilir.
Örnek: Örnek
#nullable disable string x = null; string y = ""; #nullable enable Console.WriteLine(x.Length); // Warning Console.WriteLine(y.Length);
bir derleme zamanı uyarısı ("olduğu
x
gibinull
") üretir. null atanabilir durumux
her yerde izlenir. Uyarılar bayrağı etkinleştirildiğinde bir uyarı verilir.son örnek
6.5.10 Pragma yönergeleri
Ön #pragma
işleme yönergesi, derleyiciye bağlamsal bilgileri belirtmek için kullanılır.
Not: Örneğin, bir derleyici şu yönergeleri sağlayabilir
#pragma
:
- Sonraki kodu derlerken belirli uyarı iletilerini etkinleştirin veya devre dışı bırakın.
- Sonraki koda uygulanacak iyileştirmeleri belirtin.
- Hata ayıklayıcı tarafından kullanılacak bilgileri belirtin.
son not
fragment PP_Pragma
: 'pragma' PP_Pragma_Text?
;
fragment PP_Pragma_Text
: PP_Whitespace Input_Character*
;
PP_Pragma_Text içindeki Input_Character, derleyici tarafından uygulamaya göre belirlenmiş bir biçimde yorumlanır. Yönergede #pragma
verilen bilgiler program semantiğini değiştirmez. Yönerge #pragma
yalnızca bu dil belirtiminin kapsamı dışında olan derleyici davranışını değiştirecektir. Derleyici Input_Characteryorumlayamıyorsa, derleyici bir uyarı üretebilir; ancak derleme zamanı hatası oluşturmaz.
Not: PP_Pragma_Text rastgele metin içerebilir; özellikle iyi biçimlendirilmiş belirteçler içermesi gerekmez. son not
ECMA C# draft specification