I was confronted to present a condensed explanation of the use cases and side-effects of matching-regexes in Perl
LHS = ($string =~ /RE(G)EX/MOD)
which depend on:
Wouldn't it be nice to create automatic tests for all cases to create a nice lookup-table/cheat-sheet?
This table would have a worst case of 4 dimensions ( context, result, capture, /g ), which means many possible projections into a 2D table, here an attempt how it might look like, if the result is coded into the cell's value
(NB: this is untested guess work and turned out to be wrong I leave it to you to spot the errors)
+------------+-----------+----------+----------+--------------+ | | SCALAR / VOID | LIST | | m/REGEX/ +-----------+----------+-----------+-------------+ | | | (groups) | | (groups) | +------------+-----------+----------+-----------+-------------+ | / | ->BOOLEAN | ->COUNT | ->BOOLEAN | ->CAPTURES | | /g | ->BOOLEAN | ->COUNT | ->BOOLEAN | ->CAPTURES | +------------+-----------+----------+-----------+-------------+
So in an outbreak of ADHD, hubris, and too much time b/c of Easter holidays I started to write - well hack - test code:
These are my results so far, only as data structures.
Imperfect because I wanna leave the house still during daylight and risks are high that the code will remain unfinished on my disk without being shared. And it even seems to be wrong. The task to condense it into a meaningful table which avoids unnecessary repetitions is even farther away...
use v5.12.0; use warnings; use Data::Dump qw/pp dd/; use Data::Dumper; my $time = '"2$X:1$X:0$X "'; my $str = ""; for my $X (1..3) { $str .= eval($time); } say $str; my ($res,@res) ; my %CTX= ( VOID => { LHS => '' , RES => undef }, SCALAR => { LHS => '$res =', RES => \$res }, LIST => { LHS => '@res =', RES => \@res }, ); my %REGEX = ( "GROUPS_NO" => '2.:1.:0.', "GROUPS_YES" => '(2.):(1.):(0.)' ); my %got; my $ctxt_cnt = 0; for my $ctx (qw/SCALAR LIST VOID/) { for my $groups ( map "GROUPS_$_", qw/YES NO/ ) { for my $mod ("","g") { my $LHS = $CTX{$ctx}{LHS}; my $REGEX = $REGEX{$groups}; my $code = "$LHS ( \$str =~ /$REGEX/$mod );"; eval($code); my $ref = $CTX{$ctx}{RES} ; my $type = ref $ref; my $res = $type eq "SCALAR" ? $$ref : $type eq "ARRAY" ? [ @$ref ] : undef; pp { context => $ctx, code => $code, mod => $mod, result = +> $CTX{$ctx}{RES} }; $got{$ctx}{"MOD_$mod"}{$groups} = $res ; } } $ctxt_cnt++; } $Data::Dumper::Indent=1; $Data::Dumper::Terse =1; say Dumper \%got; #pp \%got;
-->
{ code => "\$res = ( \$str =~ /(2.):(1.):(0.)/ );", context => "SCALAR", mod => "", result => \1, } { code => "\$res = ( \$str =~ /(2.):(1.):(0.)/g );", context => "SCALAR", mod => "g", result => \1, } { code => "\$res = ( \$str =~ /2.:1.:0./ );", context => "SCALAR", mod => "", result => \1, } { code => "\$res = ( \$str =~ /2.:1.:0./g );", context => "SCALAR", mod => "g", result => \1, } { code => "\@res = ( \$str =~ /(2.):(1.):(0.)/ );", context => "LIST", mod => "", result => [21, 11, "01"], } { code => "\@res = ( \$str =~ /(2.):(1.):(0.)/g );", context => "LIST", mod => "g", result => [23, 13, "03"], } { code => "\@res = ( \$str =~ /2.:1.:0./ );", context => "LIST", mod => "", result => [1], } { code => "\@res = ( \$str =~ /2.:1.:0./g );", context => "LIST", mod => "g", result => ["21:11:01", "22:12:02", "23:13:03"], } { code => " ( \$str =~ /(2.):(1.):(0.)/ );", context => "VOID", mod => "", result => undef, } { code => " ( \$str =~ /(2.):(1.):(0.)/g );", context => "VOID", mod => "g", result => undef, } { code => " ( \$str =~ /2.:1.:0./ );", context => "VOID", mod => "", result => undef, } { code => " ( \$str =~ /2.:1.:0./g );", context => "VOID", mod => "g", result => undef, } 21:11:01 22:12:02 23:13:03 { 'LIST' => { 'MOD_' => { 'GROUPS_NO' => [ 1 ], 'GROUPS_YES' => [ '21', '11', '01' ] }, 'MOD_g' => { 'GROUPS_NO' => [ '21:11:01', '22:12:02', '23:13:03' ], 'GROUPS_YES' => [ '23', '13', '03' ] } }, 'SCALAR' => { 'MOD_g' => { 'GROUPS_YES' => 1, 'GROUPS_NO' => 1 }, 'MOD_' => { 'GROUPS_NO' => 1, 'GROUPS_YES' => 1 } }, 'VOID' => { 'MOD_g' => { 'GROUPS_NO' => undef, 'GROUPS_YES' => undef }, 'MOD_' => { 'GROUPS_YES' => undef, 'GROUPS_NO' => undef } } }
DB<36> @res = ( $str =~ /(2.):(1.):(0.)/g ) DB<37> x @res 0 21 1 11 2 01 3 22 4 12 5 02 6 23 7 13 8 03 DB<38>
Hmm, the bug may be related to pos not being properly reset. Must check when back home :)
yeah, that was it, resetting the string is fixing the issue. Next version must monitor the side effects.
Cheers Rolf
(addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
Wikisyntax for the Monastery
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Automatic documentation of match operations?
by haukex (Archbishop) on Apr 10, 2023 at 16:14 UTC | |
by LanX (Saint) on Apr 10, 2023 at 16:43 UTC |