Düzenli ifadeler bir programlama dili midir?


27

Akademik anlamda, düzenli ifadeler bir programlama dili olarak nitelendirilebilir mi?

Merakımın motivasyonu, "X'in regex'i yapabilir mi?" Diye sorduğum, henüz baktığım bir SO sorusu. ve bana bunları kullanarak olası çözümler hakkında genel anlamda ne söylenebilir diye merak etti.

Temel olarak soruyorum, "düzenli ifadeler Turing tamamlandı" mı?


9
Peki, temel olarak, "Turing tamamlandı" ifadelerinin normal ifadeleri mi?
SinirliFormsDesigner ile

Birisi ek olarak ayrıntılı olsaydı iyi olurdu, ama evet
Aaron Anodide 21.02.2012

4
"Tamamen normal ifadeler vardır", dil türlerinin ve taklit hiyerarşinin

5
(Bir düzenlemeden 1 dakika sonra) ve bu soru ve açıklama yolunu bulmak istiyorsanız, cs teorisi değişimine bakmak isteyebilirsiniz . Pompalama lemma için en basit çürütmek olduğunu "düzenli dil eşleşebilir bir ^ nb ^ n" (Turing makinesi tarafından matchable olan).

1
Sanırım özgeçmişine "Programlama dilleri" bölümü altında yazıp yazamayacağını soruyor. Bu durumda cevap hayır. Bu "Teknolojiler" bölümüne giriyor.
Neil

Yanıtlar:


46

Düzenli İfadeler, biçimsel dil teorisinde dizeleri ve "Düzenli Dil" olarak bilinen diğer metinsel bilgileri ayrıştırmak için kullanılan belirli bir biçimsel dilbilgisi türüdür . Onlar böyle bir programlama dili değil. Bunlar, kodlama için bir kestirme yoldan daha fazladır, aksi halde uygulamak bazen son derece can sıkıcı görünümlü Regex'ten daha kafa karıştırıcı olabilir.

Programlama Dilleri tipik olarak Turing Complete olan diller olarak tanımlanır . Bu diller, herhangi bir hesaplanabilir işlevi işleyebilmelidir . Regex bu kategoriye uymuyor.

Regex'e benzeyen bir dil istiyorsanız, J'yi deneyin.


1
+1, baktım ama düzenli ifadelerin eksiksizliğini Turing'in iyi bir tartışması / etkisiz hale getiremedik.
SinirliFormsDesigner ile

1
@ davidk01 - Hücresel otomatlar tamamlanmış olabilir (iyi derleyiciler bulmak zor olsa da), normal ifadeler değildir. Önemsiz olmayan hesaplamalar yapabilirsiniz, evet, fakat yapamayacağınız oldukça önemsiz şeyler var. Tüm hücresel otomatları çevirmek bir programlama dili olarak düşünülebilir, çünkü prensipte onlarla başka bir dilde yazabileceğiniz herhangi bir programı yazabilirsiniz.
psr

1
Aynı zamanda, asallık testini yapan regex'in ( montreal.pm.org/tech/neil_kandalgaonkar.shtml#primality_regex ) akademik anlamda "normal İfadeler" den daha güçlü olan perl regex özelliklerini (yani, saklı gruplar) kullandığını not etmek önemlidir. . Normal diller isteğe bağlı bellek gerektiremez.
Eric W.

5
@WorldEngineer: Turing tamamlanmayan ilginç ve kullanışlı programlama dilleri var. Datalog, SQL ve ACL2 akla gelen birkaç örnektir, ayrıca tip teorisi temelli teoremlerin kanıtladığı gibi herhangi bir miktarda normalize edici lambda hesabı da vardır.
Ryan Culpepper,

1
Tüm programlama dilleri tamamlanmış değil. Örneğin, bir tercümanla eşleştirilmeden tam olarak tamamlanmayan XML gibi yalnızca bağlam içermeyen bildirimsel diller, programlama dilleri olarak kabul edilebilir. Hepsi sizin 'programlama dili' tanımınıza bağlıdır. 'Düzenli' bir dili 'bağlamsız' bir dile dönüştürmek için tek ihtiyacınız olan bir aşağı açılır yığın. O zaman tamamen su kaplumbağaları.
Evan Plaice

14

Tartışmaya katılanların X ve Y'nin farklı tanımlarını kullanmaları durumunda " X ve Y " tipindeki soruları cevaplamak zordur . Bazı tanımlar için cevap "evet", bazı tanımlar için cevap "hayır" olabilir. Özellikle cevap , farklı tanımların farklılık gösterdiği teknik ayrıntılara bağlıysa . Ayrıca bu tartışma bazı yanlış bilgiler içeriyor, lütfen daha uzun cevapları olan bir sabrınız olsun.

Bir " programlama dili " ile ne kastediyoruz ?

