next if m{^list operators};
s{ and unary.*}{};
s{ etc\. }{ };
+ s{\?\:}{ ? : };
foreach my $op (split /\s+/) {
next unless length $op;
next if $op =~ m{^\w+$};
my @o;
for (;;) {
s{^\s+}{};
- if (s{^[\$\@\%][_0-9a-zA-Z]+}{}) {
+ if (s{^[\$\@\%]?[_0-9a-zA-Z]+}{}) {
push @o, { T => 'ident', L => $& };
} elsif (s{^\<\<('?)([A-Z_]+)\1}{}) {
my ($q,$d) = ($1,$2);
s{^
( .* \n )
( (?: (?! $d) .* \n )* )
- }{ $1 } or die "missing end of here doc $d\n";
+ $d \n
+ }{ $1 }x or die "missing end of here doc $d\n";
$o[$#o]{V} = $2;
- } elsif (s{^ (["'])( (?: [^\\] | \\ \1 )* )}{}x) {
+ } elsif (s{^ (["'])( (?: [^\\'"]
+ | \\ [^"']
+ | (?! \1 ) [^"]
+ )*
+ \1 )}{}x) {
my ($q,$v) = ($1,$2);
push @o, { T => 'string', Q => $q, V => $v };
- } elsif (s{^$perlop_re}{}) {
+ } elsif (s{^$perlop_re|\;}{}) {
push @o, { T => 'op', L => $& };
} elsif (s/[[{(]//) {
push @o, { T => 'bra', L => $& };
} elsif (s/[]})]//) {
push @o, { T => 'ket', L => $& };
+ } elsif (s/^( [\$\@\%] )( \{ )//x) {
+ push @o, { T => 'deref', L => $1 },
+ { T => 'bra', L => $2 };
+ } elsif (s/^ [\$\@\%] [^[^{] //x) {
+ push @o, { T => 'specvar', L => $& };
} elsif (!length) {
last;
} else {
die "cannot tokenise \`$&'";
}
}
+ return @o;
}
-sub analyse_chunk () {
+sub analyse_chunk_core () {
die "plain deletion\n" unless defined $after;
die "plain insertion\n" unless defined $before;
my @before = semiparse $before;
flush STDOUT;
}
+sub analyse_chunk () {
+ for (;;) {
+ eval { analyse_chunk_core(); };
+ return unless length $@;
+ if ($@ =~ m{^missing end of here doc (\S+)\n}) {
+ # fudge this
+ $before .= "\n$1\n";
+ $after .= "\n$1\n";
+ next;
+ } else {
+ die $@;
+ }
+ }
+}
+
for ($ifilehead = 0; l_ok $ifilehead; $ifilehead++) {
m{^diff} or next;
while (l_ok $ifilehead and m{^diff|^index|^---|^\Q+++\E}) { $ifilehead++ }
$ichunkend = $i;
eval { analyse_chunk(); 1; };
if (length $@) {
- print Dumper($ichunkstart, $ichunkend,
+ print Dumper('REPORT',
+ $ichunkstart, $ichunkend,
$before, $after,
$@);
}