in reply to Re^2: Perl6: Dynamic Grammars
in thread Perl6: Dynamic Grammars

my regex line {
    ^^ :my $s; (\w+) <?{ $s = %sigils{$0} }> \h+ $s (\N*) $s $$
}

.say for "star *foo*\nat @bar\nat @baz@" ~~ m:g/<line>/;

That's HOT! :-D

But how would I rewrite my tests, then — which actually want to operate on the captured value?

This seems clunky and naïve: (Not unlike myself... «grin»)

#!/usr/bin/env perl6 use Test; my %sigils = bang => '!', at => '@', hash => '#', dollar => '$', percent => '%', caret => '^', and => '&', star => '*', zero => '0'; my regex line { ^^ :my $s; (\w+) <?{ $s = %sigils{$0} }> \h+ $s (\N*) $s $$ } is ('bang !one!' ~~ m/<line>/)<line>[1], 'one', 'is bang!one'; is ('zero 0one0' ~~ m/<line>/)<line>[1], 'one', 'is zero0one'; isnt 'bang @one@' ~~ m/<line>/ && $<line>[1], 'one', 'isnt bang@one'; isnt 'BONK !one!' ~~ m/<line>/ && $<line>[1], 'one', 'isnt BONK!one'; nok 'bang @one@' ~~ m/<line>/, 'mismatch fails'; nok 'BONK !one!' ~~ m/<line>/, 'unknown fails';

Replies are listed 'Best First'.
Re^4: Perl6: Dynamic Grammars
by Anonymous Monk on Jun 13, 2016 at 22:58 UTC
    But how would I rewrite my tests, then — which actually want to operate on the captured value?
    This is Perl, so there's more than one way to do it, eg
    my %sigils = bang => '!', at => '@', hash => '#', dollar => '$', percent => '%', caret => '^', and => '&', star => '*', zero => '0'; my regex line { ^^ :my $s; (\w+) <?{ $s = %sigils{$0} }> \h+ $s (\N*) $s $$ { make ~$0 => ~$1 } } sub parse($_) { map *.<line>.made, m:g/<line>/ } say parse "star *foo*\nat @bar\nat @baz@";
    will generate a sequence of pairs with the key being the name of the sigil and the value the enclosed text.
Re^4: Perl6: Dynamic Grammars
by raiph (Deacon) on Jun 12, 2016 at 18:16 UTC
    You can name a capture if you think that's an improvement over numbered captures (see the two lines with comments):

    my regex line { ^^ (\w+) :my $s; <?{ $s = %sigils{$0} }> \h+ $s $<foo>=\N* $s # Note the foo bit here ... $$ } is ('bang !one!' ~~ m/<line>/)<line><foo>, 'one', 'is bang!one'; # +... and here

    Another tweak is to drop one level of hash keys by using a grammar (again, see the two lines with comments):

    grammar g { regex TOP { # drop 'my'; name 'TOP' to simplify .parse call in `is +` test ^^ (\w+) :my $s; <?{ $s = %sigils{$0} }> \h+ $s $<foo>=\N* $s $$ } } is g.parse('bang !one!')<foo>, 'one', 'is bang!one'; # calling +.parse method on grammar defaults to starting with rule (regex) named + 'TOP'

    perl6.party (not mine)