Basit bir cevap "programlar oluşturmak için kullanılan bir dil" olabilir. Elbette, fakat: ne tür programlar? Bazı program türlerini oluşturmak için kullanılabilecek , başka program türlerini kullanamayan bir dilden ne haber ? Aşırı olayları göstermek için iki özel örnek:

1) M adında hayali bir dil şöyle çalışır: Eğer program "m" tek harfini içeriyorsa, Mayın Tarlası oyununu yaratır. Geriye kalan her şey bir sözdizimi hatasıdır.

Sezgisel olarak, "programlama dili" derken demek istediğimiz bu değil . Ancak M'nin pazarlama departmanı , tanımı tanımlamak için teknik olarak yerine getirdiğini iddia edebilir , çünkü bir program oluşturmak için kullanılabilir. Elbette, derleyici sizin için bazı kritik parçalar yapar, fakat derleyiciler bunu yapar, değil mi? C dilinin bir derleyicisi aynı zamanda bazı basit kelimeleri düzinelerce işlemci talimatına çevirir. M derleyicisi daha da ileri gidiyor ve işinizi daha da kolaylaştırıyor.

2) Ünlü Turbo Pascal'ın orjinal versiyonunu kurarsanız, birçok çeşit program yazabilirsiniz. Ancak web tarayıcısında çalışan bir oyun yazamazsınız, çünkü gerekli API orada değildir.

Peki, Turbo Pascal'ı bir programlama dili yapan şey tam olarak nedir, ama M'de yok mu? Basitçe konuşursak, Pascal'da M'den daha fazlasını yapabilirsiniz . Ancak bir web tarayıcısında çalışan bir Mayın Tarlası oyununu oluşturan bir M.NET'in olduğunu hayal edin. Şimdi Pascal'ın yapabileceği ve M.NET'in yapamayacağı bir şeye sahibiz, ancak M.NET'in yapabileceği ve Pascal'ın yapabileceği bir şeye sahibiz. Neden Pascal'ın avantajlarını ve M.NET'in avantajlarını alakasız görelim?

Cevap, Pascal'a her türlü algoritmayı yazabilmenizdir , ancak M veya M.NET'te algoritmalar yazamazsınız. Elbette, M "m" komutunu, C ise "strcmp" komutunu derler. Fakat "strcmp" yi daha geniş bir bağlamda koyabilirsiniz, örneğin iki dosyayı satır satır karşılaştırabilir veya bin dizgiyi okuyabilir ve bunları alfabetik olarak sıralayabilirsiniz, ya da ... milyonlarca başka şey. Ve kesin olarak, verilen komutları bir programlama dilinin özünü oluşturan herhangi bir algoritmada kullanma yeteneğidir .

Tam olarak bir algoritma nedir ve daha da önemlisi “herhangi bir algoritma” nedir? Bilgisayar biliminde Turing-complete sözcüklerini kullanıyoruz . Buradaki fikir, her birinin hepsini simüle edebilecek bir dizi bilgisayar dili olduğudur . Bu dillerden biri Turing makinesidir, bu yüzden buna böyle denir. Pascal var, C var, Java var, Python var, Lisp var, Smalltalk var, hatta XSLT var. Bizim varsayımsal M ve M.NET orada değil . İyi bir bilgisayar bilimi kursu veren herhangi bir üniversitede bu konuda daha fazla bilgi edinebilirsiniz, ancak fikir Turing-tamamlanmış bir dilin her şeyi yapabileceğidir.gerekli minimum API'yi verirseniz, başka bir Turing-complete dilinin yapabildiğini (Bazı web tarayıcı API'lerini Pascal'a verirseniz, web tarayıcısında her türlü oyunu oluşturabilirsiniz. Web tarayıcı API'sini M'ye verirseniz, yine de yalnızca Mayın Tarlası'nı oluşturabilirsiniz.) Mecazi olarak Tüm API'leri bir programlama dilinden kaldırırsanız önemli olan kalır.

" Normal ifadeler " ile ne kastediyoruz ?

Farklı programlama dilleri bunları biraz farklı şekilde uygular. Ancak asıl fikir, düzenli ifadelerin normal diller olarak ifade edilmesiydi . Buradaki programlama dilleri hakkında değil, (sözde) insan dilleri hakkında konuştuğumuzu unutmayın. Sadece "ba", "baba", "bababa" sözcüklerinden oluşan bir dili konuşan egzotik bir kabile bulduğunuzu hayal edin. Bu dili sözlü olarak "bir veya daha fazla defa tekrarlanan heceli" ba "olarak ya da normal bir ifadeyi" (ba) + "olarak kullanarak tanımlayabilirsiniz.

