7 unshift @d, "# dummy line to make line 1 index 1 in \@d\n";
10 our $count_i_last_l_ok;
15 if ($i == $i_last_l_ok) {
16 confess $i if $count_i_last_l_ok++ > 50;
18 $count_i_last_l_ok = 0;
22 return unless $i < @d;
24 #print STDERR "L $i\n";
30 confess $i unless l_ok $i;
33 our $perlop_text = <<'END'; # c&p from man perlop
34 left terms and list operators (leftward)
38 right ! ~ \ and unary + and -
43 nonassoc named unary operators
44 nonassoc < > <= >= lt gt le ge
45 nonassoc == != <=> eq ne cmp ~~
52 right = += -= *= etc. goto last next redo dump
54 nonassoc list operators (rightward)
59 **= += *= &= &.= <<= &&=
69 foreach (split /\n/, $perlop_text) {
73 s{^(?: left | right | nonassoc ) \s+}{}x;
74 next if m{^terms and list operators};
75 next if m{^named unary};
76 next if m{^list operators};
80 foreach my $op (split /\s+/) {
81 next unless length $op;
82 next if $op =~ m{^\w+$};
87 $perlop_re = '(?: '.(join ' | ', @ops).' )';
88 $perlop_re = qr{$perlop_re}x;
89 #print STDERR "$perlop_re\n";
94 our ($ifilehead, $ihunkhead, $ichunkstart, $ichunkend);
95 our ($before, $after);
102 if (s{^[\$\@\%]?[_0-9a-zA-Z]+}{}) {
103 push @o, { T => 'ident', L => $& };
104 } elsif (s{^\<\<('?)([A-Z_]+)\1}{}) {
105 my ($q,$d) = ($1,$2);
106 push @o, { T => 'heredoc', Q => $q, Delim => $d };
109 ( (?: (?! $d) .* \n )* )
111 }{ $1 }x or die "missing end of here doc $d\n";
113 } elsif (s{^ (["'])( (?: [^\\'"]
118 my ($q,$v) = ($1,$2);
119 push @o, { T => 'string', Q => $q, V => $v };
120 } elsif (s{^$perlop_re|\;}{}) {
121 push @o, { T => 'op', L => $& };
122 } elsif (s/[[{(]//) {
123 push @o, { T => 'bra', L => $& };
124 } elsif (s/[]})]//) {
125 push @o, { T => 'ket', L => $& };
126 } elsif (s/^( [\$\@\%] )( \{ )//x) {
127 push @o, { T => 'deref', L => $1 },
128 { T => 'bra', L => $2 };
129 } elsif (s/^ [\$\@\%] [^[^{] //x) {
130 push @o, { T => 'specvar', L => $& };
135 die "cannot tokenise \`$&'";
141 sub analyse_chunk_core () {
142 die "plain deletion\n" unless defined $after;
143 die "plain insertion\n" unless defined $before;
144 my @before = semiparse $before;
145 my @after = semiparse $after;
146 print Dumper($ichunkstart, $ichunkend, \@before, \@after);
150 sub analyse_chunk () {
152 eval { analyse_chunk_core(); };
153 return unless length $@;
154 if ($@ =~ m{^missing end of here doc (\S+)\n}) {
165 for ($ifilehead = 0; l_ok $ifilehead; $ifilehead++) {
167 while (l_ok $ifilehead and m{^diff|^index|^---|^\Q+++\E}) { $ifilehead++ }
168 $ihunkhead = $ifilehead;
169 while (l_ok $ihunkhead) {
170 m{^\@\@} or confess "$ihunkhead $_ ?";
171 my $i = $ihunkhead + 1;
173 if (!l_ok $i or m{^ } or m{^\@\@}) {
174 if (defined $ichunkstart) {
176 eval { analyse_chunk(); 1; };
178 print Dumper('REPORT',
179 $ichunkstart, $ichunkend,
183 $ichunkstart = $ichunkend = $before = $after = undef;
188 my $which = $& eq '-' ? \$before : \$after;