I've simplified a more complicated pattern I'm trying to match down to the following program:
my token paren { '(' <tok> ')' }
my token tok { <paren>? foo }
say "(foo)foo" ~~ /<tok>/;
This seems straightforward enough to me, but I get this error:
No such method 'tok' for invocant of type 'Match'. Did you mean 'to'?
in regex paren at a.p6 line 1
in regex tok at a.p6 line 2
in block <unit> at a.p6 line 4
What's the reason for this error?
The pattern matches without error if I change the first <tok>
to <&tok>
, but then I don't get a capture of that named pattern, which, in my original, more-complicated case, I need.
The problem is that tok
isn't in the current lexical namespace yet, so <tok>
gets compiled as a method call instead.
If you force it to be a lexical call with &
, it works.
my token paren { '(' <&tok> ')' }
my token tok { <paren>? foo }
say "(foo)foo" ~~ /<tok>/;
If <…>
starts with anything other than a letter it doesn't capture.
So to capture it under the name tok
, we add tok=
to the <…>
my token paren { '(' <tok=&tok> ')' }
my token tok { <paren>? foo }
say "(foo)foo" ~~ /<tok>/;
Brad's answer is correct, but I wanted to offer another possible solution: you can recurse within a single regex using the special <~~>
token. Using that, plus a regular named capture, would create the captures you want in the simplified example in your question; here's how that would look:
my token paren { $<tok> = ['(' <~~> ')']? foo }
I'm not sure whether your more complicated case can be as easily re-written to recurse on itself rather than with two mutually recursive tokens. But, when this pattern works, it can simplify the code quite a bit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With