Passing variables to token
or regex
or rule
is fairly straightfoward. For example, the output of
grammar Foo {
token TOP { (.) {} <bar($0)> }
token bar($s) { {say ~$s} .+ }
}
Foo.parse("xyz")
is simply x
. But things get awry when using proto. For example,1 let's make a simple proto to discriminate the rest of the string being alpha or numeric:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
This bombs, claiming that it expected 1 argument but got 2
for bar
. Okay, well in normal methods, we have to specify the args in the proto declaration, so let's just declare that:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar ($s) { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
Now we get the opposite: expected 2 arguments but got 1
. Hm, maybe that means the proto declaration is eating the value and not passing anything along. So I tried just slipping it in:
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar (|) { * }
token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}
Foo.parse("xyz")
Same error here. It claims it expected 2 arguments, but got 1
.2 Somehow the use of proto
is eating up the arguments. Currently, the only solution that I've found uses dynamic variables, which makes me think that there may be some hidden step where the variable isn't being passed from proto to candidate.
grammar Foo {
token TOP { (.) {} <bar($0)> }
proto token bar ($*s) { * }
token bar:sym<a> { {say ~$*s} <alpha>+ }
token bar:sym<1> { {say ~$*s} <digit>+ }
}
Foo.parse("xyz")
But this seems like a not-entirely intuitive step. How would one pass the variable directly in a non-dynamic fashion to a proto such that it is received by the candidate?
[1] Note that all of the above code has been golfed to focus on passing variables. The actual tokens used bear no resemblance to my real code.
[2] I'm starting to wonder too if this is (generally speaking) a LTA error message. While I get that it's based on first arg = invocant, it still feels off. Maybe it should say "Expected invocant and one argument, only received invocant" or somesuch.