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   8 use strict;
  1         2  
  1         42  
2 1     1   6 use warnings;
  1         3  
  1         60  
3              
4             package Locale::Simple::Scraper::Parser;
5             BEGIN {
6 1     1   45 $Locale::Simple::Scraper::Parser::AUTHORITY = 'cpan:GETTY';
7             }
8             $Locale::Simple::Scraper::Parser::VERSION = '0.019';
9             # ABSTRACT: parser to finds translation tokens in a code file
10              
11 1     1   7 use base qw( Parser::MGC );
  1         2  
  1         1255  
12              
13 1     1   14627 use Moo;
  1         18116  
  1         7  
14 1     1   1119 use Try::Tiny;
  1         1635  
  1         79  
15 1     1   850 use curry;
  1         206  
  1         1690  
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 4046 my ( $self ) = @_;
25 21         139 $self->sequence_of( $self->c_any_of( $self->curry::noise, $self->curry::call ) );
26 21         898 return $self->found;
27             }
28              
29             sub noise {
30 317     317 0 4347 my ( $self ) = @_;
31 317         1015 my $noise = $self->substring_before( $self->func_qr );
32 317 100       12671 $self->fail( "no noise found" ) if !length $noise;
33 167         549 $self->debug( "discarded %d characters of noise", length $noise );
34 167         3895 return $noise;
35             }
36              
37             sub call {
38 188     188 0 9149 my ( $self ) = @_;
39              
40 188         593 my $func = $self->expect( $self->func_qr );
41 152         8694 my $line = ( $self->where )[0];
42 152         20401 $self->debug( "found func $func at line %d", $line );
43              
44             try {
45 152     152   4629 my $arguments = $self->arguments( $func );
46 58         88 push @{ $self->found }, { func => $func, args => $arguments, line => $line };
  58         387  
47             }
48             catch {
49 94 50   94   4198 die $_ if !eval { $_->isa( "Parser::MGC::Failure" ) };
  94         397  
50 94         305 $self->warn_failure( $_ );
51 152         4268 };
52              
53 152         1719 return;
54             }
55              
56             sub arguments {
57 152     152 0 369 my ( $self, $func ) = @_;
58              
59 152         310 my @arguments = ( $self->op( "(" ), $self->required_args( $func ), $self->extra_arguments, $self->op( ")" ) );
60 58         3481 $self->debug( "found %d arguments", scalar @arguments );
61              
62 58         1490 return \@arguments;
63             }
64              
65             sub op {
66 255     255 0 1484 my ( $self, $op ) = @_;
67 255 100       3352 return if $self->with_ws( maybe_expect => qr/\s*\Q$op\E/ );
68 56         3049 $self->fail( "Expected \"$op\"" );
69             }
70              
71             sub extra_arguments {
72 58     58 0 90 my ( $self ) = @_;
73 58 100       284 return if !$self->maybe_expect( "," );
74              
75 19         720 my @types = ( $self->curry::call, $self->curry::dynamic_string, $self->curry::token_int, $self->curry::variable );
76 19         705 my $extra_args = $self->list_of( ",", $self->c_any_of( @types ) );
77 19         689 return @{$extra_args};
  19         203  
78             }
79              
80             sub required_args {
81 97     97 0 5739 my ( $self, $func ) = @_;
82 97         1032 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 97         397 return $self->collect_from( $arg_lists{$func} );
92             }
93              
94 68     68 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 66 sub plural_count { shift->named_token( "count of plural entity", "token_int" ) }
97 9     9 0 34 sub context_id { shift->named_token( "context id" ) }
98 23     23 0 68 sub domain_id { shift->named_token( "domain id" ) }
99 45     45 0 97 sub comma { shift->op( "," ) }
100 11     11 0 888 sub variable { shift->expect( qr/[\w\.]+/ ) }
101              
102             sub constant_string {
103 146     146 0 647 my ( $self, @components ) = @_;
104              
105 146         217 my $p = $self->{patterns};
106              
107 146         414 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 146         1957 my $string = $self->list_of( $self->concat_op, $self->c_any_of( @components ) );
112              
113 146 100       22280 return join "", map { $_ ? $_ : "" } @{$string} if @{$string};
  116 100       1177  
  108         204  
  146         397  
114              
115 38         103 $self->fail;
116             }
117              
118             sub concat_op {
119 146     146 0 908 my %ops = ( js => "+", pl => ".", tx => qr/(_|~)/, py => "+" );
120 146         1088 return $ops{ shift->type };
121             }
122              
123             sub dynamic_string {
124 25     25 0 2138 my ( $self ) = @_;
125 25         114 return $self->constant_string( $self->curry::call, $self->curry::variable );
126             }
127              
128             sub double_quote_string_contents {
129 55     55 0 77 my ( $self ) = @_;
130 55         247 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 93 my ( $self ) = @_;
135 56         236 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 111     111 0 219 my ( $self, @contents ) = @_;
145 111         296 my $elements = $self->sequence_of( $self->c_any_of( @contents ) );
146 111 100       9648 return join "", @{$elements} if @{$elements};
  104         546  
  111         322  
147 7         30 $self->fail( "no string contents found" );
148             }
149              
150             1;
151              
152             __END__