Search code examples
regexregex-lookaroundsraku

Regex assertions working only in lookahead and lookbehind fashion


While trying to come up with some examples for solving this issue, I came up with this snippet:

my regex key {^^ <![#-]> \d+ }
say "333" ~~ &key;                         # OUTPUT: «「333」␤»
say "#333" ~~ &key;

say '333$' ~~ m/ \d+ <?[$]>/;              # OUTPUT: «「333」␤»
say '333' ~~ m/ \d+ <?[$]>/;
say '$333' ~~ m/<?[$]> \d+ /;

only the statements indicated return 「333」, which seems to indicate <! > works as lookahead assertion, while <? > works only as zero-width lookbehind. Is that the case? If that's the case, what's the way of creating a positive look-ahead assertion and a negative look-behind?


Solution

  • I think you've just misinterpreted your experiments.

    <? > works only as zero-width lookbehind. Is that the case?

    No. It's a lookahead. Per your own experiments:

    say '333$' ~~ m/ \d+ <?[$]>/;              # OUTPUT: «「333」␤»
    

    The \d+ matches 333.

    The <? > does a zero width assertion. What does it assert? It asserts, positively (? not !) that the next character (so it's a lookahead, like most regex patterns) must be $. The next character is indeed $, so the assertion succeeds. But as it's a zero-width assertion, it doesn't move the matching cursor forward. (That's what the "zero-width" aspect means.)

    Then the overall regex is done, the overall regex succeeds, and the overall regex captures just 333.

    say '333' ~~ m/ \d+ <?[$]>/;
    

    In this instance there is no $ for the positive assertion to match, so the overall match fails.

    say '$333' ~~ m/<?[$]> \d+ /;
    

    As before, the <?[$]> asserts that the next character is a $. It is, so it succeeds. But, because it's a zero-width assertion, it does not advance the cursor.

    The \d+ then fails (because the matching cursor is still pointing at a $).