Düzenli ifadelerin şunu ifade etmesi gerekir: "hiçbir şey", "bu mektup", "bunu, ardından", "bunu veya", "bunu, bir veya daha fazla kez tekrarlandı" ve "bunu değil". - Matematiksel tanım budur. Başka bir şey sadece önceki bileşenlerden yapılmış uygun bir kısayol. Örneğin, "bu, iki ya da üç kez tekrarlanan", "bu, ardından gelen, ardından (bu ya da hiçbir şey)" olarak çevrilebilir, ancak "ba {2,3}" yazmayı "baba" dan daha uygun (ba)?".

Gerçek hayatta, "normal ifadelerin" tipik bir uygulaması bundan daha fazlasını sağlar. Örneğin, matematiksel bir tanımını, bir "aba", "aabaa", "aaabaaa" dil ve benzeri kullanılarak - ardından "a" ların herhangi bir sayıda, bir "b", ardından aynı A" sayısına "s - normal bir dil değil . Bununla birlikte, günümüzde kullanılan birçok "normal ifade", "daha önce bulduğumuzla aynı" ek konseptini kullanarak, "(a +) b \ 1" olarak yazılmıştır. Bu ek kavramı kullanarak bazı harika şeyler yapabiliriz, örneğin asal harflerden oluşan sözcükleri tespit edebiliriz . Yine de, herhangi bir algoritma yapamıyoruz ... bir açıklama için neden,

Öyleyse, asıl konuya geri dönersek: düzenli ifadeler (ya: Chomsky hiyerarşisindeki normal dilleri tanımlayan ifadeler; ya da: eski, artı \ 1 işlemi olarak tanımlanır) bir programlama dili mi (turing-complete) Cevap hayır . Hayır, uygulayamaz herhangi algoritma düzenli ifadeler kullanarak ve uygulama yeteneği herhangi bir algoritma Bilgisayar okuyan insanlar genellikle dil programlama özü olarak anlaşılması şeydir.

Elbette, herkes farklı bir tanım üzerinde ısrar ederek cevabı değiştirebilir . Başlangıçta yazdığım gibi, teknik detaylar burada önemlidir. Onları yanlış anlarsan, yanlış bir cevap alırsın.

Eğer Ve eğer değil teknik detaylar ilgilenen, cevap olabilir: Eğer düzenli ifadeler (ve başka bir şey) bir program yapmak için kullanabilir miyim? Hayır. Peki neden ona programlama dili diyorsunuz? (Bununla birlikte, bunun gibi bir cevap burada indirildi ve silindi, bu yüzden bu daha uzun sürümü yazdım.)

EDIT: Ayrıca, herkes bazı yeni özelliklerle birlikte kendi "normal ifadeler" varyantını uygulayan bir kütüphane oluşturabilir. Bir anda, yeni özellikler tüm sistemin Turing-eksiksiz olması için yeterli olabilir . Önemsiz bir örnek, bazı yeni sözdizimleri kullanarak bir Turing-tamamlanmış dili gömmek olabilir; ama aynı zamanda daha az açık bir şekilde gerçekleşebilir. Belki zaten oldu.


0

Net'te, Regex yalnızca farklı dönüşüm ve görünüm kombinasyonlarını kullanarak birden fazla koşul formunu işlemekle kalmaz, aynı zamanda kendi yığınını da yönetebilir.

(?xm)
    (?>
        <(?<Tagname>table)[^>]*>
    )
(?(Tagname)
    (
        </(?(?!\k'Tagname')(?<-Tagname>))*\k'Tagname'>(?<-Tagname>)
    |
        (?>
            <(?<Tagname>[a-z][^\s>]*)[^>]*>
        )
    |
        [^<]+
    )+?
    (?(Tagname)(?!))
)

Bu, örneğin, bir HTML Tablosu almak için yazdığım küçük bir snippet. Diğer regex motorlarından farklı olarak, bu, yakalama koleksiyonlarının yığınını (push, peek ve pop) kontrol eder ve iç içe geçmiş nesneleri işleyebilir. Daha karmaşık bir tane var, ancak bu tescilli bir ürün.

Bu örnekte Regex'in bir programlama dilinin tüm temel gereksinimlerine sahip olduğunu söyleyebilirim. Değişkenleri, satır içi belleği, koşullu değerleri, giriş ve çıkışı vardır, çoklu regex derleme motorlarından birini kullanarak derler (. Bu durumda. Net).

Aşırı kullanılmış squawking'in (ASLA) Regex ile Ayrıştırma HTML yanıtına yanıt olarak, devam ettim ve gönderebileceğim önceden yazılmış bir yanıt gönderdim: Ayrıştırma HTML

Anoter örneği (sadece bir gösteri) aşağıdaki gibidir:

