File Coverage

blib/lib/AtteanX/Parser/Trig.pm
Criterion Covered Total %
statement 43 132 32.5
branch 0 36 0.0
condition 0 21 0.0
subroutine 16 23 69.5
pod 3 3 100.0
total 62 215 28.8


line stmt bran cond sub pod time code
1 2     2   7931 use v5.14;
  2         8  
2 2     2   11 use warnings;
  2         4  
  2         99  
3              
4             # AtteanX::Parser::Trig
5             # -----------------------------------------------------------------------------
6              
7             =head1 NAME
8              
9             AtteanX::Parser::Trig - Trig RDF Parser
10              
11             =head1 VERSION
12              
13             This document describes AtteanX::Parser::Trig version 0.032
14              
15             =head1 SYNOPSIS
16              
17             use Attean;
18             my $parser = AtteanX::Parser::Trig->new( handler => sub {...}, base => $base_iri );
19            
20             # Parse data from a file-handle and handle triples in the 'handler' callback
21             $parser->parse_cb_from_io( $fh );
22            
23             # Parse the given byte-string, and return an iterator of triples
24             my $iter = $parser->parse_iter_from_bytes('<s> <p> 1, 2, 3 .');
25             while (my $triple = $iter->next) {
26             print $triple->as_string;
27             }
28              
29             =head1 DESCRIPTION
30              
31             This module implements a parser for the Trig RDF format.
32              
33             =head1 ROLES
34              
35             This class consumes L<Attean::API::Parser>, L<Attean::API::PushParser>,
36             <Attean::API::AbbreviatingParser>, and <Attean::API::TripleParser>.
37              
38             =head1 ATTRIBUTES
39              
40             =over 4
41              
42             =item C<< canonical_media_type >>
43              
44             =item C<< media_types >>
45              
46             =item C<< file_extensions >>
47              
48             =item C<< canonicalize >>
49              
50             A boolean indicating whether term values should be canonicalized during parsing.
51              
52             =back
53              
54             =head1 METHODS
55              
56             =over 4
57              
58             =cut
59              
60             use Moo;
61 2     2   10 use Types::Standard qw(Bool ArrayRef HashRef Str Maybe InstanceOf);
  2         5  
  2         12  
62 2     2   713 use Types::Namespace qw( NamespaceMap );
  2         4  
  2         22  
63 2     2   2234 use utf8;
  2         5  
  2         18  
64 2     2   599 use Carp qw(carp);
  2         6  
  2         12  
65 2     2   47 use Encode qw(encode);
  2         4  
  2         100  
66 2     2   10 use Scalar::Util qw(blessed);
  2         4  
  2         63  
67 2     2   9 use Attean::API::Parser;
  2         5  
  2         64  
68 2     2   564 use AtteanX::Parser::Turtle;
  2         5  
  2         54  
69 2     2   424 use AtteanX::Parser::Turtle::Constants;
  2         4  
  2         50  
70 2     2   11 use namespace::clean;
  2         4  
  2         255  
71 2     2   12  
  2         4  
  2         9  
