File Coverage

blib/lib/SpeL/Parser/Auxiliary.pm
Criterion Covered Total %
statement 75 94 79.7
branch 12 18 66.6
condition n/a
subroutine 10 14 71.4
pod 5 5 100.0
total 102 131 77.8


line stmt bran cond sub pod time code
1             # -*- cperl -*-
2             # ABSTRACT: Aux file parser
3              
4              
5 39     39   2141 use strict;
  39         82  
  39         1400  
6 39     39   172 use warnings;
  39         67  
  39         2106  
7             package SpeL::Parser::Auxiliary;
8              
9 39     39   224 use parent 'Exporter';
  39         65  
  39         347  
10 39     39   2638 use Carp;
  39         70  
  39         3062  
11              
12 39     39   18959 use IO::File;
  39         294719  
  39         5228  
13 39     39   351 use File::Basename;
  39         202  
  39         4072  
14              
15             our $grammar = do {
16 39     39   54666 use Regexp::Grammars;
  39         1218191  
  39         359  
17             qr{
18             #
19              
20             <[line]>+
21              
22            
23              
24             ( | | | <.otherwise> ) \n
25              
26             \\ newlabel \{ <[args=Arg]>{5} \}
27              
28             \\ bibcite
29              
30             \\ \@ input
31              
32             [^\n]*
33              
34             \{ \}
35             |
36            
37             \{ \}
38              
39             ([^\{\}]*)
40              
41             \\ endinput
42              
43             }xms
44             };
45              
46             # to debug:
47             #
48             #
49              
50              
51             sub new {
52 40     40 1 423825 my $class = shift;
53              
54 40         105 my $self = {};
55 40 50       155 $class = (ref $class ? ref $class : $class );
56 40         114 bless $self, $class;
57              
58 40         406 $self->{lines} = [];
59 40         160 $self->{lineinfo} = [];
60 40         204 return $self;
61             }
62              
63              
64             sub parseAuxFile {
65 4     4 1 2270 my $self = shift;
66 4         14 my ( $filename ) = @_;
67              
68 4         43 my $file = IO::File->new();
69 4 50       237 $file->open( "<$filename" )
70             or croak( "Error: canot open aux file '$filename' for reading\n" );
71 4         6652 @{$self->{lines}} = <$file>;
  4         72  
72              
73             # setup lineposition bookkeeping
74 4         17 my $firstlineindex = 0;
75 4         25 @{$self->{lineinfo}} =
76 296         429 map{ my $retval = $firstlineindex;
77 296         415 $firstlineindex += length( $_ );
78 296         507 $retval
79 4         12 } @{$self->{lines}};
  4         17  
80 4         13 push @{$self->{lineinfo}}, $self->{lineinfo}->[-1] + 1;
  4         25  
81              
82             # parse
83 4         9 my $contents = join( '', @{$self->{lines}} ) . '\endinput';
  4         99  
84              
85 4         12 my $result;
86 4 50       267 if ( $result = ( $contents ) =~ $SpeL::Parser::Auxiliary::grammar ) {
87 4         66 $self->{tree} = \%/;
88             }
89             else {
90 0         0 $![0] =~ /^(.*)__(\d+),(\d+)__(.*)$/;
91 0         0 $![0] = $1 . $self->_errloc( $3 ) . $4;
92 0         0 die( "Error: failed to parse $filename\n" .
93             "=> " . join( "\n ", @! ) . "\n" );
94             }
95 4         471 delete $self->{lines};
96 4         160 delete $self->{lineinfo};
97              
98             # say STDERR Data::Dumper->Dump( [ $self ] , [ qw (doc) ] );
99             }
100              
101              
102              
103             sub parseAuxString {
104 0     0 1 0 my $self = shift;
105 0         0 my ( $string ) = @_;
106              
107 0         0 $string .= "\n\\endinput";
108              
109 0         0 my $result;
110 0 0       0 if ( $result = ( $string ) =~ $SpeL::Parser::Auxiliary::grammar ) {
111 0         0 return \%/;
112             }
113             else {
114 0         0 $![0] =~ /^(.*)__(\d+),(\d+)__(.*)$/;
115 0         0 $![0] = $1 . $self->_errloc( $3 ) . $4;
116 0         0 die( "Error: failed to parse string\n" .
117             "=> " . join( "\n ", @! ) . "\n" );
118             }
119             }
120              
121              
122             sub object {
123 0     0 1 0 my $self = shift;
124 0         0 return $self;
125             }
126              
127              
128             sub database {
129 5     5 1 976 my $self = shift;
130 5         24 my $db = { bibcite => {},
131             newlabel => {} };
132 5         12 for my $line ( @{$self->{tree}->{line}} ) {
  5         28  
133 315 100       723 if ( ref( $line ) eq 'HASH' ) {
134 34         95 foreach my $key ( (keys %$line)[0] ) {
135 34 100       94 $key =~ /bibcite/ and do {
136 24         92 $db->{$key}->{$line->{$key}->{label}} = $line->{$key}->{text};
137 24         48 last;
138             };
139 10 100       37 $key =~ /newlabel/ and do {
140             # if the caption text field of the label contains curly brackets,
141             # the field will be the hash of the Regexp::Grammars parser and
142             # we need to replace it by its context field:
143 9 100       37 if ( ref( $line->{$key}->{args}->[2] ) eq 'HASH' ) {
144 2         12 $line->{$key}->{args}->[2] = $line->{$key}->{args}->[2]->{''};
145             # remove the opening and closing curly brace
146 2         44 $line->{$key}->{args}->[2] =~ s/^\{(.*)\}$/$1/;
147             }
148 9         38 $db->{$key}->{$line->{$key}->{label}} = $line->{$key}->{args};
149 9         26 last;
150             };
151 1 50       7 $key =~ /input/ and do {
152 1         14 my $auxparser = SpeL::Parser::Auxiliary->new();
153 1         8 $auxparser->parseAuxFile( $line->{$key}->{file} );
154             $db =
155             {
156 1         6 bibcite => { %{$db->{bibcite}}, %{$auxparser->database()->{bibcite}} },
  1         9  
157 1         4 newlabel => { %{$db->{newlabel}}, %{$auxparser->database()->{newlabel}} },
  1         4  
  1         8  
158             };
159 1         24 last;
160             };
161             }
162             }
163             }
164 5         33 return $db;
165             }
166              
167              
168             sub _report {
169 0     0     my ( $match ) = @_;
170 0           return "__$match->{matchpos},$match->{matchline}__";
171             }
172              
173              
174             sub _errloc {
175 0     0     my $self = shift;
176 0           my ( $matchline ) = @_;
177 0           return "line $matchline";
178             }
179              
180             1;
181              
182             __END__