lexers vs parsers


308

Lexers ve ayrıştırıcılar teoride gerçekten bu kadar farklı mı?

Düzenli ifadelerden nefret etmek moda görünüyor: kodlama korkusu , başka bir blog yazısı .

Ancak, popüler lexing araçları tabanlı: pygments , geshi veya hoşlaştırmak , tüm kullanım düzenli ifadeler. Her şeyi seviyor gibi görünüyorlar ...

Lexing ne zaman yeterli, EBNF'ye ne zaman ihtiyacınız var?

Bu lexers tarafından üretilen jetonları bizon veya antlr ayrıştırıcı jeneratörleri ile kullanan var mı?


2
Evet. Autohotkey'i ayrıştırmaya çalışıyorum. Pıhtıları gerçekten hızlı kullanarak bir sözdizimi vurgulayıcı oluşturabiliyordum. Ama antlr çok daha uzun sürüyor ... İki araç arasında çok fazla çapraz tozlaşma görmedim.
Naveen

67
Yanlış kullanıldığında düzenli ifadelerden nefret etmek tek moda. Bağlamsız ayrıştırma gerektiğinde birçok kişi düzenli ifadeler kullanmaya çalışır. Her zaman başarısız olurlar. Ve düzenli ifade teknolojisini suçluyorlar. Bu, çekiçinizin kırıcı bir testere olduğundan şikayet etmeye benzer. Doğru, ama çok fazla sempati görmeyeceksin.
Ira Baxter

2
Neyse ki antlr ile biraz hızlanmaya başlıyorum. Bir çok lexing bağlamdan bağımsızdır ve hatta bazen içeriğe de bağlıdır.
Naveen

1
Lexer ve ayrıştırıcı sorununun temel bir yönü, lexerlerin sonlu otomata (FSA) veya daha kesin olarak sonlu transdüserlere (FST) dayanmasıdır. Ayrıştırma formalizmlerinin çoğu (sadece Bağlamdan bağımsız değil) FSA veya FST uygulaması ile kesişme altında kapalıdır. Bu nedenle, sözlük için daha basit düzenli ifade tabanlı formnalizmin kullanılması, daha karmaşık ayrıştırıcı formalizmlerin sözdizimsel yapılarının karmaşıklığını arttırmaz. Bu, dillerin yapısını ve semantiğini tanımlarken kesinlikle büyük bir modülerlik sorunudur ve yüksek oylanan cevaplar tarafından göz ardı edilir.
babou

Bu lexers ve ayrıştırıcıları olmadığını belirtmek gerekir sahip farklı olmak, mesela LLLPG ve antlr önceki sürümleri lexers ve ayrıştırıcıları ikisi için de aynı LL (k) ayrıştırma sistemi kullanın. Temel fark regex'lerin genellikle sözlükler için yeterli olması ancak ayrıştırıcılar için yeterli olmamasıdır.
Qwertie

Yanıtlar:


475

