2014-11-24 12 views
5

Marpa'da yeni bir DSL uyguluyorum ve (Regexp :: Grammars'dan geliyor) memnun kaldım. Dilim, bir grup ikili ve ikili operatörü, C stili tanımlayıcıları olan nesneleri ve tanıdık nokta gösterimini kullanan yöntem çağrılarını desteklemektedir. Örneğin:Marpa: Anahtar kelimeleri tanımlayıcı olarak açıkça reddedebilir miyim?

foo.has(bar == 42 AND baz == 23)

Ben Marpa en dilbilgisi tanımlama dili ile sunulan prioritized rules özelliğini bulundu ve bu çok güvenmek gelmiş, bu yüzden neredeyse tek G1 kural Expression var. Alıntı (kısaca geçilmiştir birçok alternatifleri ve semantik eylemler): Gördüğünüz gibi, ben Scanless arabirimini (SLIF) kullanıyorum

Expression ::= 
     NumLiteral 
    | '(' Expression ')'    assoc => group 
    || Expression ('.') Identifier 
    || Expression ('.') Identifier Args 
    | Expression ('==') Expression 
    || Expression ('AND') Expression 

Args  ::= ('(') ArgsList (')') 
ArgsList ::= Expression+    separator => [,] 

Identifier   ~ IdentifierHeadChar IdentifierBody 
IdentifierBody  ~ IdentifierBodyChar* 
IdentifierHeadChar ~ [a-zA-Z_] 
IdentifierBodyChar ~ [a-zA-Z0-9_] 

NumLiteral ~ [0-9]+ 

. Benim sorunum bu da örneğin, ayrıştırır şudur:

foo.AND(5) 

Marpa sadece bir nokta sonra bir tanımlayıcı olamayacağını bilir, bu yüzden bile AND bir anahtar kelime olabileceği gerçeğini dikkate almaz. AND'u bir anahtar kelime olarak tanımlayan ayrı bir lexing aşaması yaparak bu problemden kaçınabileceğimi biliyorum, ancak bu minik kağıt parçası çabaya değmez.

Identifier kuralını yalnızca anahtar kelime olmayan tanımlayıcılarla kısıtlamak için SLIF'de bir yol var mı?

+0

"Anahtar kelime" ile ne demek istiyorsunuz? “assoc” ve “separator”, Marpa lingo'daki anahtar kelimelerdir. – choroba

+0

@choroba, “AND” operatörünü tanımlarsa, tanımlayıcı olarak izin verilmesini istemez. – ikegami

+0

Bunu test etmedim, ancak 'latm' zarfına bakmak isteyebilirsiniz. Bu, Marpa'nın, bir kelimenin tam anlamıyla bir lütuf olduğunu ve böylece bir 'VE' nin tamam olduğunu düşünecek olan, bu nedenle, bir kelimenin tam anlamıyla "aptal" hale getirilmesiyle ilgili olarak, kelimenin tam olarak ne kabul edilebilir olduğu hakkındaki bilgisini kapatmanızı sağlar. ayrıştırmak, istediğin gibi. Bunu belki de daha yüksek bir sözlük önceliği ile birleştirin, böylece bir operatör olarak 'VE' bir tanımlayıcı olarak 'VE' üzerinden tercih edilir. Kafamın üstünden ama umarım yardımcı olur. –

cevap

2

Dilbilgisinde böyle bir şeyi nasıl ifade edeceğimi bilmiyorum. Gerçi durumunu kontrol hangi Tanımlayıcısı'nın bir ara terminal dışı tanıtabilirsiniz:

#!/usr/bin/perl 
use warnings; 
use strict; 
use Syntax::Construct qw{ // }; 

use Marpa::R2; 

my %reserved = map { $_ => 1 } qw(AND); 

my $grammar = 'Marpa::R2::Scanless::G'->new(
    { bless_package => 'main', 
     source => \(<< '__GRAMMAR__'), 

:default ::= action => store 

:start ::= S 
S ::= Id 
    | Id NumLiteral 
Id ::= Identifier action => allowed 

Identifier   ~ IdentifierHeadChar IdentifierBody 
IdentifierBody  ~ IdentifierBodyChar* 
IdentifierHeadChar ~ [a-zA-Z_] 
IdentifierBodyChar ~ [a-zA-Z0-9_] 

NumLiteral ~ [0-9]+ 

:discard ~ whitespace 
whitespace ~ [\s]+ 

__GRAMMAR__ 
    }); 

for my $value ('ABC', 'ABC 42', 'AND 1') { 
    my $value = $grammar->parse(\$value, 'main'); 
    print $$value, "\n"; 
} 


sub store { 
    my (undef, $id, $arg) = @_; 
    $arg //= 'null'; 
    return "$id $arg"; 
} 

sub allowed { 
    my (undef, $id) = @_; 
    die "Reserved keyword $id" if $reserved{$id}; 
    return $id 
} 
+0

oops, doh! [kendi kendini imha edecek] – ikegami

+0

'priority' ve' latm' lexeme zarflarının çeşitli permütasyonlarını denedim, ancak bu benim ünite testimi yeşil yapan tek şeydi. Hata mesajları güzel olmayabilir, ancak en azından dilbilgisini doğru olarak kabul eder. –

+0

@StefanMajewsky: Bir "olumsuz kural" sahip olmak güzel olurdu. İlginç bir soru için teşekkürler. – choroba

3

Sadece şey bu tür yönelik sözlükbirim öncelikleri kullanabilirsiniz, örnek Marpa :: R2 test paketi here olduğunu.

Temel olarak, <AND keyword> ~ 'AND' sözlüğünü bildirir ve Identifier üzerinden tercih edilmesini sağlar. Bu hile yapmalı.

P.S. Bir örnek vermek için yukarıdaki betiği biraz değiştirdim - code, output.

+1

Dilbilgisini 'S :: = Id Call ile genişletirseniz; Çağrı :: = '. Id '(' ')' ve sonra bir test örneği ekleyin ABC.AND() '_exactly_ istenmeyen davranışını kabul ettiğini göreceksiniz. Ben de, bu olayı önlemek için arıyorum! Herhangi bir fikir? İşlemler, formuna göre bir jetonu reddetmek için kullanılabilir mi? –

+0

Eylemler kullanılabilir, ancak bu çok verimli değildir - giriş okunduğunda değerlendirme aşamasında eylemler denir. Olaylar daha iyi, bu özü gör - https://gist.github.com/rns/d19b40ffc5523659dec9 - 'VE' tanımlayıcısı girdide karşılandıktan sonra reddedilir. – rns

+0

Ahh güzel. Şimdi eylemler ve olaylar arasındaki farkı daha net görüyorum. Olaylar, zorunlu boşlukları test etmek için iyi bir yer gibi görünüyor. Gördüğüm bir soru, açık bir cevap olmadan birkaç kez soruldu mu? Örneğin, dilbilginiz bir sayı listesi için izin veriyorsa, '4' ile '-' arasındaki '12' arasındaki '12' arasındaki uyarıyı bildirmek “güzel” olur. '$ r-> literal ($ lexeme_start + $ lexeme_length, 1);' tanınan simgeden sonraki sonraki karakter mi? Ayrıca "düşmek" sonunun ele alınması gerekiyor ... –

İlgili konular