Balanced.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:66k
- # EXTRACT VARIOUSLY DELIMITED TEXT SEQUENCES FROM STRINGS.
- # FOR FULL DOCUMENTATION SEE Balanced.pod
- use 5.005;
- use strict;
- package Text::Balanced;
- use Exporter;
- use SelfLoader;
- use vars qw { $VERSION @ISA %EXPORT_TAGS };
- #use version; $VERSION = qv('2.0.0');
- $VERSION = '2.0.0';
- @ISA = qw ( Exporter );
-
- %EXPORT_TAGS = ( ALL => [ qw(
- &extract_delimited
- &extract_bracketed
- &extract_quotelike
- &extract_codeblock
- &extract_variable
- &extract_tagged
- &extract_multiple
- &gen_delimited_pat
- &gen_extract_tagged
- &delimited_pat
- ) ] );
- Exporter::export_ok_tags('ALL');
- # PROTOTYPES
- sub _match_bracketed($$$$$$);
- sub _match_variable($$);
- sub _match_codeblock($$$$$$$);
- sub _match_quotelike($$$$);
- # HANDLE RETURN VALUES IN VARIOUS CONTEXTS
- sub _failmsg {
- my ($message, $pos) = @_;
- $@ = bless { error=>$message, pos=>$pos }, "Text::Balanced::ErrorMsg";
- }
- sub _fail
- {
- my ($wantarray, $textref, $message, $pos) = @_;
- _failmsg $message, $pos if $message;
- return (undef,$$textref,undef) if $wantarray;
- return undef;
- }
- sub _succeed
- {
- $@ = undef;
- my ($wantarray,$textref) = splice @_, 0, 2;
- my ($extrapos, $extralen) = @_>18 ? splice(@_, -2, 2) : (0,0);
- my ($startlen, $oppos) = @_[5,6];
- my $remainderpos = $_[2];
- if ($wantarray)
- {
- my @res;
- while (my ($from, $len) = splice @_, 0, 2)
- {
- push @res, substr($$textref,$from,$len);
- }
- if ($extralen) { # CORRECT FILLET
- my $extra = substr($res[0], $extrapos-$oppos, $extralen, "n");
- $res[1] = "$extra$res[1]";
- eval { substr($$textref,$remainderpos,0) = $extra;
- substr($$textref,$extrapos,$extralen,"n")} ;
- #REARRANGE HERE DOC AND FILLET IF POSSIBLE
- pos($$textref) = $remainderpos-$extralen+1; # RESET G
- }
- else {
- pos($$textref) = $remainderpos; # RESET G
- }
- return @res;
- }
- else
- {
- my $match = substr($$textref,$_[0],$_[1]);
- substr($match,$extrapos-$_[0]-$startlen,$extralen,"") if $extralen;
- my $extra = $extralen
- ? substr($$textref, $extrapos, $extralen)."n" : "";
- eval {substr($$textref,$_[4],$_[1]+$_[5])=$extra} ; #CHOP OUT PREFIX & MATCH, IF POSSIBLE
- pos($$textref) = $_[4]; # RESET G
- return $match;
- }
- }
- # BUILD A PATTERN MATCHING A SIMPLE DELIMITED STRING
- sub gen_delimited_pat($;$) # ($delimiters;$escapes)
- {
- my ($dels, $escs) = @_;
- return "" unless $dels =~ /S/;
- $escs = '\' unless $escs;
- $escs .= substr($escs,-1) x (length($dels)-length($escs));
- my @pat = ();
- my $i;
- for ($i=0; $i<length $dels; $i++)
- {
- my $del = quotemeta substr($dels,$i,1);
- my $esc = quotemeta substr($escs,$i,1);
- if ($del eq $esc)
- {
- push @pat, "$del(?:[^$del]*(?:(?:$del$del)[^$del]*)*)$del";
- }
- else
- {
- push @pat, "$del(?:[^$esc$del]*(?:$esc.[^$esc$del]*)*)$del";
- }
- }
- my $pat = join '|', @pat;
- return "(?:$pat)";
- }
- *delimited_pat = &gen_delimited_pat;
- # THE EXTRACTION FUNCTIONS
- sub extract_delimited (;$$$$)
- {
- my $textref = defined $_[0] ? $_[0] : $_;
- my $wantarray = wantarray;
- my $del = defined $_[1] ? $_[1] : qq{'"`};
- my $pre = defined $_[2] ? $_[2] : 's*';
- my $esc = defined $_[3] ? $_[3] : qq{\};
- my $pat = gen_delimited_pat($del, $esc);
- my $startpos = pos $$textref || 0;
- return _fail($wantarray, $textref, "Not a delimited pattern", 0)
- unless $$textref =~ m/G($pre)($pat)/gc;
- my $prelen = length($1);
- my $matchpos = $startpos+$prelen;
- my $endpos = pos $$textref;
- return _succeed $wantarray, $textref,
- $matchpos, $endpos-$matchpos, # MATCH
- $endpos, length($$textref)-$endpos, # REMAINDER
- $startpos, $prelen; # PREFIX
- }
- sub extract_bracketed (;$$$)
- {
- my $textref = defined $_[0] ? $_[0] : $_;
- my $ldel = defined $_[1] ? $_[1] : '{([<';
- my $pre = defined $_[2] ? $_[2] : 's*';
- my $wantarray = wantarray;
- my $qdel = "";
- my $quotelike;
- $ldel =~ s/'//g and $qdel .= q{'};
- $ldel =~ s/"//g and $qdel .= q{"};
- $ldel =~ s/`//g and $qdel .= q{`};
- $ldel =~ s/q//g and $quotelike = 1;
- $ldel =~ tr/[](){}<>