File Coverage

blib/lib/Locale/Simple/Scraper/Parser.pm
Criterion Covered Total %
statement 85 85 100.0
branch 13 14 92.8
condition n/a
subroutine 29 29 100.0
pod 0 20 0.0
total 127 148 85.8


line stmt bran cond sub pod time code
1 1     1   6 use strict;
  1         4  
  1         50  
2 1     1   8 use warnings;
  1         2  
  1         64  
3              
4             package Locale::Simple::Scraper::Parser;
5             BEGIN {
6 1     1   37 $Locale::Simple::Scraper::Parser::AUTHORITY = 'cpan:GETTY';
7             }
8             $Locale::Simple::Scraper::Parser::VERSION = '0.017';
9             # ABSTRACT: parser to finds translation tokens in a code file
10              
11 1     1   8 use base qw( Parser::MGC );
  1         2  
  1         1134  
12              
13 1     1   12762 use Moo;
  1         21314  
  1         8  
14 1     1   2418 use Try::Tiny;
  1         1429  
  1         50  
15 1     1   996 use curry;
  1         207  
  1         1658  
16              
17             has func_qr => ( is => 'ro', default => sub { qr/\bl(|n|p|np|d|dn|dnp)\b/ } );
18             has found => ( is => 'ro', default => sub { [] } );
19             has type => ( is => 'ro', required => 1 );
20              
21             with "Locale::Simple::Scraper::ParserShortcuts";
22              
23             sub parse {
24 21     21 0 5244 my ( $self ) = @_;
25 21         225 $self->sequence_of( $self->c_any_of( $self->curry::noise, $self->curry::call ) );
26 21         1312 return $self->found;
27             }
28              
29             sub noise {
30 315     315 0 4086 my ( $self ) = @_;
31 315         995 my $noise = $self->substring_before( $self->func_qr );
32 315 100       12744 $self->fail( "no noise found" ) if !length $noise;
33 166         550 $self->debug( "discarded %d characters of noise", length $noise );
34 166         3744 return $noise;
35             }
36              
37             sub call {
38 185     185 0 8420 my ( $self ) = @_;
39              
40 185         578 my $func = $self->expect( $self->func_qr );
41 151         9277 my $line = ( $self->where )[0];
42 151         20766 $self->debug( "found func $func at line %d", $line );
43              
44             try {
45 151     151   4496 my $arguments = $self->arguments( $func );
46 57         82 push @{ $self->found }, { func => $func, args => $arguments, line => $line };
  57         505  
47             }
48             catch {
49 94 50   94   4264 die $_ if !eval { $_->isa( "Parser::MGC::Failure" ) };
  94         617  
50 94         313 $self->warn_failure( $_ );
51 151         4329 };
52              
53 151         1697 return;
54             }
55              
56             sub arguments {
57 151     151 0 228 my ( $self, $func ) = @_;
58              
59 151         302 my @arguments = ( $self->op( "(" ), $self->required_args( $func ), $self->extra_arguments, $self->op( ")" ) );
60 57         3501 $self->debug( "found %d arguments", scalar @arguments );
61              
62 57         1867 return \@arguments;
63             }
64              
65             sub op {
66 253     253 0 1573 my ( $self, $op ) = @_;
67 253 100       3624 return if $self->with_ws( maybe_expect => qr/\s*\Q$op\E/ );
68 56         3088 $self->fail( "Expected \"$op\"" );
69             }
70              
71             sub extra_arguments {
72 57     57 0 105 my ( $self ) = @_;
73 57 100       200 return if !$self->maybe_expect( "," );
74              
75 18         773 my @types = ( $self->curry::call, $self->curry::dynamic_string, $self->curry::token_int, $self->curry::variable );
76 18         769 my $extra_args = $self->list_of( ",", $self->c_any_of( @types ) );
77 18         710 return @{$extra_args};
  18         151  
78             }
79              
80             sub required_args {
81 96     96 0 5581 my ( $self, $func ) = @_;
82 96         1886 my %arg_lists = (
83             l => [qw( tr_token )],
84             ln => [qw( tr_token comma plural_token comma plural_count )],
85             lp => [qw( context_id comma tr_token )],
86             lnp => [qw( context_id comma tr_token comma plural_token comma plural_count )],
87             ld => [qw( domain_id comma tr_token )],
88             ldn => [qw( domain_id comma tr_token comma plural_token comma plural_count )],
89             ldnp => [qw( domain_id comma context_id comma tr_token comma plural_token comma plural_count )],
90             );
91 96         378 return $self->collect_from( $arg_lists{$func} );
92             }
93              
94 67     67 0 209 sub tr_token { shift->named_token( "translation token" ) }
95 21     21 0 63 sub plural_token { shift->named_token( "plural translation token" ) }
96 20     20 0 63 sub plural_count { shift->named_token( "count of plural entity", "token_int" ) }
97 9     9 0 28 sub context_id { shift->named_token( "context id" ) }
98 23     23 0 70 sub domain_id { shift->named_token( "domain id" ) }
99 45     45 0 117 sub comma { shift->op( "," ) }
100 10     10 0 923 sub variable { shift->expect( qr/[\w\.]+/ ) }
101              
102             sub constant_string {
103 144     144 0 705 my ( $self, @components ) = @_;
104              
105 144         228 my $p = $self->{patterns};
106              
107 144         612 unshift @components,
108             $self->curry::scope_of( q["], $self->c_with_ws( "double_quote_string_contents" ), q["] ),
109             $self->curry::scope_of( q['], $self->c_with_ws( "single_quote_string_contents" ), q['] );
110              
111 144         1686 my $string = $self->list_of( $self->concat_op, $self->c_any_of( @components ) );
112              
113 144 100       29116 return join "", map { $_ ? $_ : "" } @{$string} if @{$string};
  112 100       1418  
  106         203  
  144         395  
114              
115 38         114 $self->fail;
116             }
117              
118             sub concat_op {
119 144     144 0 718 my %ops = ( js => "+", pl => ".", tx => "_", py => "+" );
120 144         806 return $ops{ shift->type };
121             }
122              
123             sub dynamic_string {
124 24     24 0 3692 my ( $self ) = @_;
125 24         134 return $self->constant_string( $self->curry::call, $self->curry::variable );
126             }
127              
128             sub double_quote_string_contents {
129 52     52 0 80 my ( $self ) = @_;
130 52         220 return $self->string_contents( $self->c_expect( qr/[^\\"]+/ ), $self->c_expect_escaped( q["] ) );
131             }
132              
133             sub single_quote_string_contents {
134 56     56 0 83 my ( $self ) = @_;
135 56         269 return $self->string_contents(
136             $self->c_expect( qr/[^\\']+/ ),
137             $self->c_expect_escaped( q['] ),
138             $self->c_expect_escaped( q[\\] ),
139             $self->c_expect( qr/\\/ ),
140             );
141             }
142              
143             sub string_contents {
144 108     108 0 227 my ( $self, @contents ) = @_;
145 108         294 my $elements = $self->sequence_of( $self->c_any_of( @contents ) );
146 108 100       9675 return join "", @{$elements} if @{$elements};
  101         595  
  108         352  
147 7         19 $self->fail( "no string contents found" );
148             }
149              
150             1;
151              
152             __END__