Ayrıştırıcıların ve sözlükçelerin ortak noktası:

  1. Bazı alfabe sembollerini girdilerinden okurlar .

    • İpucu: Alfabenin harflerden olması gerekmez. Ancak , parser / lexer tarafından anlaşılan dil için atomik semboller olmalıdır .
    • Lexer için semboller: ASCII karakterleri.
    • Ayrıştırıcı için semboller: gramerlerinin terminal sembolleri olan belirli jetonlar.
  2. Bu sembolleri analiz ederler ve anladıkları dilin grameri ile eşleştirmeye çalışırlar .

    • Gerçek fark genellikle burada yatmaktadır. Daha fazla bilgi için aşağıya bakın.
    • Dilbilgisi sözcükleri tarafından anlaşıldı: düzenli dilbilgisi (Chomsky'nin seviye 3).
    • Dilbilgisi ayrıştırıcılar tarafından anlaşıldı: bağlamsız dilbilgisi (Chomsky'nin seviye 2).
  3. Buldukları dil parçalarına anlambilim (anlam) eklerler .

    • Lexers sınıflandırarak anlam eklemek lexemes edilmiş olarak (girişinden sembollerin dizeleri) belirteçleri . Örneğin Bütün bu lexemeler: *, ==, <=, ^C / C ++ lexer tarafından belirteci "operatörü" olarak sınıflandırılır.
    • Ayrıştırıcılar, girdiden (cümle) belirteç dizelerini belirli terminal olmayanlar olarak sınıflandırarak ve ayrıştırma ağacını oluşturarak anlam ekler . Örneğin tüm bu belirteç dizeleri: [number][operator][number], [id][operator][id], [id][operator][number][operator][number]C / C ++ çözümleyici tarafından terminal olmayan "ifadesi" olarak sınıflandırılır.
  4. Tanınan öğelere bazı ek anlamlar (veriler) ekleyebilirler.

    • Bir lexer uygun bir sayı oluşturan bir karakter dizisini tanıdığında, onu ikili değerine dönüştürebilir ve "sayı" belirteci ile saklayabilir.
    • Benzer şekilde, bir ayrıştırıcı bir ifadeyi tanıdığında, değerini hesaplayabilir ve sözdizimi ağacının "ifade" düğümü ile depolayabilir.
  5. Hepsi çıktılarında tanıdıkları dilin uygun cümlelerini üretir .

    • Lexers üretmek belirteçleri olan cümleler arasında düzenli dili tanıdıkları. Her token bir iç sözdizimine sahip olabilir (seviye 3 değil, seviye 2 olsa da), ancak bu çıkış verileri ve bunları okuyanlar için önemli değildir.
    • Ayrıştırıcılar üretmek sözdizimi ağaçları temsilleridir, cümle içinde bağlam serbest dilin tanıdıkları. Genellikle tüm belge / kaynak dosyası için sadece bir büyük ağaçtır, çünkü tüm belge / kaynak dosyası onlar için uygun bir cümledir . Ancak ayrıştırıcının çıktısında bir dizi sözdizimi ağacı üretememesinin bir nedeni yoktur. Örneğin, düz metne yapıştırılmış SGML etiketlerini tanıyan bir ayrıştırıcı olabilir. Bu yüzden edeceğiz tokenize jeton bir dizi haline SGML belgesi: [TXT][TAG][TAG][TXT][TAG][TXT]....

Gördüğünüz gibi, ayrıştırıcıların ve belirteçlerin ortak noktaları var. Bir ayrıştırıcı, giriş belirteçlerini kendi alfabesinden semboller olarak (belirteçler sadece bazı alfabelerin sembolleri) okuyan diğer ayrıştırıcı için bir belirteç olabilir, bir dilden gelen cümleler diğer bazı daha yüksek seviyedeki alfabetik semboller olabilir dil. Örneğin, *ve -alfabenin sembolleri M( "Morse kodu semboller" gibi), o zaman Mors kodu kodlanmış harfleri olarak bu noktaların ve çizgilerin dizeleri tanıdığı bir ayrıştırıcı inşa edebilirsiniz. Dil "Mors Kodu" cümle olabilir belirteçleri diğer bazı ayrıştırıcı için, bu jetonlardilinin atom sembolleri (örn. "İngilizce Kelimeler" dili). Ve bu "İngilizce Kelimeler", "İngilizce Cümleler" dilini anlayan bazı üst düzey ayrıştırıcılar için jetonlar (alfabenin sembolleri) olabilir. Ve tüm bu diller sadece dilbilgisinin karmaşıklığında farklılık gösterir . Başka bir şey yok.

Peki bu "Chomsky'nin dilbilgisi seviyeleri" ne olacak? Noam Chomsky, gramerlerini karmaşıklıklarına bağlı olarak dört seviyeye sınıflandırdı:

  • Seviye 3: Düzenli dilbilgisi

    Bunlar olduğunu, sadece alfabenin sembollerin oluşabilir, normal ifadeler kullanır ( a, b) onların concatenations ( ab, aba, bbb. ETD), veya alternatifler (örn a|b).
    NFA (Belirsiz Sonlu Otomat) veya daha iyi DFA (Deterministik Sonlu Otomat) gibi sonlu durum otomatları (FSA) olarak uygulanabilirler.
    Düzenli dilbilgileri , örneğin düzgün iç içe / eşleştirilmiş parantez , iç içe HTML / BBcode etiketleri, iç içe bloklar vb. Gibi iç içe geçmiş sözdizimi(()()(()())) ile baş edemez.
  • Seviye 2: Bağlamdan bağımsız gramerler

    Sözdizimi ağaçlarında iç içe geçmiş, özyinelemeli, kendine benzer dallara sahip olabilirler, böylece iç içe geçmiş yapılarla iyi başa çıkabilirler.
    Yığınlı durum otomatı olarak uygulanabilirler. Bu yığın, sözdiziminin yuvalama düzeyini temsil etmek için kullanılır. Pratikte, genellikle iç içe geçme seviyesini izlemek için makinenin yordam çağrısı yığınını kullanan ve sözdizimindeki terminal olmayan her sembol için özyineli olarak adlandırılan yordamlar / işlevler kullanan yukarıdan aşağıya, özyinelemeli bir ayrıştırıcı olarak uygulanırlar.
    Ancak bağlama duyarlı bir sözdizimi ile başa çıkamazlar. Örneğin, bir ifadeniz olduğunda x+3ve bir bağlamda bu xbir değişkenin adı olabilir ve diğer bağlamda bir işlevin adı olabilir.
  • Seviye 1: Bağlama duyarlı dilbilgisi

  • Seviye 0: Sınırsız gramerler
    Yinelenen numaralandırılabilir gramerler olarak da adlandırılır.


70
Ah evet? Peki şu "kelimeler veya jetonlar" nedir? Bunlar sadece alfabenin harflerinden oluşan normal dilde cümlelerdir . Ayrıştırıcıdaki "yapılar" veya "ağaçlar" nelerdir? Ayrıca cümlelerdir , ancak belirli tokenlerin alfabetik semboller olduğu farklı, daha üst düzey bir dilde. Fark, söyledikleriniz değil, KULLANILAN DİLİN KARMAŞIKLIĞINDA . Ayrıştırma teorisi hakkında herhangi bir el kitabı ile -1 ile yüzleşin.
SasQ

3
@SasQ Hem Lexers hem de Parsers'ın girdi olarak biraz dilbilgisi ve bir dizi jeton aldığını söylemek adil olur mu?
Parag

4
Oldukça öyle. Her ikisi de tanıdıkları alfabeden bir dizi sembol alır. Lexer için, bu alfabe sadece düz karakterlerden oluşur. Ayrıştırıcı için alfabe, ne tanımlanırsa tanımlansın terminal sembollerinden oluşur. Eğer lexer kullanmazsanız ve tek karakterli tanımlayıcılar ve tek haneli sayılar vb. Kullanırsanız, bunlar da karakter olabilir (gelişimin ilk aşamalarında oldukça yararlıdır). Ancak bunlar genellikle jetonlardır (sözcük sınıfları) çünkü jetonlar iyi bir soyutlamadır: temsil ettikleri gerçek lexemleri (dizeleri) değiştirebilirsiniz ve ayrıştırıcı değişikliği görmez.
SasQ

6
Örneğin, STMT_ENDtalimatların sonunu belirtmek için sözdiziminizde (ayrıştırıcı için) bir terminal sembolü kullanabilirsiniz . Artık lexer tarafından oluşturulan, onunla ilişkili aynı ada sahip bir jetonunuz olabilir. Ama bunun gerçek anlamını değiştirebilirsiniz. Örneğin. C / C ++ benzeri kaynak koduna sahip STMT_ENDolarak tanımlayabilirsiniz ;. Ya endda onu bir şekilde Pascal tarzına benzetmek olarak tanımlayabilirsiniz . Ya da sadece '\n'Python'da olduğu gibi, talimatı satır sonu ile bitirmek olarak tanımlayabilirsiniz . Ancak komut sözdizimi (ve ayrıştırıcı) değişmeden kalır :-) Sadece lexer'ın değiştirilmesi gerekir.
SasQ

24
Vikipedi ve Google'da saatler işe yaramadı, ancak Chomsky'nin gramerlerini 3 dakika içinde açıkladınız. Teşekkür ederim.
enrey

107

Evet, teoride ve uygulamada çok farklılar.

Lexers, dil öğelerini oluşturan "kelimeleri" tanımak için kullanılır, çünkü bu tür kelimelerin yapısı genellikle basittir. Düzenli ifadeler, bu daha basit yapıyı ele alma konusunda son derece iyidir ve lexer'ları uygulamak için kullanılan çok yüksek performanslı düzenli ifadeli eşleştirme motorları vardır.

Ayrıştırıcılar, bir dil ifadesinin "yapısını" tanımak için kullanılır. Bu tür yapı genellikle "düzenli ifadelerin" tanıyabileceğinin çok ötesindedir, bu nedenle bu yapıyı çıkarmak için "bağlama duyarlı" ayrıştırıcılara ihtiyaç vardır. Bağlama duyarlı ayrıştırıcıların oluşturulması zordur, bu nedenle mühendislikten ödün vermek "bağlamsız" gramerler kullanmak ve bağlama duyarlı parçayı işlemek için ayrıştırıcılara ("sembol tabloları" vb.) Kesmek eklemektir.

Ne lexing ne de ayrıştırma teknolojisi yakında ortadan kalkacak gibi görünüyor.

Bunlar olabilir olarak şu anda sözde scannerless GLR'nin ayrıştırıcıları tarafından keşfedilmeden, "kelimelerini" tanımak için teknoloji "ayrıştırma" kullanmaya karar birleşmiş olabilirler. Genellikle çalışma gerektirmeyen bir soruna daha genel makineler uyguladığınız için çalışma zamanı maliyeti vardır ve genellikle bunun bedelini ödersiniz. Çok sayıda serbest döngünüz olduğunda, bu ek yük önemli olmayabilir. Çok fazla metin işlerseniz, ek yük önemli olur ve klasik düzenli ifade ayrıştırıcıları kullanılmaya devam eder.


40
Güzel açıklama Ira. Analojinize ekleme: Sözlükler kelimeleri doğru yapmakla ilgili olsa da, ayrıştırıcılar cümleleri doğru yapmakla ilgilidir. "Spot çalışmasına bakın" ve "spot çalışmasına bak" sözcüklerinin her ikisi de bir lexer söz konusu olduğunda geçerlidir. Cümle yapısının yanlış olduğunu belirlemek için bir ayrıştırıcı gerekir (İngilizce dilbilgisi).
Alan

sanırım bir ayrıştırıcı bir ağaç yürüteç bir ayrıştırıcı olduğu gibi bir lexer olduğunu. Teorinin farklı olduğuna ikna olmadım: antlr.org/wiki/display/~admin/ANTLR+v4+lexers ama aralarındaki sözleşmedeki farklılıkları anlamaya başlıyorum ...
Naveen

4
Teori çok farklı. Ayrıştırıcı teknolojilerinin çoğu bağlamsız dilleri bir dereceye kadar ele almaya çalışmaktadır (bazıları sadece kısmen, örneğin LALR, bazıları ise, örneğin GLR). Çoğu lexer teknolojisi yalnızca düzenli ifadeler yapmaya çalışır.
Ira Baxter

3
Teori farklıdır, çünkü birçok farklı insan tarafından önerilmiştir ve farklı terminoloji ve algoritmalar kullanır. Ancak onlara yakından bakarsanız, benzerlikleri tespit edebilirsiniz. Örneğin, sol özyineleme sorunu NFA'larda determinizm sorununa çok benzer ve sol özyinelemeyi kaldırmak determinizmi ortadan kaldırmaya ve NFA'yı DFA'ya dönüştürmeye benzer. Jetonlar, tokenizer (çıktı) için cümlelerdir, ancak ayrıştırıcı (girdi) için alfabetik sembollerdir. Farklılıkları (Chomsky seviyeleri) inkar etmiyorum, ancak benzerlikler tasarımda çok yardımcı oluyor.
SasQ

1
Memurum kategori teorisindeydi. Kasnakların kategorik teori kavramının her türlü desen eşleşmesini nasıl kapsadığını ve soyut bir kategorik spesifikasyondan LR ayrışmasını türetebildiğini gösterdi. Aslında, yeterince soyutlaşırsanız, bu tür ortaklıkları bulabilirsiniz. Kategori teorisinin amacı genellikle "sonuna kadar" soyutlayabileceğinizdir; Farklılıkları silen bir kategori teorisi ayrıştırıcısı oluşturabileceğinize eminim. Ancak bunun pratik kullanımlarının belirli bir problem alanına doğru bir şekilde başlaması gerekir ve daha sonra farklılıklar gerçek olarak ortaya çıkar.
Ira Baxter

32

Lexing ne zaman yeterli, EBNF'ye ne zaman ihtiyacınız var?

EBNF , gramerlerin gücüne gerçekten fazla bir şey katmıyor. Standart Chomsky'nin Normal Form (CNF) dilbilgisi kurallarına göre sadece bir kolaylık / kısayol gösterimi / "sözdizimsel şeker" dir . Örneğin, EBNF alternatifi:

S --> A | B

CNF'de her alternatif üretimi ayrı ayrı listeleyerek başarabilirsiniz:

S --> A      // `S` can be `A`,
S --> B      // or it can be `B`.

EBNF'den isteğe bağlı eleman:

S --> X?

CNF'de null edilebilir bir üretim, yani boş bir dize ile değiştirilebilen (burada sadece boş üretim ile gösterilir; diğerleri epsilon veya lambda veya çapraz daire kullanır) kullanarak elde edebilirsiniz:

S --> B       // `S` can be `B`,
B --> X       // and `B` can be just `X`,
B -->         // or it can be empty.

BYukarıdaki sonuncusu gibi bir formata "silme" denir, çünkü diğer prodüksiyonlarda ne anlama geldiğini silebilir (başka bir şey yerine boş bir dize üretebilir).

EBNF'den sıfır veya daha fazla tekrar:

S --> A*

özyinelemeli üretimi, yani kendisini içinde bir yere gömen bir nesneyi elde edebilirsiniz . İki şekilde yapılabilir. Birincisi sol özyineleme (genellikle kaçınılmalıdır, çünkü Yukarıdan Aşağı Özyinelemeli İniş ayrıştırıcıları ayrıştıramıyor):

S --> S A    // `S` is just itself ended with `A` (which can be done many times),
S -->        // or it can begin with empty-string, which stops the recursion.

Sadece boş bir dize (sonuçta) ve ardından sıfır veya daha fazla As ürettiğini bilerek , aynı dize ( ancak aynı dil değil! ) Sağ özyineleme kullanılarak ifade edilebilir :

S --> A S    // `S` can be `A` followed by itself (which can be done many times),
S -->        // or it can be just empty-string end, which stops the recursion.

+EBNF'den bir veya daha fazla tekrar söz konusu olduğunda :

S --> A+

birini çarpanlarına ayırıp daha önce olduğu gibi Akullanarak yapabilirsiniz *:

S --> A A*

CNF'de böyle ifade edebilirsiniz (burada doğru özyineleme kullanıyorum; diğerini egzersiz olarak anlamaya çalışın):

S --> A S   // `S` can be one `A` followed by `S` (which stands for more `A`s),
S --> A     // or it could be just one single `A`.

Bunu bilerek, artık normal bir ifade için bir dilbilgisini (yani, normal dilbilgisi ) yalnızca terminal sembollerinden oluşan tek bir EBNF üretiminde ifade edilebilecek bir dilbilgisi tanıyabilirsiniz . Daha genel olarak, bunlara benzer prodüksiyonlar gördüğünüzde düzenli gramerleri tanıyabilirsiniz:

A -->        // Empty (nullable) production (AKA erasure).
B --> x      // Single terminal symbol.
C --> y D    // Simple state change from `C` to `D` when seeing input `y`.
E --> F z    // Simple state change from `E` to `F` when seeing input `z`.
G --> G u    // Left recursion.
H --> v H    // Right recursion.

Yani, sadece boş dizeler, terminal sembolleri, ikameler ve durum değişiklikleri için basit terminaller kullanma ve yalnızca tekrarlama elde etmek için özyineleme kullanma (sadece doğrusal özyineleme olan yineleme - ağaç benzeri olmayan dal). Bunların üzerinde daha gelişmiş bir şey yok, o zaman düzenli bir sözdizimi olduğundan eminsiniz ve bunun için sadece lexer ile gidebilirsiniz.

Ancak sözdiziminiz, aşağıdaki gibi ağaç benzeri, kendine benzer, iç içe yapılar oluşturmak için özyinelemeyi önemsiz olmayan bir şekilde kullandığında:

S --> a S b    // `S` can be itself "parenthesized" by `a` and `b` on both sides.
S -->          // or it could be (ultimately) empty, which ends recursion.

o zaman bunun düzenli ifade ile yapılamayacağını kolayca görebilirsiniz, çünkü bunu hiçbir şekilde tek bir EBNF üretiminde çözemezsiniz; Ssüresiz olarak ikame edersiniz , bu da her iki tarafa da her zaman başka bir as ve bs ekler . Lexers (daha spesifik olarak: lexers tarafından kullanılan Sonlu Durum Otomataları) rastgele sayıya (sonlu, hatırladınız mı?) Sayamaz, bu yüzden kaç tane as ile eşit olarak eşleşecekleri kaç tane olduğunu bilmezler b. Bunun gibi gramerlere bağlamsız gramerler denir (en azından) ve ayrıştırıcıya ihtiyaç duyarlar.

Bağlamdan bağımsız gramerlerin ayrıştırılması iyi bilinmektedir, bu nedenle programlama dillerinin sözdizimini tanımlamak için yaygın olarak kullanılırlar. Ama dahası da var. Bazen daha genel bir dilbilgisi gerekir - aynı anda, bağımsız olarak sayılacak daha fazla şeyiniz olduğunda. Örneğin, bir kişinin yuvarlak parantezleri ve kare parantezleri aralıklı olarak kullanabileceği bir dil tanımlamak istediğinizde, ancak birbirleriyle doğru bir şekilde eşleştirilmeleri gerekir (parantezli parantez, yuvarlak yuvarlak). Bu tür gramer içeriğe duyarlı olarak adlandırılır . Solda (oktan önce) birden fazla sembolü olmasıyla bunu tanıyabilirsiniz. Örneğin:

A R B --> A S B

Soldaki bu ek sembolleri kuralı uygulamak için bir "bağlam" olarak düşünebilirsiniz. Bazı ön şartlar var olabilir, vb Hedefşartlar Örneğin, yukarıda kural yerine başkalarını Riçine S, ancak aradaki var sadece Ave Bbu bırakarak Ave Bdeğişmeden kendilerini. Bu tür bir sözdiziminin ayrıştırılması gerçekten zordur, çünkü tam gelişmiş bir Turing makinesine ihtiyaç duyar. Bu tamamen başka bir hikaye, bu yüzden burada bitireceğim.


1
EBNF'nin "standart Chomsky'nin Normal Form (CNF) dilbilgisi kurallarına göre sadece bir kolaylık / kısayol gösterimi /" sözdizimsel şeker "olduğunu belirtiyorsunuz. Ancak CNF'nin eldeki konuyla hiçbir ilgisi yok. EBNF kolayca standart BNF'ye dönüştürülebilir. Dönemi. Standart BNF için sözdizimsel şekerdir.
babou

11

Soruyu sorulduğu gibi cevaplamak için (diğer cevaplarda görünenleri gereksiz yere tekrar etmeden)

Lexers ve ayrıştırıcılar, kabul edilen yanıtın önerdiği gibi çok farklı değildir. Her ikisi de basit dil biçimciliğine dayanmaktadır: sözlükler için normal diller ve neredeyse her zaman ayrıştırıcılar için bağlamsız (CF) diller. Her ikisi de oldukça basit hesaplama modelleri, sonlu durum otomatı ve aşağı itme yığını otomatı ile ilişkilidir. Düzenli diller, bağlamsız diller için özel bir durumdur, böylece sözlükler biraz daha karmaşık CF teknolojisi ile üretilebilir. Ancak en az iki nedenden dolayı iyi bir fikir değildir .

Programlamadaki temel nokta, bir sistem bileşeninin en uygun teknolojiyle donatılmasıdır, böylece üretilmesi, anlaşılması ve bakımı kolaydır. Teknoloji aşırıya kaçmamalı (gerekenden çok daha karmaşık ve maliyetli teknikler kullanarak) veya gücünün sınırında olmamalı, böylece istenen hedefe ulaşmak için teknik eğilmeler gerektirmemelidir.

Bu yüzden "Düzenli ifadelerden nefret etmek moda görünüyor". Çok şey yapabilseler de, bazen uygulamada çeşitli uzantıların ve kısıtlamaların teorik sadeliklerini bir şekilde azalttığı gerçeğinden bahsetmemek için, bunu elde etmek için çok okunamayan kodlamaya ihtiyaç duyuyorlar. Lexers genellikle bunu yapmaz ve genellikle jetonu ayrıştırmak için basit, verimli ve uygun bir teknolojidir. Jeton için CF ayrıştırıcılarını kullanmak aşırı olabilir, ancak mümkün.

Sözlükçüler için CF formalizmini kullanmamanın bir başka nedeni de, tam CF gücünü kullanmanın cazip gelmesidir. Ancak bu, programların okunmasıyla ilgili önemli sorunları doğurabilir.

Temel olarak, anlamın çıkarıldığı program metninin yapısının çoğu bir ağaç yapısıdır. Ayrıştırma cümlesinin (program) sözdizimi kurallarından nasıl üretildiğini ifade eder. Anlambilim, ayrıştırma ağacını oluşturmak için sözdizimi kurallarının oluşturulma biçiminden kompozisyon teknikleri (matematiksel yönelimli homomorfizm) tarafından türetilir. Bu nedenle ağaç yapısı esastır. Jetonların düzenli bir set tabanlı lexer ile tanımlanması gerçeği durumu değiştirmez, çünkü normalden oluşan CF hala CF verir (Normal dönüştürücüler hakkında çok gevşek konuşuyorum, bir karakter akışını bir token akışına dönüştürüyor).

Bununla birlikte, CF ile oluşturulan CF (CF dönüştürücüler aracılığıyla ... matematik için üzgünüm), mutlaka CF vermez ve işleri daha genel, ancak pratikte daha az izlenebilir hale getirebilir. Bu yüzden CF, kullanılabilmesine rağmen, sözlükler için uygun bir araç değildir.

Düzenli ve CF arasındaki en büyük farklardan biri, normal dillerin (ve dönüştürücülerin) hemen hemen her biçimciliği çeşitli şekillerde çok iyi oluşturması, CF dillerinin (ve dönüştürücülerin) kendileriyle bile (birkaç istisna dışında) olmamasıdır.

(Normal dönüştürücülerin bazı sözdizimi hata işleme tekniklerinin resmileştirilmesi gibi başka kullanımları olabileceğini unutmayın.)

BNF, CF gramerlerini sunmak için sadece belirli bir sözdizimidir.

EBNF, BNF gramerlerinin ters versiyonunu vermek için düzenli gösterim olanaklarını kullanan BNF için sözdizimsel bir şekerdir . Her zaman eşdeğer bir saf BNF'ye dönüştürülebilir.

Bununla birlikte, düzenli gösterim EBNF'de genellikle sözdiziminin sözcüksel öğelerin yapısına karşılık gelen bu kısımlarını vurgulamak için kullanılır ve geri kalanı düz BNF'de sunulurken, lexer ile tanınmalıdır. Ancak bu mutlak bir kural değildir.

Özetlemek gerekirse, tokenin daha basit yapısı normal dillerin daha basit teknolojisi ile daha iyi analiz edilirken, dilin (program sözdiziminin) ağaç yönelimli yapısı CF gramerleri tarafından daha iyi ele alınmaktadır.

AHR'nin cevabına da bakmanızı öneririm .

Ama bu bir soruyu açık bırakıyor: Neden ağaçlar?

Ağaçlar sözdizimini belirtmek için iyi bir temel oluşturur çünkü

  • metne basit bir yapı kazandırırlar

  • anlambilimi bu yapıya dayalı olarak metinle, yukarıda belirtildiği gibi, matematiksel olarak iyi anlaşılmış bir teknoloji (homomorfizmalar yoluyla kompozisyon) ile ilişkilendirmek için çok uygundur. Matematiksel formalizmlerin anlambilimini tanımlamak için temel bir cebirsel araçtır.

Bu nedenle, Özet Sözdizimi Ağaçlarının (AST) başarısı ile gösterildiği gibi iyi bir ara gösterimdir. AST'nin ayrıştırma ağacından genellikle farklı olduğunu unutmayın, çünkü birçok profesyonel tarafından kullanılan ayrıştırma teknolojisi (LL veya LR gibi) yalnızca CF gramer alt kümesine uygulanır, böylece daha sonra AST'de düzeltilecek olan gramer bozulmalarını zorlar. Bu, herhangi bir CF dilbilgisini kabul eden daha genel ayrıştırma teknolojisi (dinamik programlamaya dayalı) ile önlenebilir.

Programlama dillerinin CF yerine bağlama duyarlı (CS) olduğu gerçeğine ilişkin ifade keyfi ve tartışmalıdır.

Sorun, sözdizimi ve anlambilimin ayrılmasının keyfi olmasıdır. Bildirimleri veya tür anlaşmasını denetleme sözdiziminin bir parçası veya anlambilimin bir parçası olarak görülebilir. Aynı şey doğal dillerde cinsiyet ve sayı anlaşması için de geçerlidir. Fakat çoğul anlaşmanın kelimelerin gerçek anlamsal anlamına bağlı olduğu doğal diller vardır, böylece sözdizimine iyi uymaz.

Anlamsal anlambilimde programlama dillerinin birçok tanımı, anlambilimde bildirimler ve tür denetimi yerleştirir. Ira Baxter'in yaptığı gibi , CF ayrıştırıcılarının sözdiziminin gerektirdiği bir bağlam duyarlılığı elde etmek için saldırıya uğradığını belirtmek, en iyi ihtimalle durumun keyfi bir görüşüdür. Bazı derleyicilerde bir hack olarak organize edilebilir, ancak olması gerekmez.

Ayrıca, sadece CS ayrıştırıcılarının (burada diğer cevaplarda kullanılan anlamda) oluşturulması zor ve daha az verimli değildir. Ayrıca, ihtiyaç duyulabilecek bağlam duyarlılığı kinf'ini açıkça ifade etmek için yetersizdirler. Ve doğal olarak, programın anlambilimini türetmek, yani derlenmiş kodu üretmek için uygun bir sözdizimsel yapı (ayrıştırma ağaçları gibi) üretmezler.


Evet, ayrıştırma ağaçları ve AST'ler farklıdır, ancak aslında gerçekten yararlı değildir.
Ira Baxter

@IraBaxter Sizinle aynı fikirde değilim, ancak gönderinize temiz bir cevap hazırlamak için gerçekten zamanım yok. Temel olarak, pragmatik bir bakış açısı alıyorsunuz (ve ayrıca kendi sisteminizi de savunuyorsunuz). Bu daha da kolaydır, çünkü bazı sistemlerde olduğu gibi deterministik olanlardan ziyade genel CF ayrıştırıcıları kullanırsınız (ancak GLR en verimli olmayabilir). AST'yi resmen tanımlanmış tedaviye, muhtemelen doğru dönüşümlere, matematiksel kanıtlara, birden fazla somut temsile ayrılmaya vb. Borç veren referans temsil olarak görüyorum
babou

"Pragmatik" görüş, yararlı bir şekilde çok farklı olmadıklarını iddia etmemin sebebidir. Ve sadece (ad hoc AST) kullanmanın size "makul olarak doğru dönüşümler" verdiğine inanmıyorum; ad hoc AST'nizin işlenmekte olan dilin gerçek dilbilgisi ile belirgin bir ilişkisi yoktur (ve burada, evet, benim sistemim "AST" nin BNF'ye göre isomorfik bir eşdeğer olması nedeniyle savunulabilir). Geçici Varış yerini- zi do not GLR (değil en verimli) için Sen itiraz oldukça anlamsız görünüyor) size birden fazla beton temsiller" için unparse için herhangi bir ek yeteneği vermek Ne de nondeterministic vardır...
Ira Baxter