72             my $RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
73             my $XSD = 'http://www.w3.org/2001/XMLSchema#';
74            
75             extends 'AtteanX::Parser::Turtle';
76              
77              
78 0     0 1 0 return [qw(text/trig)];
79             }
80              
81 3     3 1 8  
82             has 'canonicalize' => (is => 'rw', isa => Bool, default => 0);
83             has '_map' => (is => 'ro', isa => HashRef[Str], default => sub { +{} });
84 1     1 1 3  
85             with 'Attean::API::MixedStatementParser';
86            
87             ################################################################################
88              
89             # this is the entry point where we change the rules from Turtle to Trig
90             my $self = shift;
91             my $l = shift;
92             $l->check_for_bom;
93             while (my $t = $self->_next_nonws($l)) {
94             $self->_trigDoc($l, $t);
95 0     0     }
96 0           }
97 0            
98 0           my $self = shift;
99 0           my $l = shift;
100             my $t = shift;
101             my $type = $t->type;
102             if ($type == TURTLEPREFIX or $type == PREFIX) {
103             $t = $self->_get_token_type($l, PREFIXNAME);
104 0     0     use Data::Dumper;
105 0           unless (defined($t->value)) {
106 0           my $tname = AtteanX::Parser::Turtle::Constants::decrypt_constant($t->type);
107 0           Carp::confess "undefined $tname token value: " . Dumper($t);
108 0 0 0       }
    0 0        
109 0           my $name = $t->value;
110 2     2   1605 chop($name) if (substr($name, -1) eq ':');
  2         4  
  2         1727  
111 0 0         # $name =~ s/:$//;
112 0           $t = $self->_get_token_type($l, IRI);
113 0           my %args = (value => $t->value);
114             if ($self->has_base) {
115 0           $args{base} = $self->base;
116 0 0         }
117             my $r = $self->new_iri(%args);
118 0           my $iri = $r->as_string;
119 0           if ($type == TURTLEPREFIX) {
120 0 0         $t = $self->_get_token_type($l, DOT);
121 0           # $t = $self->_next_nonws($l);
122             # if ($t and $t->type != DOT) {
123 0           # $self->_unget_token($t);
124 0           # }
125 0 0         }
126 0           $self->_map->{$name} = $iri;
127             if ($self->has_namespaces) {
128             my $ns = $self->namespaces;
129             unless ($ns->namespace_uri($name)) {
130             $ns->add_mapping($name, $iri);
131             }
132 0           }
133 0 0         }
134 0           elsif ($type == TURTLEBASE or $type == BASE) {
135 0 0         $t = $self->_get_token_type($l, IRI);
136 0           my %args = (value => $t->value);
137             if ($self->has_base) {
138             $args{base} = $self->base;
139             }
140             my $r = $self->new_iri(%args);
141 0           my $iri = $r->as_string;
142 0           if ($type == TURTLEBASE) {
143 0 0         $t = $self->_get_token_type($l, DOT);
144 0           # $t = $self->_next_nonws($l);
145             # if ($t and $t->type != DOT) {
146 0           # $self->_unget_token($t);
147 0           # }
148 0 0         }
149 0           $self->base($iri);
150             }
151             else {
152             $self->_block( $l, $t );
153             }
154             # }
155 0           }
156              
157             my $self = shift;
158 0           my $l = shift;
159             my $t = shift;
160             my $type = $t->type;
161             if ($type == GRAPH) {
162             # "GRAPH" labelOrSubject wrappedGraph
163             my $graph = $self->_labelOrSubject($l);
164 0     0     local($self->{graph}) = $graph;
165 0           $t = $self->_get_token_type($l, LBRACE);
166 0           $self->_block($l, $t);
167 0           } elsif ($type == LBRACE) {
168 0 0         $t = $self->_next_nonws($l);
    0          
169             $type = $t->type;
170 0           while ($type != RBRACE) {
171 0           $self->_triple($l, $t);
172 0           $t = $self->_next_nonws($l);
173 0           $type = $t->type;
174             unless ($type == RBRACE or $type == DOT) {
175 0           carp "Expected DOT or closing brace";
176 0           }
177 0           if ($type == DOT) {
178 0           $t = $self->_next_nonws($l);
179 0           $type = $t->type;
180 0           }
181 0 0 0       }
182 0           } else {
183             $self->_triple($l, $t);
184 0 0         $t = $self->_get_token_type($l, DOT);
185 0           }
186 0           }
187            
188             my $self = shift;
189             my $l = shift;
190 0           my $t = $self->_next_nonws($l);
191 0           if ($t->type == IRI or $t->type == PREFIXNAME or $t->type == BNODE) {
192             return $self->_token_to_node($t);
193             } else {
194             $self->_throw_error(sprintf("Expecting graph name but got %s", decrypt_constant($t->type)), $t, $l);
195             }
196 0     0     }
197 0          
198 0           my $self = shift;
199 0 0 0       my $subj = shift;
      0        
200 0           my $pred = shift;
201             my $obj = shift;
202 0           if ($self->canonicalize and blessed($obj) and $obj->does('Attean::API::Literal')) {
203             $obj = $obj->canonicalize;
204             }
205            
206             my $graph = $self->{graph};
207 0     0     my $t = (defined($graph))
208 0           ? Attean::Quad->new($subj, $pred, $obj, $graph)
209 0           : Attean::Triple->new($subj, $pred, $obj);
210 0           $self->handler->($t);
211 0 0 0       return $t;
      0        
212 0           }
213              
214             my $self = shift;
215 0           my $message = shift;
216 0 0         my $t = shift;
217             my $l = shift;
218             my $line = $t->start_line;
219 0           my $col = $t->start_column;
220 0           # Carp::cluck "$message at $line:$col";
221             my $text = "$message at $line:$col";
222             if (defined($t->value)) {
223             $text .= " (near '" . $t->value . "')";
224 0     0     }
225 0           Carp::cluck "TriG parser error";
226 0           die $text;
227 0           }
228 0           }
229 0            
230             1;
231 0            
232 0 0          
233 0           =back
234              
235 0           =head1 BUGS
236 0            
237             Please report any bugs or feature requests to through the GitHub web interface
238             at L<https://github.com/kasei/perlrdf/issues>.
239              
240             =head1 AUTHOR
241              
242             Gregory Todd Williams C<< <gwilliams@cpan.org> >>
243              
244             =head1 COPYRIGHT
245              
246             Copyright (c) 2014--2022 Gregory Todd Williams. This
247             program is free software; you can redistribute it and/or modify it under
248             the same terms as Perl itself.
249              
250             =cut