A lookbehind assertion, lookahead assertion, and well every other assertion
are zero width.

That means they do not advance the cursor.

So in the case of `<?after '1:'>` it asserts that the previous two
characters are `1:`
If that is a true assertion, then nothing happens.
If it is instead false, it causes the regex to try backtracking if possible.

---

So for  `"1:" ~~ /.<?after '1:'>/`

Initially the `.` will try matching at the beginning of the string. ( It
matches`1` )
Then the `<?after '1:'>` will look to see if it follows `1:`.

It doesn't. Instead it follows `1`.
So it tells the rest of the regex to try again.

So now the `.` will try matching the second character.
It now matches the `:`.

So the cursor is now located after the `:`
So when `<?after '1:'>` looks to see if it follows `1:`.
It does. So nothing happens.

Now the regex tries the rest of the regex after the lookbehind.
There is nothing after it.

So the regex succeeds.

Really that regex is basically the same as

    /    '1'  <(   ':'   )>   /

(The `1` gets thrown out because it is before `<(` )

---

You could think of assertions as matching in the non-existent region
between characters.

It may be more obvious if you use a regular Perl6 code assertion. `<?{ … }>`
(It checks if the result of the expression is Truthy.)

    $str ~~ /
        .
        <?{
            try $/.target.substr($/.pos-2,2) eq '1:'
        }>
    /

That does the exact same thing as `/.<?after '1:'>/`

It checks to see if the current position is after `1:`


On Thu, Aug 22, 2019 at 8:17 PM William Michels via perl6-users <
perl6-us...@perl.org> wrote:

> Hi Sean, From the docs:
> ____
> Lookbehind assertions:
> https://docs.perl6.org/language/regexes#Lookbehind_assertions
>
> "To check that a pattern appears after another pattern, use a
> lookbehind assertion via the after assertion. This has the form:
> <?after pattern>
>
> "Therefore, to search for the string bar immediately preceded by the
> string foo, use the following regexp:
> / <?after foo> bar /
> ____
>
>
> So for a lookbehind assertion , the 'after" comes first and the
> pattern comes second, within the "<>". Also, you didn't give the regex
> a "bar" pattern to key on after the lookbehind assertion (see above),
> so the lookbehind apparently becomes the primary matching sequence.
> Without the "dot" there, you simply append an "x" to the end of "1:"
> (see code below).
>
> However, you added a "dot" ahead of (and outside of) the lookbehind
> assertion. If I'm interpreting the results below correctly, it looks
> as if a literal "1:" is matched in all cases, however placing a "dot"
> before the lookbehind assertion changes the "registration" (overlap)
> between the literal and the replacement sequence, creating a
> single-character overlap. Adding two "dots" before the lookbehind
> assertion creates a two character overlap:
>
> > my $str = '1:';
> 1:
> > $str ~~ s/<?after '1:'>/x/;
> 「」
> > say $str
> 1:x
> > my $str = '1:';
> 1:
> > $str ~~ s/.<?after '1:'>/x/;
> 「:」
> > say $str
> 1x
> > my $str = '1:';
> 1:
> > $str ~~ s/..<?after '1:'>/x/;
> 「1:」
> > say $str
> x
> > say $*VM
> moar (2019.07.1)
> >
>
>
> HTH, Bill.
>
>
>
> On Thu, Aug 22, 2019 at 12:26 PM Sean McAfee <eef...@gmail.com> wrote:
> >
> > This seems like a bug, but I thought I'd ask here before reporting it.
> >
> >     $_ = '1:';
> >     s/.<?after '1:'>/x/;
> >     .say;
> >
> > This prints "1x".  Is that what's supposed to happen somehow?  I would
> have thought that '1:' should only match a literal "1:", leaving nothing
> for the dot to match.
> >
>

Reply via email to