Sentaks (Sözdizim) ve Semantik (Anlam)
Sözdizim ve anlam bir dili tanımlamayı sağlar. Giriş Sözdizimi: İfadelerin (expression), beyanların (statement) ve program ünitelerinin yapısı Anlam: İfadelerin (expression), beyanların (statement) ve program ünitelerinin anlamı Sözdizim ve anlam bir dili tanımlamayı sağlar. 1-2 2
Örnek: Sentaks ve Semantik while beyanı sentaks: while (<boolean_ifade>) <beyan> semantik: boolean_ifade doğru olunca beyan çalıştırılır.
Sentaksı Tanımlama: Terminoloji Alfabe: Σ, Bütün stringler: Σ* Bir cümle belirli bir alfabe üzerindeki karakterlerden oluşan bir string dir. Bir dil (L) cümleler kümesidir. L ⊆ Σ* 4
Sentaksı Tanımlama: Terminoloji Bir dil (L) cümleler kümesidir. Doğal Diller: İngilizce, Türkçe, … Programlama Dilleri: C, Fortran, Java,… Formal Diller: a*b*, 0n1n Yukarıdaki dillerin sırayla string leri nelerdir? Cümleler Program beyanları Kelimeler (aaaaabb, 000111)
Lexeme ler lexeme bir dilin en düşük seviyedeki sentaktik birimidir. (Örn., *, sum, begin) Düşük seviyedeki yapılar sentaks tarafından değil lexical spesifikasyonlarla verilir. Örnekler: identifiers (değişkenler), constants (sabitler), operators (operatörler), special words (özel kelimeler). toplam, carpim, 1254, ++, (, : Bu yüzden, bir dil lexeme stringlerinden oluşan bir kümedir. Dil, rastgele karakter stringlerinden oluşan bir küme değildir!!!
Token Dildeki bir token, lexeme lerin kategorisidir (sınıfıdır). Örneğin, identifier bir token dır ve sum ve total gibi lexeme değerleri alabilir.
Java Dilinden Bir Örnek
Sentaksı Tanımlama Daha yukarı seviye yapılar sentaks kuralları ile verilir. Sentaks kuralları, Σ* içindeki hangi stringlerin dile ait olduğunu belirtir. Örnekler: döngü yapıları, atama, ifadeler, alt program tanımları ve çağırmaları.
Sentaksın Elemanları Sembollerden oluşan bir alfabe Semboller ya terminal ya da non-terminal (terminal olmayan) dir. Terminaller daha fazla parçalanamazlar. Non-terminaller daha fazla parçalanabilirler. Sembollerin ne şekilde birleşerek legal cümleler oluşturacağını belirten gramer kuralları Kurallar şu genel forma sahiptir: non-terminal sembol::= sıfır ya da daha fazla sayıda terminal ya da non-terminallerden oluşan bir liste Kuralları kullanarak legal cümleleri tanımaya (ayrıştırmaya) (parse etmeye) çalışırız.
İçerikten Bağımsız Gramer A context-free grammar (CFG) is a set of recursive rewriting rules (or productions) used to generate patterns of strings. A CFG consists of the following components: a set of terminal symbols, which are the characters of the alphabet that appear in the strings generated by the grammar. a set of nonterminal symbols, which are placeholders for patterns of terminal symbols that can be generated by the nonterminal symbols. a set of productions, which are rules for replacing (or rewriting) nonterminal symbols (on the left side of the production) in a string with other nonterminal or terminal symbols (on the right side of the production). a start symbol, which is a special nonterminal symbol that appears in the initial string generated by the grammar. Why are such grammars called `context free'? Because all rules contain only one symbol on the left hand side --- and wherever we see that symbol while doing a derivation, we are free to replace it with the stuff on the right hand side. That is, the 'context' in which a symbol on the left hand side of a rule occurs is unimportant --- we can always use the rule to make the rewrite while doing a derivation.
Backus-Naur Form (BNF) Programlama Dillerinin sentaksını tanımlayan bir notasyondur. Nereden geliyor? John Backus – Algol 58 Peter Naur – Algol 60 Bir metadil (metalanguage) diğer bir dili tanımlamak için kullanılan dile denir. BNF diğer PL leri (Programlama Dillerini) tanımlamak için kullanılan bir metadildir.
BNF Temel Bilgileri BNF sentaktik yapılar için soyutlamalar kullanır: <LHS> → <RHS> LHS (Left-Hand Side) (Sol El Tarafı): tanımlanan soyutlama RHS (Right-Hand Side) (Sağ El Tarafı): tanım “→” şu demektir: “yandaki şekli alabilir.” Bazen → yerine ::= kullanılır.
BNF Temel Bilgileri Örneğin Java atama beyanı (assignment statement) <assign> soyutlamasıyla temsil edilebilir. <assign> → <variable> = <expression> Bu bir rule (kural) ya da production (üretim) dir. Burada, <variable> ve <expression> de tanımlanmalıdır. Bu soyutlamanın örnek instance ları şunlar olabilir: toplam = deger1 + deger2 x = 4 variable: değişken, expression: ifade
BNF Temel Bilgileri Bu soyutlamalar gramerin Variable, ya da Nonterminal leridir. Tokenlar gramerin Terminal leridir. Nonterminaller genelde <> içerisinde gösterilir. Örnek BNF kuralları: <ident_list> → identifier | identifier, <ident_list> <if_stmt> → if <logic_expr> then <stmt>
BNF Temel Bilgileri Rule un resmi tanımı: <LHS> → <RHS> rule un sol tarafı nonterminaldir, sağ tarafı ise terminal ve/veya non-teminallerin karışımıdır. <LHS> → <RHS> Gramer: sonlu, boş olmayan kurallar (rule lar) kümesidir.
İlk Örnek Aşağıdaki cümleye bakalım. “Marry selamlar John” Basit bir gramer <cümle> ::= <özne><belirteç> <özne> ::= Mary <belirteç> ::= <fiil><nesne> <fiil> ::= selamlar <nesne> ::= John
Değişimler Çoklu tanımları | (OR) ile ayırma: <nesne> ::= John | Ali Bu ekleme “Mary selamlar Ali” yi yasal cümlelere ekler. Biraz daha değiştirelim: <özne> ::= Mary | John | Ali <nesne> ::= Mary | John | Ali Yeni gramerimiz: <cümle> ::= <özne><belirteç> <özne> ::= <isim> <belirteç> ::= <fiil><nesne> <fiil> ::= selamlar <nesne> ::= <isim> <isim> ::= Mary | John | Ali
Sonsuz Sayıda Cümle <nesne> ::= Ali| Ali tekrar| Ali tekrar ve tekrar| …. Bunun yerine rekürsif tanım kullanalım. <nesne> ::= Ali | Ali <tekrar faktörü> <tekrar faktörü> ::= tekrar| tekrar ve <tekrar faktörü> Bir kuralın LHS si aynı anda RHS içinde yer alıyorsa, o kural rekürsiftir.
Programlama Dilleri İçin Basit Bir Örnek Basit aritmetiği nasıl tanımlarsınız? <ifade> ::= <ifade> <operator> <ifade> |<değişken> | <işaretli sayı> <operator> ::= + | - | * | / <değişken> ::= a | b | c | … <işaretli sayı> ::= + <sayı> | - <sayı> <sayı> ::= <sayı> <rakam> | <rakam> <rakam>::= 0|1|….|9
if Statement (if Beyanı) <if_stmt> → if <logic_expr> then <stmt> <if_stmt> → if <logic_expr> then <stmt> else <stmt> Ya da | if <logic_expr> then <stmt> else <stmt> logic expr: mantıksal ifade stmt: beyan (statement ın kısaltılmışı)
Gramerler ve Türetmeler (Grammars and Derivations ) Bir gramer, dilleri tanımlamak için üretici bir aygıttır. Bir dilin cümleleri kuralların belirli bir sırada uygulanmasıyla oluşturulur. İlk başlayacağımız kuralın sol tarafı özel bir nonterminaldir. Bu bir başlangıç sembolüdür. Böyle bir üretimin diğer adı da türetmedir.
Örnek Bir Gramer <program> → begin <stmt_list> end <stmt_list> → <stmt> | <stmt> ; <stmt_list> <stmt> → <variable> := <expression> <variable> → A | B | C <expression>→ <variable> | <variable> <operator> <variable> <operator> → + | - | * | / 23
Türetme (Derivation) Bir input string inin dile ait olup olmadığını anlamak için onu gramer vasıtasıyla türetmeye çalışırız. Türetme işlemi başlama sembolü olarak hangi nonterminal seçilmişse ondan başlar. Eğer belirtilmemişse ilk kuralın LHS sindeki nonterminalden türetme işlemine başlarız. Türetmenin her adımında bir nonterminali, tanımındaki RHS ile yer değiştiririz.
Örnek Bir Türetme Şu stringi türetelim: begin A := B; C := A * B end <program> ⇒ begin <stmt_list> end ⇒ begin <stmt> ; <stmt_list> end ⇒ begin <variable> := <expression>; <stmt_list> end ⇒ begin A := <expression>; <stmt_list> end ⇒ begin A := <variable>; <stmt_list> end ⇒ begin A := B; <stmt_list> end ⇒ begin A := B; <stmt> end ⇒ begin A := B; <variable> := <expression> end ⇒ begin A := B; C := <expression> end ⇒ begin A := B; C := <variable><operator><variable> end ⇒ begin A := B; C := A <operator> <variable> end ⇒ begin A := B; C := A * <variable> end ⇒ begin A := B; C := A * B end Eğer hep en soldaki nonterminali tanımı ile yer değiştiriyorsak buna leftmost derivation (en sol türetme) denir.
Örneğe Ait Ayrıştırma Ağacı A parse tree is a graphical representation of a derivation.
Gramerlerde Belirsizlik (Ambiguity) Birden fazla ayrıştırma (parse) ağacı oluşturan bir gramer belirsizdir. 27
A = B + C * A için ayrıştırma ağacı yapalım. Örnek Aşağıdaki gramer verilmiş olsun: <assign> ::= <id> = <expr> <id> ::= A | B | C <expr> ::= <expr> + <expr> | <expr> * <expr> | (<expr>) | <id> A = B + C * A için ayrıştırma ağacı yapalım.
A = B + C * A için ayrıştırma ağaçları
Belirsizlik Bir programlama dilinin grameri belirsiz olmamalıdır. Belirsizliği düzeltmek için çözümler vardır. Operatör (işleç) önceliği (Operator precedence)
İşleç Önceliği (Operator Precedence) Matematikte *, + dan önceliklidir. Fazla nonterminal kullanımı ile bunu sağlayabiliriz. <assign> ::= <id> = <expr> <id> ::= A | B | C <expr> ::= <expr> + <expr> | <expr> * <expr> | (<expr>) | <id> <assign> ::= <id> = <expr> <id> ::= A | B | C <expr> ::= <expr> + <term> | <term> <term> ::= <term> * <factor> | <factor> <factor> ::= (<expr>) | <id>
A = B + C * A İçin Tekil Ayrıştırma Ağacı -----
Sallanan else Belirsizliği (Dangling else) if a then if b then s1 else s2 Yukarıdaki satırda sırasıyla a ve b koşulları kontrol edilecek ardından başarılı olunursa s1 satırı çalışacaktır. Ancak else satırının (s2) hangi durumda çalışacağı bir muammadır. Burada iki ihtimal bulunur : a başarısızlığında s2’nin çalışması b başarısızlığında s2’nin çalışması Bu belirsizlik aşağıdaki şekilde modellenebilir: if a then { if b then s1 } else s2 This dangling-else ambiguity problem was first discovered around 1960 in the ALGOL60 programming language. if a then { if b then s1 } else s2 } Dangling else problem: there are more if then else http://bilgisayarkavramlari.sadievrenseker.com/2008/11/17/dangling-else-sallanan-else/ Birçok programlama dili şu kuralı benimser: “Bir else daha önce eşleşmemiş en yakın if ile eşleşir.”