|
Abipalve perli regulaaravaldise gurule, oleks vaja perli skriptis teha kindlaks et stringis ei esine ekraneerimata lõpetavat sulgu mis asub ekraneerimata alustava sulu ja stringi lõpu vahel. Midagi sellist oleks ehk pool teed: /(?<!\\)\([^\)]*$/ See avaldis leiab stringist ekraneerimata alustava sulu ja teeb kindlaks et puudub järgnev lõpetav sulg, kuid ei kontrolli et lõpetav sulg oleks ekraneerimata. Kas sellist testi üldse regulaaravaldisega esitada õnnestuks? |
|
Lühidalt öeldes, seda ei saa teha. Detailsemalt öeldes on sulgude asetamine (sarnaselt html tag-dele) tüüp-2 grammatika (Chomsky hierarhias) ja regex (ilma tagasi-viideteta) on tüüp-3 grammatika, ning keerulisemat grammatikat vähem võimsamaga ei saa parsida. Põhimõtteliselt on lihtsam funktsioon kirjutada, mis seda teeb (pseudokoodis midagi sellist):
Sõltub, kas sulgude üksteise sisse panek on lubatud. Kui ei ole, siis on tegemist relgulaarse keelega, mille tuvastamiseks piisab ka regulaaravaldisest. Kui sulge võib üksteise sisse panna, siis on tegu kontekstivaba keelega ja selle kirjeldamiseks on üldjuhul tõesti vaja vähemalt kontekstivaba grammatikat.
(Aug 23 '11 at 15:07)
Ahto Truu ♦♦
Samas on Perli regulaaravaldistes olemas mitmeid laiendusi (näiteks tagasiviited ja rekursiivsed mallid), mille tõttu on nendega võimalik kirjeldada ka mõningaid mitteregulaarseid keeli. Kuna ma olen ise Perli väga vähe kasutanud, ei oska kohe öelda, mis piirides täpselt nende laienduste abil suluavaldisi parsida saab. Põhimõtteliselt on teada, et Perli regulaaravaldiste väljendusvõimsus on rangelt regulaarsete ja kontekstivabade keelte vahel, mis tähendab, et kõiki kontekstivabu keeli nendega siiski parsida ei saa.
(Aug 23 '11 at 15:09)
Ahto Truu ♦♦
On olemas tagasiviited aga nende arv on piiratud ja üldiselt see lõpeb ühe õudsa regexp avaldisega ning tõenäoliselt on see aeglasem kui funktsioon.
(Aug 23 '11 at 15:13)
egon ♦♦
Oh, ma ei püüdnudki väita, et see lahendus funktsioonist parem oleks. Vabandust, kui selline mulje jäi.
(Aug 23 '11 at 20:22)
Ahto Truu ♦♦
|
|
Ehh, eks ta rumal küsimus oli. /(?<!\\)\((?:(?<=\\).|[^\)])*$/ lahendab selle konkreetse probleemi. Eks ole vist ka paremaid lahendusi, aga praeguseks on ka see OK. |
