my $explanation = $exp{$type} . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::macro::explanation {
my $self = shift;
my $type = $self->text;
my $explanation = $exp{$type} . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::oct::explanation {
my $self = shift;
my $n = oct($self->{TEXT});
my $explanation = "character $n" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::hex::explanation {
my $self = shift;
my $n = hex($self->{TEXT});
my $explanation = "character $n" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::utf8hex::explanation {
my $self = shift;
my $n = hex($self->{TEXT});
my $explanation = "UTF character $n" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::ctrl::explanation {
my $self = shift;
my $c = $self->{TEXT};
my $explanation = "^$c" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::named::explanation {
my $self = shift;
my $c = $self->{TEXT};
my $explanation = "the character named '$c'" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::Cchar::explanation {
my $self = shift;
my $c = $self->{TEXT};
my $explanation = "one byte (a C character)" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::slash::explanation {
my $self = shift;
my $explanation =
($trans{$self->text} || "'$self->{TEXT}'") .
$self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::any::explanation {
my $self = shift;
my $type = '.';
$type .= 's' if $modes{on} =~ /s/;
my $explanation = $exp{$type} . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::text::explanation {
my $self = shift;
my $text = $self->text;
$text =~ s/\n/\\n/g;
$text =~ s/\r/\\r/g;
$text =~ s/\t/\\t/g;
$text =~ s/\f/\\f/g;
$text =~ s/'/\\'/g;
my $explanation = "'$text'" . $self->extra_info;
my $string = $self->string;
if ($using_rex) {
$string =~ s/\n/\\n/g;
$string =~ s/\r/\\r/g;
$string =~ s/\t/\\t/g;
$string =~ s/\f/\\f/g;
$string =~ s/([ #])/\\$1/g;
}
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::alt::explanation {
my $self = shift;
my $explanation = $exp{'|'};
my $string = $self->string;
my $oldfmt = $format;
$format =~ s/ (\^<+)/$1 /g;
$format =~ s/ #/# / if $using_rex;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
$format = $oldfmt;
}
sub YAPE::Regex::Explain::backref::explanation {
my $self = shift;
my $explanation =
"what was matched by capture \\$self->{TEXT}" . $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my ($c1, $name, $pP, $utf8, $neg, $posix) = ($1,$2,$3,$4,$5,$6);
if ($name) {
$explanation .= qq{the character named "$name"};
}
elsif ($utf8) {
$utf8 =~ tr/{}//d;
(my $nice = $utf8) =~ s/^Is//;
my $add =
($pP eq 'P' and "anything but ") .
($macros{lc $nice} || "UTF macro '$utf8'");
$add =~ s/\\([wds])/\\\U$1/ if $pP eq 'P';
$explanation .= $add;
}
elsif ($posix) {
my $add = ($neg and "anything but ") . $macros{lc $posix};
$add =~ s/\\([wds])/\\\U$1/ if $neg;
$explanation .= $add;
}
else {
$explanation .= (
$trans{$c1} ||
($c1 =~ /\\[wWdDsS]/ and $exp{$c1}) ||
"'$c1'"
);
}
if (!$utf8 and !$posix and $c1 !~ /\\[wWdDsS]/ and $class =~ s/^-$cc_REx//) {
my ($c2, $name, $pP, $utf8, $neg, $posix) = ($1,$2,$3,$4,$5,$6);
$class = "-$c2", next if $utf8 or $posix or $c2 =~ /\\[wWdDsS]/;
if ($name) {
$explanation .= qq{ to the character named "$name"};
}
else {
$explanation .= ' to ' . ($trans{$c2} || "'$c2'");
}
}
$explanation .= ', ';
}
substr($explanation,-2) = $self->extra_info;
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::comment::explanation { }
sub YAPE::Regex::Explain::whitespace::explanation { }
sub YAPE::Regex::Explain::flags::explanation {
my $self = shift;
if ($using_rex) {
$self->{ON} .= 'x' if $self->{ON} !~ /x/;
$self->{OFF} =~ s/x//;
}
my $string = $self->string;
my $explanation =
'set flags for this block' .
$self->handle_flags;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::code::explanation {
my $self = shift;
my $string = $self->string;
my $explanation = 'run this block of Perl code';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::later::explanation {
my $self = shift;
my $string = $self->string;
my $explanation = 'run this block of Perl code (that isn\'t interpolated until RIGHT NOW)';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::group::explanation {
my $self = shift;
if ($using_rex) {
$self->{ON} .= 'x' if $self->{ON} !~ /x/;
$self->{OFF} =~ s/x//;
}
my $explanation =
'group, but do not capture' .
$self->handle_flags .
$self->extra_info .
":";
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my %old = %modes;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{CONTENT} };
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation = 'end of grouping';
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::capture::explanation {
my $self = shift;
my $explanation =
'group and capture to \\' .
++$br .
$self->extra_info .
":";
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my %old = %modes;
my $old_br = $br;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{CONTENT} };
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation = "end of \\$old_br";
$explanation .= << "END" if $self->quant;
(NOTE: because you're using a quantifier on this capture, only the LAST
repetition of the captured pattern will be stored in \\$old_br)
END
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::cut::explanation {
my $self = shift;
my $explanation =
'match (and do not backtrack afterwards)' .
$self->extra_info .
":";
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my %old = %modes;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{CONTENT} };
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation = 'end of look-ahead';
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::lookahead::explanation {
my $self = shift;
if (not @{ $self->{CONTENT} }) {
my $explanation =
($self->{POS} ? 'succeed' : 'fail') .
$self->extra_info;
my $string = $self->fullstring;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
return;
}
my $explanation =
'look ahead to see if there is' .
($self->{POS} ? '' : ' not') .
$self->extra_info .
":";
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my %old = %modes;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{CONTENT} };
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation = 'end of look-ahead';
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::lookbehind::explanation {
my $self = shift;
my $explanation =
'look behind to see if there is' .
($self->{POS} ? '' : ' not') .
$self->extra_info .
":";
my $string = $self->string;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
my %old = %modes;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{CONTENT} };
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation = 'end of look-behind';
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
sub YAPE::Regex::Explain::conditional::explanation {
my $self = shift;
my ($string,$explanation);
if (ref $self->{CONTENT}) {
$string = '(?';
$explanation =
'if the following assertion is true' .
$self->extra_info .
":";
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$self->{CONTENT}[0]->explanation;
$format =~ s/ (\^<+)/$1 /g;
$format =~ s/ #/# / if $using_rex;
$explanation = 'then:';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
my %old = %modes;
my $oldfmt = $format;
$format =~ s/\^<<(<+)/ ^$1/g;
$format =~ s/# / #/ if $using_rex;
$_->explanation for @{ $self->{TRUE} };
unless (@{ $self->{TRUE} }) {
my $string = "";
my $explanation = 'succeed';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
{
my $oldfmt = $format;
$format =~ s/ (\^<+)/$1 /g;
$format =~ s/ #/# / if $using_rex;
my $string = "|";
my $explanation = 'else:';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
$format = $oldfmt;
}
$_->explanation for @{ $self->{FALSE} };
if (not @{ $self->{FALSE} }) {
my $string = "";
my $explanation = 'succeed';
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) }
$^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
$format = $oldfmt;
$string = ')' . $self->quant;
$explanation =
"end of conditional" .
(ref $self->{CONTENT} ? '' : " on \\$self->{CONTENT}");
%modes = %old;
if ($using_rex ne 'silent') { formline($format, $string, $explanation) while length($string . $explanation) } else { formline($format, $string) while length($string) } $^A .= ($using_rex ? '' : '-' x 70) . "\n";
}
1;
__END__
=head1 NAME
YAPE::Regex::Explain - explanation of a regular expression
=head1 SYNOPSIS
use YAPE::Regex::Explain;
my $exp = YAPE::Regex::Explain->new($REx)->explain;
=head1 C<YAPE> MODULES
The C<YAPE> hierarchy of modules is an attempt at a unified means of parsing
and extracting content. It attempts to maintain a generic interface, to
promote simplicity and reusability. The API is powerful, yet simple. The
modules do tokenization (which can be intercepted) and build trees, so that
extraction of specific nodes is doable.
=head1 DESCRIPTION
This module merely sub-classes C<YAPE::Regex>, and produces a rather verbose
explanation of a regex, suitable for demonstration and tutorial purposes.
Perl 5.6 regex structures like C<\p{...}> and C<\P{...}> and C<[:...:]> are