Yinelemeli iniş ayrıştırıcı - Recursive descent parser - Wikipedia

İçinde bilgisayar Bilimi, bir yinelemeli iniş ayrıştırıcı bir çeşit yukarıdan aşağı ayrıştırıcı bir dizi karşılıklı yinelemeli prosedürler (veya yinelemeli olmayan eşdeğer) prosedür birini uygular terminal olmayanlar of dilbilgisi. Bu nedenle ortaya çıkan programın yapısı, tanıdığı dilbilgisinin yapısını yakından yansıtır.[1]

Bir tahmine dayalı ayrıştırıcı gerektirmeyen özyinelemeli bir iniş ayrıştırıcısıdır geri izleme.[2] Tahmine dayalı ayrıştırma yalnızca şu sınıf için mümkündür: LL (k) olan gramerler bağlamdan bağımsız gramerler bunun için bir pozitif tamsayı var k bu, özyinelemeli bir iniş ayrıştırıcısının yalnızca bir sonrakini inceleyerek hangi üretimin kullanılacağına karar vermesini sağlar. k girdi belirteçleri. LL (k) gramerler bu nedenle hepsini dışlar belirsiz gramerler yanı sıra içeren tüm gramerler sol özyineleme. Bağlamdan bağımsız herhangi bir gramer, sol özyinelemeye sahip olmayan eşdeğer bir gramere dönüştürülebilir, ancak sol özyinelemenin kaldırılması her zaman bir LL (LL) vermez (k) dilbilgisi. Tahmine dayalı bir ayrıştırıcı çalışır doğrusal zaman.

Geri izleme ile yinelemeli iniş, hangisinin olduğunu belirleyen bir tekniktir. üretim her bir üretimi sırayla deneyerek kullanmak. Geri izleme ile yinelemeli iniş LL ile sınırlı değildir (k) dilbilgisi, ancak dilbilgisi LL olmadığı sürece sona erdirilmesi garanti edilmez (k). Sonlandırıldıklarında bile, geri izleme ile özyinelemeli iniş kullanan ayrıştırıcılar gerekli olabilir üstel zaman.

Tahmine dayalı ayrıştırıcılar yaygın olarak kullanılmasına ve sıklıkla elle ayrıştırıcı yazılırsa seçilmesine rağmen, programcılar genellikle bir tablo tabanlı ayrıştırıcı kullanmayı tercih eder. ayrıştırıcı oluşturucu[kaynak belirtilmeli ]LL için (k) dil veya alternatif bir ayrıştırıcı kullanarak, örneğin LALR veya LR. Bu, özellikle bir dilbilgisi yoksa LL (k) form, dilbilgisinin tahmini ayrıştırma için uygun hale getirilmesi için LL'ye dönüştürülmesi söz konusudur. Tahmine dayalı ayrıştırıcılar, aşağıdaki gibi araçlar kullanılarak otomatik olarak oluşturulabilir: ANTLR.

Öngörülü ayrıştırıcılar, başlangıç ​​ve son durumlar arasındaki kenarların üretim kuralının sağ tarafındaki sembollerle (terminaller ve terminal olmayanlar) etiketlendiği her bir terminal olmayan sembol için geçiş diyagramları kullanılarak gösterilebilir.[3]

Örnek ayrıştırıcı

