TL; DR regex
nin geri izi. token
yok. Bu yüzden deseniniz uyuşmuyor. Bu cevap bunu açıklamaya ve gramerinizi nasıl düzelteceğinize odaklanıyor. Bununla birlikte, muhtemelen yeniden yazmalı veya mevcut bir ayrıştırıcı kullanmalısınız, bu da raku regexes'i öğrenmek yerine TSV'yi ayrıştırmak istiyorsanız kesinlikle yapmanız gereken şeydir .
Temel bir yanlış anlama?
Bence raku'daki normal ifadelerle ilgili temel bir şeyi yanlış anlıyorum.
("Normal ifadeler" teriminin zaten oldukça belirsiz olduğunu biliyorsanız, bu bölümü atlamayı düşünün.)
Yanlış anlayabileceğiniz temel şeylerden biri "normal ifadeler" sözcüğünün anlamıdır. İşte halkın varsaydığı bazı popüler anlamlar:
Bu anlamların hiçbiri birbiriyle uyumlu değildir.
Perl regex'leri semantik olarak resmi düzenli ifadelerin üst kümesidir, ancak birçok yönden çok daha yararlıdırlar, ancak aynı zamanda patolojik geri izlemeye karşı daha savunmasızdırlar .
Perl Uyumlu Düzenli İfadeler, 1990'ların sonunda orijinal Perl regexes'leriyle aynı oldukları ve Perl'in PCRE motoru dahil takılabilir regex motorlarını desteklediği anlamıyla Perl ile uyumlu olsa da, PCRE regex sözdizimi standartla aynı değildir Perl regex 2020'de Perl tarafından varsayılan olarak kullanılır.
"Normal ifadeler" olarak adlandırılan metin modeli eşleme ifadeleri genellikle birbirine benziyor ve tüm metinleri eşleştiriyor olsa da, sözdiziminde ve hatta aynı sözdiziminin anlamlarında düzinelerce, belki de yüzlerce varyasyon var.
Raku metin deseni eşleştirme ifadelerine genellikle "kurallar" veya "normal ifadeler" denir. "Regexes" teriminin kullanımı, diğer regex'lere benzediği gerçeğini ifade eder (sözdizimi temizlenmesine rağmen). "Kurallar" terimi , ayrıştırmaya (ve ötesine) kadar ölçeklenen çok daha geniş bir özellik ve araç grubunun parçası olduklarını ifade eder .
Hızlı düzeltme
"Regexes" kelimesinin yukarıdaki temel yönü ortadan kalktığında, artık "regex" davranışınızın temel yönüne dönebilirim .
Biz sizin dilbilgisi kalıplarını üçünü geçerseniz token
için Bildiricisi regex
Bildiricisi istediğiniz gibi, sizin dilbilgisi çalışır:
grammar Parser {
regex TOP { <headerRow><valueRow>+ }
regex headerRow { [\s*<header>]+\n }
token header { \S+ }
regex valueRow { [\s*<value>]+\n? }
token value { \S+ }
}
A token
ve a arasındaki tek fark regex
, regex
geriye doğru izlenirken, a'nın token
olmamasıdır. Böylece:
say 'ab' ~~ regex { [ \s* a ]+ b } # 「ab」
say 'ab' ~~ token { [ \s* a ]+ b } # 「ab」
say 'ab' ~~ regex { [ \s* \S ]+ b } # 「ab」
say 'ab' ~~ token { [ \s* \S ]+ b } # Nil
Son paternin işlenmesi sırasında (ki genellikle "regex" olarak adlandırılabilir, ancak gerçek beyanı token
olmayan, değil regex
), önceki satırdaki regex'in işlenmesi sırasında geçici olarak yaptığı gibi \S
yutulur 'b'
. Ancak, kalıp bir olarak bildirildiğinden token
, kural motoru ("normal ifade motoru" olarak da bilinir) geri gitmez , bu nedenle genel eşleşme başarısız olur.
OP'nizde olan bu.
Doğru düzeltme
Genel olarak daha iyi bir çözüm kendinizi vazgeçirmek için varsayarak yavaş ve (program asılı ayırt edilemez) bile felaket yavaş olabilir, çünkü bir karakter yanlışlıkla talihsiz kombinasyonu ile kötü amaçla inşa dize veya birine karşı eşleştirme kullanıldığında, geri izleme davranışı.
Bazen regex
s uygundur. Örneğin, bir kereye mahsus yazarsanız ve regex işi yaparsa, işiniz bitti demektir. Bu iyi. Bu / ... /
, raku'daki sözdiziminin, tıpkı bir geri izleme modeli beyan etmesinin nedeninin bir parçası regex
. (Daha sonra / :r ... /
, cırcırlamayı açmak istiyorsanız tekrar yazabilirsiniz - "cırcır", "geri izlemenin " tersi anlamına gelir, bu nedenle :r
normal ifadeyi token
semantiğe geçirir.)
Bazen geri izleme, ayrıştırma bağlamında hala bir role sahiptir. Örneğin, raku dilbilgisi genellikle geri izlemeden kaçınır ve bunun yerine yüzlerce rule
s ve token
s olsa da, yine de 3 regex
s vardır.
Yararlı olduğu için @ user0721090601 ++ 'ın cevabını iptal ettim. Ayrıca, bana hemen kodunuzda deyimsel olarak kapalı görünen bazı şeylere de hitap eder ve daha da önemlisi, token
s'ye yapışır . Tercih ettiğiniz cevap iyi olabilir, ki bu harika olacaktır.
Nil
. Geri bildirim gittikçe kısır, değil mi? Hata ayıklama için, henüz yapmadıysanız virgül indirin ve / veya Gramerlerdeki hata bildirimi nasıl geliştirilebilir? Konusuna bakın. .Nil
Çünkü deseniniz geri izleme anlambilimi aldınız . Bu konudaki cevabımı gör. Geri takip etmenizi tavsiye ederim. @ User0721090601'in bu konudaki cevabına bakınız. Saf pratiklik ve hız için JJ'nin cevabına bakın. Ayrıca, "Raku ile X'i ayrıştırmak istiyorum. Birisi yardımcı olabilir mi?" .