File Coverage

blib/lib/App/Gimei/Parser.pm
Criterion Covered Total %
statement 69 69 100.0
branch 16 16 100.0
condition 27 27 100.0
subroutine 10 10 100.0
pod 0 1 0.0
total 122 123 99.1


line stmt bran cond sub pod time code
1 8     8   4643 use v5.40;
  8         29  
2 8     8   42 use feature 'class';
  8         14  
  8         1162  
3 8     8   68 no warnings 'experimental::class';
  8         16  
  8         872  
4              
5             class App::Gimei::Parser {
6              
7 8     8   3718 use App::Gimei::Generator;
  8         28  
  8         386  
8 8     8   3958 use App::Gimei::Generators;
  8         23  
  8         8731  
9              
10             #
11             # class methods
12             #
13              
14 37     37 0 633896 sub parse ($args) {
  37         57  
  37         94  
15 37         312 my $generators = App::Gimei::Generators->new();
16 37         66 foreach my $arg ( @{$args} ) {
  37         86  
17 54         118 $generators->add_generator( _parse_arg($arg) );
18             }
19              
20 31         73 return $generators;
21             }
22              
23             # BNF-like notation
24             #
25             # ARG: [WORD_TYPE] [':' RENDERING]
26             # WORD_TYPE:  TYPE_NAME [':' SUBTYPE_NAME] | TYPE_ADDRESS [':' SUBTYPE_ADDRESS ]
27             # TYPE_NAME: 'name' | 'male' | 'female'
28             # SUBTYPE_NAME: 'family' | 'given'
29             # TYPE_ADDRESS: 'address'
30             # SUBTYPE_ADDRESS: 'prefecture' | 'city' | 'town'
31             # RENDERING: 'kanji' | 'hiragana' | 'katakana' | 'romaji'
32             # (DO NOT support romaji rendering for type address)
33 54     54   63 sub _parse_arg ($arg) {
  54         74  
  54         59  
34 54         76 my ( $gen, @tokens, %params );
35              
36 54         191 @tokens = split( /[-:]/, $arg );
37              
38 54         102 my $token = shift @tokens;
39 54 100 100     272 if ( $token eq 'name' || $token eq 'male' || $token eq 'female' ) { # TYPE_NAME
    100 100        
40 36         89 $params{word_class} = "Data::Gimei::Name";
41 36 100       101 if ( $token ne 'name' ) {
42 7         19 $params{gender} = $token;
43             }
44 36         97 $params{word_subtype} = _subtype_name( \@tokens );
45             } elsif ( $token eq 'address' ) { # TYPE_ADDRESS
46 16         43 $params{word_class} = "Data::Gimei::Address";
47 16         40 $params{word_subtype} = _subtype_address( \@tokens );
48             } else {
49 2         18 die "Error: unknown word_type: $token\n";
50             }
51              
52 52         110 $params{rendering} = _rendering( \@tokens );
53              
54 52 100       120 if (@tokens) {
55 4 100       10 if ( defined $params{word_subtype} ) {
56 1         7 die "Error: unknown rendering: $tokens[0]\n";
57             } else {
58 3         36 die "Error: unknown subtype or rendering: $tokens[0]\n";
59             }
60             }
61              
62 48         381 return App::Gimei::Generator->new(%params);
63             }
64              
65 36     36   41 sub _subtype_name ($tokens_ref) {
  36         58  
  36         68  
66 36         47 my $word_subtype;
67              
68 36         214 my %map = (
69             'family' => 'surname',
70             'last' => 'surname',
71             'given' => 'forename',
72             'first' => 'forename',
73             'gender' => 'gender',
74             'sex' => 'gender',
75             );
76              
77 36   100     115 my $token = @$tokens_ref[0] // '';
78 36 100       92 if ( $word_subtype = $map{$token} ) {
79 16         28 shift @$tokens_ref;
80             }
81              
82 36         116 return $word_subtype;
83             }
84              
85 16     16   50 sub _subtype_address ($tokens_ref) {
  16         22  
  16         19  
86 16         23 my ($word_subtype);
87              
88 16   100     49 my $token = @$tokens_ref[0] // '';
89 16 100 100     85 if ( $token eq 'prefecture' || $token eq 'city' || $token eq 'town' ) {
      100        
90 9         16 shift @$tokens_ref;
91 9         18 $word_subtype = $token;
92             }
93              
94 16         41 return $word_subtype;
95             }
96              
97 52     52   62 sub _rendering ($tokens_ref) {
  52         63  
  52         71  
98 52         67 my $rendering = 'kanji';
99              
100 52   100     140 my $token = @$tokens_ref[0] // '';
101 52 100 100     262 if ( $token eq 'kanji'
      100        
      100        
102             || $token eq 'hiragana'
103             || $token eq 'katakana'
104             || $token eq 'romaji' )
105             {
106 14         18 shift @$tokens_ref;
107 14         20 $rendering = $token;
108             }
109              
110 52         135 return $rendering;
111             }
112             }
113              
114             1;