On Wed, Mar 02, 2005 at 12:42:08PM -0600, Rod Adams wrote: : Larry Wall wrote: : : >On Tue, Mar 01, 2005 at 11:06:17PM -0600, Rod Adams wrote: : >: Since the line between rules and subs is already blurring significantly, : >: I want to blur it a little more. I want to write rules which can take : >: parameters. : > : >No problem. That's how the arguments to rules like <before foo> are : >already passed. : > : Excellent! : : >Of course, one can call them like ordinary methods too, as long as one : >supplies an appropriate pattern-matching context invocant. But it's : >pretty handy to have that magically supplied for you inside <...>. : > : > : : Now for the tricky part. : : rule baltag (Str $tag, Str $body is rw) { : \< $tag .*? \> : $<body> := (.*?) : \</ $tag \> : }
Well, that would be written: rule baltag (Str $tag, Str $body is rw) { \< $tag .*? \> $body := (.*?) \</ $tag \> } since $body is a real variable rather than a hash entry. However, I don't think binding works even in an ordinary sub--rebinding the variable would break its association with whatever actual parameter. You'd need to use assignment: rule baltag (Str $tag, Str $body is rw) { \< $tag .*? \> (.*?) \</ $tag \> { let $body = $1 } } : $buffer ~~ / <baltag title $<body>> .* \> <$body> \< /; That'd have to be something like: $buffer ~~ / <baltag(/title/,$<body>)> .* \> <$body> \< /; But in theory it should autovivify the $<body> for you based on the "is rw". : In other words, I want to pass a possibly unbound hypothetical into a : subrule, and let the subrule bind/rebind it. Can only assign it. You'd have to pass the actual symbol table holding $<body> if you want to rebind the name. You could presumably pass in $/ as an argument and hash it explicitly. : Alternatively would be a syntax for calling the subrule, and then : binding a hypothetical to one of the hypotheticals returned in the : subrule. I'm moderately sure S05 made this possible, but I couldn't put : all the pieces together. I'll hazard the following guess: : : rule baltag (Str $tag) { : \< $tag .*? \> : $<body> := (.*?) : \</ $tag \> : } : : $buffer ~~ / $<btag> := <baltag title> <($<body> := $btag<body>)> /; That's essentially correct, though that should probably be {...} instead of <(...)>, in case the body has the value "0" which would cause the <(...)> assertion to fail. There might also be some circumstances in which you need a "let" in there if there's any possibility of backtracking over the binding but still having access to the match object. : Which seems very clumsy, especially if I wish to call it a lot. Be nicer : if I could push the work onto the subrule. Well, if you never want <baltag> to return the tags, then you can just say something like: rule baltag (Str $tag) { \< $tag .*? \> $0 := (.*?) \</ $tag \> } $buffer ~~ / $<body> := <baltag title> /; But you probably want to know what attributes that first .*? matched too. Larry