Function Regex("<(td>)((?:[^<]*(?(?!</\1)<))*)</\1")
    Group(0) = "<"
    Group(1) = "td>"
    Group(0) += Group(1)
    Group(2) = LoopMethod()
    Group(0) += Group(2)
    Group(0) += "</" & Group(1)
    Return Group()
End Function

Function LoopMethod()
    retGroup = ""
    Do
        tmpGroup = Everything that is NOT an Opening HTML Delimeter
        If the Text following tmpGroup Does NOT Equal "</" & Group(1) Then
            tmpGroup += "<"
            retGroup += tmpGroup
        Else
            Exit Do
        End If
    Loop
    Return retGroup
End Function

Yine, HTML papağanları için: HTML'nin ayrıştırılması

Bu, döngüleri ve koşullamaları gerçekleştiren daha basit bir regex gösterir (algoritmalar?). Eksik olan tek şey gerçek matematiksel hesaplama. Bu, bir TD Hücresini tipik "(. *?)" Yönteminden daha verimli çeken daha ayrıntılı bir Düzenli İfadedir.

Fakat bir Regex meraklısı ve ilan edilmiş bir usta olarak bile, hiç kimseye Regex'in bir Programlama dili olduğunu söyleyemem. Kendime karşı olan savım, tek başına duramayacağı, başka bir programlama dili motoru tarafından desteklenirken kendi motoruyla çalıştırılması gerektiğidir.


Bunu "test" ederseniz ve çalışmazsa, çoğu regex motorunun "test cihazlarının" .Net Regex'in (Dengeleme Grupları) işlenmediğini anlamalısınız. Bunu bir .NET programında kullanmak zorundaydın.
Suamere

3
Aman Tanrım, bu html'yi ayrıştırmak için neden asla regex kullanmamanız gerektiğine dair prima facia kanıtı . Hiç.
Saat

@Tacroy HTML’nin regex ile ayrıştırılmasıyla ilgili tavsiyelerde bulunan birisini görmek güzel. Kalbi zayıf olmasa da, yukarıdaki gibi regex'leri yığınla birleştirmek, bağlamsız bir çözümleyici oluşturmak için temel (ve verimli) bir reçetedir.
Evan Plaice

1
Papağan Squawking'e cevaben. Bunu ben yarattım: HTML Ayrıştırma
Suamere

Bağlama duyarlı dilleri kabul ediyorsa, Normal İfade değildir. Regex'in süperseti olan başka bir DSL. Satıcı adı bunu değiştirmez
Caleth

0

Normal ifadedeki bir bul / değiştir, Turing-complete bir programlama dili olmasa da, önceki yanıtlarda açıklandığı gibi, düzenli ifadelerle değiştirmenin tekrarlanan eylemlerini kullanmanıza izin verirseniz, normal ifadeyi kullanarak herhangi bir Turing makinesini kodlayabilirsiniz:

Tekrarlanan bulma / Düzenli ifadelerle değiştirme, Turing-komple bir Programlama Dilidir.

Sonuç olarak, aynı aramayı kullanarak herhangi bir hesaplanabilir işlevi hesaplayabilir ve javascript düzenli ifadesini tekrar tekrar değiştirebilirsiniz.

Turingin tamamlandığını ispatlamak için, bir Turing makinesini düzenli ifade arama / değiştirme olarak kodlamak yeterlidir. Editörün durumunun şöyle olduğunu varsayalım:

0000#12345:01-5:0#0000000

üzerinde bir okuyucu bulunan bir semboller bandı olarak okunabilir:

[left symbols]#[set of states]:[set of symbols]-[current state]:[current symbol]#[right symbols]

Durum 5'de 0 okumak, 1 yazmak ve durumunu 3 olarak değiştirmek ve sola hareket etmek için, aşağıdaki gösterimi kullanarak soyutlarız:

5:0 => 1, 3:[left]

Önceki notasyonu bir arama düzenli ifadesinde kodladık:

(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#

ve onun yerine geçen ifade (javascript benzeri)

#12345:01-$4:$1#$8

Tamam, şimdi nasıl birçok kural kodlanır? Düzenli ifade araması için oroperatörle |birleştirmeyi kullanıyoruz ve sonuçları değiştirilen, numaralandırılmış grup numaralarında ofsetlerle birleştiriyoruz. Örneğin, dört kural kümesini düşünelim.

5:0 => 1, 3:left
3:0 => 1, 5:right
5:1 => 1, 5:right
3:1 => 1: 3:stop

Onları bir aramada kodlar ve ifadeyi değiştiririz:

Search:
(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#

Replace by:
$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8

Favori javascript motorunuzda deneyin:

function turingstep(s) {
  return s.replace(/(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#/g,"$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8");
}

var tape = "0000#12345:01-5:0#0000000"
for(var i = 0; i < 6; i++) {
  console.log(tape)
  tape = turingstep(tape)
}
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.