Aşağıdaki EBNF -sevmek dilbilgisi (için Niklaus Wirth 's PL / 0 programlama dili Algoritmalar + Veri Yapıları = Programlar ) içinde LL (1) form:

 program = blok "." .  blok =     ["sabit" kimlik "=" num {"," kimlik "=" num} ";"]     ["var" kimlik {"," kimlik} ";"]     {"prosedür" kimlik ";" blok ";"} Beyan .  Beyan =     kimlik ":=" ifade     | "telefon etmek" kimlik     | "başla" Beyan {";" Beyan } "son"     | "Eğer" şart "sonra" Beyan     | "süre" şart "yapmak" Beyan .  şart =     "garip" ifade     | ifade ("="|"#"|"<"|"<="|">"|">=") ifade .  ifade = ["+"|"-"] dönem {("+"|"-") dönem} .  dönem = faktör {("*"|"/") faktör} .  faktör =     kimlik     | numara     | "(" ifade ")" .

Terminaller tırnak içinde ifade edilir. Her biri terminal olmayan dilbilgisinde bir kuralla tanımlanır, hariç kimlik ve numaraörtük olarak tanımlandığı varsayılır.

C uygulaması

Aşağıda, yukarıdaki dil için özyinelemeli iniş ayrıştırıcısının bir uygulaması yer almaktadır. C. Ayrıştırıcı kaynak kodunu okur ve kod ayrıştırılamazsa bir hata mesajıyla çıkar, kod doğru ayrıştırılırsa sessizce çıkar.

Aşağıdaki öngörücü ayrıştırıcının yukarıdaki dilbilgisini ne kadar yakından yansıttığına dikkat edin. Dilbilgisindeki her terminal dışı için bir prosedür vardır. Ayrıştırma, son nonterminal işlenene kadar yukarıdan aşağıya doğru iner. Program parçası genel bir değişkene bağlıdır, sym, girişten mevcut sembolü ve işlevi içeren Nextsymhangi güncellemeler sym arandığında.

Fonksiyonların uygulamaları Nextsym ve hata basit olması için ihmal edilmiştir.

typedef Sıralama {kimlik, numara, Lparen, Rparen, zamanlar, yırtmaç, artı,    eksi, eql, neq, lss, leq, gtr, geq, Aramalarım, başlarım, noktalı virgül,    en sonunda, ifsym, whilesym, olur, thensym, dosym, Constsym, virgül,    Varsym, procsym, dönem, olasılık} Sembol;Sembol sym;geçersiz Nextsym(geçersiz);geçersiz hata(sabit kömür msg[]);int kabul etmek(Sembol s) {    Eğer (sym == s) {        Nextsym();        dönüş 1;    }    dönüş 0;}int beklemek(Sembol s) {    Eğer (kabul etmek(s))        dönüş 1;    hata("beklemek: beklenmeyen sembol");    dönüş 0;}geçersiz faktör(geçersiz) {    Eğer (kabul etmek(kimlik)) {        ;    } Başka Eğer (kabul etmek(numara)) {        ;    } Başka Eğer (kabul etmek(Lparen)) {        ifade();        beklemek(Rparen);    } Başka {        hata("faktör: sözdizimi hatası");        Nextsym();    }}geçersiz dönem(geçersiz) {    faktör();    süre (sym == zamanlar || sym == yırtmaç) {        Nextsym();        faktör();    }}geçersiz ifade(geçersiz) {    Eğer (sym == artı || sym == eksi)        Nextsym();    dönem();    süre (sym == artı || sym == eksi) {        Nextsym();        dönem();    }}geçersiz şart(geçersiz) {    Eğer (kabul etmek(olasılık)) {        ifade();    } Başka {        ifade();        Eğer (sym == eql || sym == neq || sym == lss || sym == leq || sym == gtr || sym == geq) {            Nextsym();            ifade();        } Başka {            hata("durum: geçersiz operatör");            Nextsym();        }    }}geçersiz Beyan(geçersiz) {    Eğer (kabul etmek(kimlik)) {        beklemek(olur);        ifade();    } Başka Eğer (kabul etmek(Aramalarım)) {        beklemek(kimlik);    } Başka Eğer (kabul etmek(başlarım)) {        yapmak {            Beyan();        } süre (kabul etmek(noktalı virgül));        beklemek(en sonunda);    } Başka Eğer (kabul etmek(ifsym)) {        şart();        beklemek(thensym);        Beyan();    } Başka Eğer (kabul etmek(whilesym)) {        şart();        beklemek(dosym);        Beyan();    } Başka {        hata("ifade: sözdizimi hatası");        Nextsym();    }}geçersiz blok(geçersiz) {    Eğer (kabul etmek(Constsym)) {        yapmak {            beklemek(kimlik);            beklemek(eql);            beklemek(numara);        } süre (kabul etmek(virgül));        beklemek(noktalı virgül);    }    Eğer (kabul etmek(Varsym)) {        yapmak {            beklemek(kimlik);        } süre (kabul etmek(virgül));        beklemek(noktalı virgül);    }    süre (kabul etmek(procsym)) {        beklemek(kimlik);        beklemek(noktalı virgül);        blok();        beklemek(noktalı virgül);    }    Beyan();}geçersiz program(geçersiz) {    Nextsym();    blok();    beklemek(dönem);}

Örnekler

Bazı özyinelemeli iniş ayrıştırıcı üreteçleri:

Ayrıca bakınız

Referanslar

  1. ^ Burge, W.H. (1975). Yinelemeli Programlama Teknikleri. ISBN  0-201-14450-6.
  2. ^ Watson, Des (22 Mart 2017). Derleyici Yapısına Pratik Bir Yaklaşım. Springer. ISBN  978-3-319-52789-5.
  3. ^ Aho, Alfred V.; Sethi, Ravi; Ullman, Jeffrey (1986). Derleyiciler: İlkeler, Teknikler ve Araçlar (ilk baskı). Addison Wesley. s.183.

Genel referanslar

  • Derleyiciler: İlkeler, Teknikler ve Araçlar, ilk baskı, Alfred V Aho, Ravi Sethi ve Jeffrey D Ullman, özellikle Bölüm 4.4.
  • Java'da Modern Derleyici Uygulaması, İkinci SürümAndrew Appel, 2002, ISBN  0-521-82060-X.
  • Yinelemeli Programlama Teknikleri, W.H. Burge, 1975, ISBN  0-201-14450-6
  • C ile Derleyici Oluşturma, Charles N Fischer ve Richard J LeBlanc, Jr, 1991, ISBN  0-8053-2166-7.
  • C # ve Java ile DerlemePat Terry, 2005, ISBN  0-321-26360-X, 624
  • Algoritmalar + Veri Yapıları = ProgramlarNiklaus Wirth, 1975, ISBN  0-13-022418-9
  • Derleyici İnşaatıNiklaus Wirth, 1996, ISBN  0-201-40353-6

Dış bağlantılar