Joseph F. Ryan:
# Is that quotemeta necessary? I think that it would cause
# problems since it would backslash inner '<', which would
# prevent inner sequences from expanding.
It expands innermost-to-outermost, so inner sequences that were in the
original will be expanded beforehand. If you're referring to inner
sequences added by the expansion function, I already mentioned that you
can just call the expand function for them manually.
What is an issue is that things can get quotemetaed two or more times:
C:\>perl -e "print quotemeta quotemeta '< >'"
\\\<\\\ \\\>
C:\>perl -e "print quotemeta quotemeta '\< \>'"
\\\\\\\<\\\ \\\\\\\>
The fix:
sub unquotemeta(;$) {
@_=($_) unless @_;
local $_=shift;
s/\\(.)/$1/gs;
return $_;
}
sub default {
warn "Invalid escape sequence used";
return shift;
}
sub expand_escapes {
my($str, $map)=@_;
#We remove all the X<> sequences, inside-out and
# left-to-right
1 while $str =~ s{
(\w) <
(
[^<>\\]*
(?>
\\.
[^<>\\]*
)*
)
>
}
{
quotemeta &{$map->{$1}||\&default}(unquotemeta $2)
}exs;
return unquotemeta($str);
}
MJD: don't use my last solution--it's known bad.
# >I'm also working on a Perl 6 solution for this QOTW. I'll
# let you guys
# >know how it turns out. :^)
# >
#
# Easy :)
#
#
# sub expand_escapes($str,$map) {
# ...
Yeah, but I want it to be all shiny. :^) Here's what I have so far:
grammar EscapeExpander {
has %.map is public;
method new(; %map) {
%.map=%map;
}
method expand(str $text) {
return .string($text){text}
}
sub expand_escapes(str $text, %map) is exported('default') {
return EscapeExpander.new(map => %map).expand($text);
}
rule string {
$0 := ( <normal>* [ <escape> <self> ]? )
}
rule normal {
$0 := \w ::: <-before <lt> > #word chars that don't
start escapes
| <lt> ::: $text := <string> <gt> #free angle brackets
{ let $0 := "<$text>" }
| \\ $0 := . #backslashed
| $0 := . #other normal characters
}
rule escape {
$char := \w <lt> $text := <string> <gt>
{
if(%.map{$char}) {
let $0 := %.map{$char}($text);
}
else {
warn "$char is not a valid escape sequence";
let $0 := $text;
}
}
}
}
The Big Question is whether you can create a grammar object the way I
have here. I haven't been able to divine that from the relevant As/Es,
but I *think* I can.
--Brent Dax <brentdax-a09SyBuiYrA@xxxxxxxxxxxxxxxx>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism
|