Wyrażenie regularne Perla vs. wyrażenie regularne Raku, różnice w silniku?

9

Próbuję przekonwertować oparte na wyrażeniach regularnych rozwiązanie problemu plecaka z Perla na raku. Szczegóły dotyczące Perlmonks

Rozwiązanie Perl tworzy to wyrażenie regularne:

(?<P>(?:vvvvvvvvvv)?)
(?<B>(?:vv)?)
(?<Y>(?:vvvv)?)
(?<G>(?:vv)?)
(?<R>(?:v)?)
0
(?=
(?(?{ $1 })wwww|)
(?(?{ $2 })w|)
(?(?{ $3 })wwwwwwwwwwww|)
(?(?{ $4 })ww|)
(?(?{ $5 })w|)
)

co się dopasowuje vvvvvvvvvvvvvvvvvvv0wwwwwwwwwwwwwww. Następnie skrót dopasowania %+zawiera elementy do włożenia do worka.

Moja konwersja raku to:

$<B> = [ [ vv ]? ]
$<P> = [ [ vvvvvvvvvv ]? ]
$<R> = [ [ v ]? ]
$<Y> = [ [ vvvv ]? ]
$<G> = [ [ vv ]? ]
0
<?before
[ { say "B"; say $/<B>; say $0; say $1; $1 } w || { "" } ]
[ { say "P"; say $/<P>; say $0; say $1; $2 } wwww || { "" } ]
[ { say "R"; say $/<R>; say $0; say $1; $3 } w || { "" } ]
[ { say "Y"; say $/<Y>; say $0; say $1; $4 } wwwwwwwwwwww || { "" } ]
[ { say "G"; say $/<G>; say $0; say $1; $5 } ww || { "" } ]

który również pasuje vvvvvvvvvvvvvvvvvvv0wwwwwwwwwwwwwww. Ale obiekt dopasowania $/nie zawiera niczego użytecznego. Ponadto wszystkie moje debugowania saymówią zero, więc w tym momencie wydaje się, że odniesienie wsteczne nie działa?

Oto mój skrypt testowy:

my $max-weight = 15;
my %items      =
    'R' => { w =>  1, v =>  1 },
    'B' => { w =>  1, v =>  2 },
    'G' => { w =>  2, v =>  2 },
    'Y' => { w => 12, v =>  4 },
    'P' => { w =>  4, v => 10 }
;

my $str = 'v' x  %items.map(*.value<v>).sum ~
          '0' ~
          'w' x  $max-weight;

say $str;

my $i = 0;
my $left = my $right = '';

for %items.keys -> $item-name
{
    my $v = 'v' x %items{ $item-name }<v>;
    my $w = 'w' x %items{ $item-name }<w>;

     $left  ~= sprintf( '$<%s> = [ [ %s ]? ] ' ~"\n", $item-name, $v );
     $right ~= sprintf( '[ { say "%s"; say $/<%s>; say $0; say $1; $%d } %s || { "" } ]' ~ "\n", $item-name, $item-name, ++$i, $w );
}
use MONKEY-SEE-NO-EVAL;

my $re = sprintf( '%s0' ~ "\n" ~ '<?before ' ~ "\n" ~ '%s>' ~ "\n", $left, $right );

say $re;
dd $/ if $str ~~ m:g/<$re>/;
Holli
źródło
1
Do Twojej wiadomości, pytania raku są dozwolone w PerlMonks
ikegami

Odpowiedzi:

1

Ta odpowiedź obejmuje tylko to, co dzieje się źle. Nie dotyczy rozwiązania. Nie zgłosiłem odpowiednich błędów. Nie przeszukałem nawet kolejek błędów, aby sprawdzić, czy mogę znaleźć raporty odpowiadające jednemu lub obu tym problemom, które ujawniłem.

my $lex-var;

sub debug { .say for ++$, :$<rex-var>, :$lex-var }

my $regex = / $<rex-var> = (.) { $lex-var = $<rex-var> } <?before . { debug }> / ;

'xx' ~~   $regex;     say $/;
'xx' ~~ / $regex /;   say $/;

wyświetla:

1
rex-var => Nil
lex-var => x
x
 rex-var => x
2
rex-var => Nil
lex-var => x
x

Koncentrując się najpierw na pierwszym wywołaniu debug(linii zaczynających się 1i kończących na rex-var => 「x」), widzimy, że:

  • Coś poszło nie tak podczas połączenia z debug: $<rex-var>jest zgłaszane jako mające wartość Nil.

  • Gdy dopasowanie wyrażenia regularnego zostanie zakończone i wrócimy do głównej linii, say $/raportuje pełny i poprawnie wypełniony wynik, który zawiera rex-varnazwane dopasowanie.

Aby dowiedzieć się, co poszło nie tak, prosimy o przeczytanie dużej części mojej odpowiedzi na inne SO pytanie . Możesz bezpiecznie pominąć Korzystanie~ . Przypisy 1,2 i 6 są również prawdopodobnie zupełnie nieistotne w twoim scenariuszu.

W przypadku drugiego dopasowania widzimy, że nie tylko jest $<rex-var>zgłaszany jako będący w Niltrakcie debugpołączenia, ale zmienna końcowego dopasowania, zgłoszona z powrotem w linii głównej wraz z drugim say $/, również nie rex-varpasuje. A jedyną różnicą jest to, że regex $regexjest wywoływana z wewnątrz zewnętrznej regex.

raiph
źródło