Aslında benim yorumuma itirazınızın hiçbir kısmını anlamıyorum. O "temiz cevabı" yazmanız gerekecek.
Ira Baxter

@IraBaxter Yorumlar doğru bir cevap için çok kısıtlanmıştır (öneri?). "Ad hoc", AST I savunucusu için uygun bir niteleyici değildir ve referans sözdizimi olmalıdır (bazen). Bu tarihsel olarak doğrudur, hem bilgisayar bilimindeki AST kavramının tarihine, hem de yorumlama ile birlikte sıralanmış bir cebirde terimler (ağaçlar) olarak biçimsel sistemler tarihine bakar. AST referans formdur, türetilmiş bir form değildir. Ayrıca bkz. Modern prova sistemleri ve otomatik program oluşturma. Başkaları tarafından tasarlanan somut bir sözdiziminden çalışmak zorunda olduğunuz gerçeğine karşı taraf olabilirsiniz.
babou

7

Bir derleyicinin analiz bölümünün normalde sözcüksel analiz ve ayrıştırma (sözdizimi analizi) aşamalarına ayrılmasının birkaç nedeni vardır.

  1. Tasarımın sadeliği en önemli husustur. Sözcüksel ve sözdizimsel analizlerin ayrılması çoğu zaman bu görevlerden en az birini basitleştirmemize izin verir. Örneğin, sözdizimsel birimler olarak yorumlarla ve boşlukla uğraşmak zorunda olan bir ayrıştırıcı olurdu. Yorum ve beyaz boşluğu varsayabilecek birinden çok daha karmaşık, sözlüksel analizör tarafından zaten kaldırılmıştır. Yeni bir dil tasarlıyorsak, sözcüksel ve sözdizimsel kaygıları ayırmak daha temiz bir genel dil tasarımına yol açabilir.
  2. Derleyici verimliliği artırıldı. Ayrı bir sözlük analizcisi, ayrıştırma işini değil, sadece sözcüksel görevi yerine getiren özel teknikleri uygulamamızı sağlar. Ayrıca, girdi karakterlerini okumak için özel tamponlama teknikleri derleyiciyi önemli ölçüde hızlandırabilir.
  3. Derleyici taşınabilirliği artırıldı. Girdi aygıta özgü özellikler sözlük çözümleyicisiyle sınırlandırılabilir.

resource___ Derleyiciler (2. Baskı) - Alfred V. Abo Columbia Üniversitesi Monica S. Lam Stanford Üniversitesi Ravi Sethi Avaya Jeffrey D. Ullman Stanford Üniversitesi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.