File Coverage

blib/lib/AtteanX/Parser/Turtle.pm
Criterion Covered Total %
statement 323 394 81.9
branch 100 164 60.9
condition 32 72 44.4
subroutine 41 42 97.6
pod 7 7 100.0
total 503 679 74.0


line stmt bran cond sub pod time code
1 12     12   85518 use v5.14;
  12         50  
2 12     12   69 use warnings;
  12         33  
  12         635  
3              
4             # AtteanX::Parser::Turtle
5             # -----------------------------------------------------------------------------
6              
7             =head1 NAME
8              
9             AtteanX::Parser::Turtle - Turtle RDF Parser
10              
11             =head1 VERSION
12              
13             This document describes AtteanX::Parser::Turtle version 0.032
14              
15             =head1 SYNOPSIS
16              
17             use Attean;
18             my $parser = AtteanX::Parser::Turtle->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 Turtle 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 12     12   71 use Types::Standard qw(Bool ArrayRef HashRef Str Maybe InstanceOf);
  12         31  
  12         100  
62 12     12   4483 use Types::Namespace qw( NamespaceMap );
  12         33  
  12         141  
63 12     12   13487 use utf8;
  12         27  
  12         112  
64 12     12   3963 use Carp qw(carp);
  12         28  
  12         110  
65 12     12   332 use Encode qw(encode);
  12         27  
  12         664  
66 12     12   71 use Scalar::Util qw(blessed);
  12         27  
  12         421  
67 12     12   68 use AtteanX::Parser::Turtle::Constants;
  12         29  
  12         508  
68 12     12   75 use AtteanX::Parser::Turtle::Lexer;
  12         30  
  12         1754  
69 12     12   5551 use AtteanX::Parser::Turtle::Token;
  12         36  
  12         412  
70 12     12   97 use Attean::API::Parser;
  12         28  
  12         271  
71 12     12   62 use namespace::clean;
  12         25  
  12         259  
72 12     12   59  
  12         26  
  12         92  
73              
74 1     1 1 965 return [qw(application/x-turtle application/turtle text/turtle)];
75             }
76              
77 3     3 1 16  
78             has 'canonicalize' => (is => 'rw', isa => Bool, default => 0);
79             has '_map' => (is => 'ro', isa => HashRef[Str], default => sub { +{} });
80 2     2 1 10  
81             =item C<< has_namespaces >>
82              
83             Returns true if the parser has a namespace map, false otherwise.
84              
85             =cut
86              
87             has 'namespaces' => (is => 'rw', isa => Maybe[NamespaceMap], predicate => 'has_namespaces');
88             has '_stack' => (
89             is => 'ro',
90             isa => ArrayRef,
91             default => sub { [] },
92             init_arg => undef,
93             );
94            
95             with 'Attean::API::TripleParser';
96             with 'Attean::API::AbbreviatingParser';
97             with 'Attean::API::PushParser';
98            
99             my $RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
100             my $XSD = 'http://www.w3.org/2001/XMLSchema#';
101              
102             =item C<< parse_cb_from_io( $fh ) >>
103              
104             Calls the C<< $parser->handler >> function once for each
105             L<Attean::API::Binding> object that result from parsing
106             the data read from the L<IO::Handle> object C<< $fh >>.
107              
108             =cut
109              
110             my $self = shift;
111             my $fh = shift;
112              
113             unless (ref($fh)) {
114             my $filename = $fh;
115 4     4 1 11 undef $fh;
116 4         8 open( $fh, '<', $filename ) or die $!;
117             }
118 4 50       19
119 0         0 my $l = AtteanX::Parser::Turtle::Lexer->new($fh);
120 0         0 $self->_parse($l);
121 0 0       0 }
122              
123             =item C<< parse_cb_from_bytes( $data ) >>
124 4         62  
125 4         645 Calls the C<< $parser->handler >> function once for each
126             L<Attean::API::Binding> object that result from parsing
127             the data read from the UTF-8 encoded byte string C<< $data >>.
128              
129             =cut
130              
131             my $self = shift;
132             my $data = shift;
133            
134             open(my $fh, '<:encoding(UTF-8)', \$data);
135             my $l = AtteanX::Parser::Turtle::Lexer->new($fh);
136             $self->_parse($l);
137 28     28 1 202 }
138 28         65  
139             =item C<< parse_term_from_bytes ( $bytes ) >>
140 6     6   58  
  6     3   14  
  6         54  
  3         2651  
  3         8  
  3         13  
  28         909  
141 28         8810 =item C<< parse_node ( $bytes ) >>
142 28         4821  
143             Returns the Attean::API::Term object corresponding to the node whose N-Triples
144             serialization is found at the beginning of C<< $bytes >>.
145              
146             =cut
147              
148             my $self = shift;
149             unless (ref($self)) {
150             $self = $self->new();
151             }
152             return $self->parse_node(@_);
153             }
154            
155 12     12 1 866 my $self = shift;
156 12 50       28 my $string = shift;
157 0         0 my %args = @_;
158            
159 12         35 open(my $fh, '<:encoding(UTF-8)', \$string);
160             my $l = AtteanX::Parser::Turtle::Lexer->new(file => $fh, %args);
161             my $t = $self->_next_nonws($l);
162             my $node = $self->_object($l, $t);
163 12     12 1 17 return $node;
164 12         19 }
165 12         20  
166             my $self = shift;
167 12         159 my $l = shift;
168 12         775 $l->check_for_bom;
169 12         1752 while (my $t = $self->_next_nonws($l)) {
170 12         68 $self->_statement($l, $t);
171 12         135 }
172             }
173              
174             ################################################################################
175 32     32   71  
176 32         68 my $self = shift;
177 32         174 my $t = shift;
178 32         142 push(@{ $self->_stack }, $t);
179 86         288 # push(@{ $self->{ stack } }, $t);
180             }
181              
182             my $self = shift;
183             if (scalar(@{ $self->_stack })) {
184             return pop(@{ $self->_stack });
185             }
186 254     254   390 my $l = shift;
187 254         311 while (1) {
188 254         317 my $t = $l->get_token;
  254         469  
189             return unless ($t);
190             # my $type = $t->type;
191             # next if ($type == WS or $type == COMMENT);
192             # warn decrypt_constant($type) . "\n";
193 761     761   13619 return $t;
194 761 100       872 }
  761         1754  
195 254         289 }
  254         687  
196              
197 507         706 my $self = shift;
198 507         648 my $l = shift;
199 507         1323 my $type = shift;
200 507 100       40024 my $t = $self->_next_nonws($l);
201             unless ($t) {
202             $l->_throw_error(sprintf("Expecting %s but got EOF", decrypt_constant($type)));
203             return;
204 474         1002 }
205             unless ($t->type eq $type) {
206             $self->_throw_error(sprintf("Expecting %s but got %s", decrypt_constant($type), decrypt_constant($t->type)), $t, $l);
207             }
208             return $t;
209 155     155   250 }
210 155         197  
211 155         243 my $self = shift;
212 155         339 my $l = shift;
213 155 50       361 my $t = shift;
214 0         0 my $type = $t->type;
215 0         0 # when (WS) {}
216             if ($type == TURTLEPREFIX or $type == PREFIX) {
217 155 50       468 $t = $self->_get_token_type($l, PREFIXNAME);
218 0         0 use Data::Dumper;
219             unless (defined($t->value)) {
220 155         561 my $tname = AtteanX::Parser::Turtle::Constants::decrypt_constant($t->type);
221             Carp::confess "undefined $tname token value: " . Dumper($t);
222             }
223             my $name = $t->value;
224 86     86   141 chop($name) if (substr($name, -1) eq ':');
225 86         122 # $name =~ s/:$//;
226 86         135 $t = $self->_get_token_type($l, IRI);
227 86         227 my %args = (value => $t->value);
228             if ($self->has_base) {
229 86 100 100     554 $args{base} = $self->base;
    100 66        
230 33         102 }
231 12     12   17989 my $r = $self->new_iri(%args);
  12         38  
  12         33323  
232 33 50       115 my $iri = $r->as_string;
233 0         0 if ($type == TURTLEPREFIX) {
234 0         0 $t = $self->_get_token_type($l, DOT);
235             # $t = $self->_next_nonws($l);
236 33         98 # if ($t and $t->type != DOT) {
237 33 50       137 # $self->_unget_token($t);
238             # }
239 33         95 }
240 33         113 $self->_map->{$name} = $iri;
241 33 100       143 if ($self->has_namespaces) {
242 1         19 my $ns = $self->namespaces;
243             unless ($ns->namespace_uri($name)) {
244 33         167 $ns->add_mapping($name, $iri);
245 33         7171 }
246 33 100       8203 }
247 31         111 }
248             elsif ($type == TURTLEBASE or $type == BASE) {
249             $t = $self->_get_token_type($l, IRI);
250             my %args = (value => $t->value);
251             if ($self->has_base) {
252             $args{base} = $self->base;
253 33         167 }
254 33 100       275 my $r = $self->new_iri(%args);
255 6         111 my $iri = $r->as_string;
256 6 50       85 if ($type == TURTLEBASE) {
257 6         57 $t = $self->_get_token_type($l, DOT);
258             # $t = $self->_next_nonws($l);
259             # if ($t and $t->type != DOT) {
260             # $self->_unget_token($t);
261             # }
262 1         4 }
263 1         6 $self->base($iri);
264 1 50       4 }
265 0         0 else {
266             $self->_triple( $l, $t );
267 1         7 $t = $self->_get_token_type($l, DOT);
268 1         215 }
269 1 50       308 # }
270 0         0 }
271              
272             my $self = shift;
273             my $l = shift;
274             my $t = shift;
275             my $type = $t->type;
276 1         18 # subject
277             my $subj;
278             my $bnode_plist = 0;
279 52         216 if ($type == LTLT) {
280 52         147 $subj = $self->_quotedTriple($l);
281             } elsif ($type == LBRACKET) {
282             $bnode_plist = 1;
283             $subj = Attean::Blank->new();
284             my $t = $self->_next_nonws($l);
285             if ($t->type != RBRACKET) {
286 52     52   104 $self->_unget_token($t);
287 52         100 $self->_predicateObjectList( $l, $subj );
288 52         80 $t = $self->_get_token_type($l, RBRACKET);
289 52         119 }
290             } elsif ($type == LPAREN) {
291 52         91 my $t = $self->_next_nonws($l);
292 52         92 if ($t->type == RPAREN) {
293 52 100 66     421 $subj = Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1);
    100          
    50          
    50          
294 1         5 } else {
295             $subj = Attean::Blank->new();
296 1         2 my @objects = $self->_object($l, $t);
297 1         25
298 1         74 while (1) {
299 1 50       9 my $t = $self->_next_nonws($l);
300 0         0 if ($t->type == RPAREN) {
301 0         0 last;
302 0         0 } else {
303             push(@objects, $self->_object($l, $t));
304             }
305 0         0 }
306 0 0       0 $self->_assert_list($subj, @objects);
307 0         0 }
308             } elsif (not($type==IRI or $type==PREFIXNAME or $type==BNODE)) {
309 0         0 $self->_throw_error("Expecting resource or bnode but got " . decrypt_constant($type), $t, $l);
310 0         0 } else {
311             $subj = $self->_token_to_node($t);
312 0         0 }
313 0         0 # warn "Subject: $subj\n"; # XXX
314 0 0       0
315 0         0 if ($bnode_plist) {
316             #predicateObjectList?
317 0         0 $t = $self->_next_nonws($l);
318             $self->_unget_token($t);
319             if ($t->type != DOT) {
320 0         0 $self->_predicateObjectList($l, $subj);
321             }
322             } else {
323 0         0 #predicateObjectList
324             $self->_predicateObjectList($l, $subj);
325 50         187 }
326             }
327              
328             my $self = shift;
329 52 100       1068 my $l = shift;
330             my $subj = $self->_qtSubject($l);
331 1         3  
332 1         5 my $t = $self->_next_nonws($l);
333 1 50       5 my $type = $t->type;
334 1         6 unless ($type==IRI or $type==PREFIXNAME or $type==A) {
335             $self->_throw_error("Expecting verb but got " . decrypt_constant($type), $t, $l);
336             }
337             my $pred = $self->_token_to_node($t);
338 51         212 my $obj = $self->_qtObject($l, $self->_next_nonws($l));
339             $self->_get_token_type($l, GTGT);
340             my $triple = Attean::Triple->new($subj, $pred, $obj);
341             return $triple;
342             }
343 1     1   11
344 1         5 my $self = shift;
345 1         5 my $l = shift;
346             my $t = $self->_next_nonws($l);
347 1         5 my $type = $t->type;
348 1         4  
349 1 50 33     8 my $subj;
      33        
350 0         0 if ($type == LTLT) {
351             $subj = $self->_quotedTriple($l);
352 1         3 } elsif ($type == LBRACKET) {
353 1         4 $self->_get_token_type($l, RBRACKET);
354 1         6 return Attean::Blank->new();
355 1         17 } elsif (not($type==IRI or $type==PREFIXNAME or $type==BNODE)) {
356 1         24 $self->_throw_error("Expecting resource or bnode but got " . decrypt_constant($type), $t, $l);
357             } else {
358             $subj = $self->_token_to_node($t);
359             }
360 1     1   2 return $subj;
361 1         2 }
362 1         3  
363 1         6 my $self = shift;
364             my $l = shift;
365 1         2 my $t = shift;
366 1 50 33     13 my $tcopy = $t;
    50          
    50          
367 0         0 my $obj;
368             my $type = $t->type;
369 0         0 if ($type == LTLT) {
370 0         0 $obj = $self->_quotedTriple($l);
371             } elsif ($type == LBRACKET) {
372 0         0 $self->_get_token_type($l, RBRACKET);
373             return Attean::Blank->new();
374 1         4 } elsif (not($type==IRI or $type==PREFIXNAME or $type==STRING1D or $type==STRING3D or $type==STRING1S or $type==STRING3S or $type==BNODE or $type==INTEGER or $type==DECIMAL or $type==DOUBLE or $type==BOOLEAN)) {
375             $self->_throw_error("Expecting object but got " . decrypt_constant($type), $t, $l);
376 1         47 } else {
377             if ($type==STRING1D or $type==STRING3D or $type==STRING1S or $type==STRING3S) {
378             my $value = $t->value;
379             my $t = $self->_next_nonws($l);
380 1     1   2 my $dt;
381 1         2 my $lang;
382 1         2 if ($t) {
383 1         2 if ($t->type == HATHAT) {
384 1         3 my $t = $self->_next_nonws($l);
385 1         4 if ($t->type == IRI or $t->type == PREFIXNAME) {
386 1 50 0     14 $dt = $self->_token_to_node($t);
    50          
    50          
387 0         0 }
388             } elsif ($t->type == LANG) {
389 0         0 $lang = $t->value;
390 0         0 } else {
391             $self->_unget_token($t);
392 0         0 }
393             }
394 1 50 33     5 my %args = (value => $value);
      33        
      0        
395 1         3 $args{language} = $lang if (defined($lang));
396 1         3 $args{datatype} = $dt if (defined($dt));
397 1         2 $obj = Attean::Literal->new(%args);
398             } else {
399 1 50       4 $obj = $self->_token_to_node($t, $type);
400 1 50       7 }
    50          
401 0         0 }
402 0 0 0     0 return $obj;
403 0         0 }
404            
405             my $self = shift;
406 0         0 my $subj = shift;
407             my @objects = @_;
408 1         3 my $head = $subj;
409             while (@objects) {
410             my $obj = shift(@objects);
411 1         4 $self->_assert_triple($head, Attean::IRI->new(value => "${RDF}first", lazy => 1), $obj);
412 1 50       4 my $next = scalar(@objects) ? Attean::Blank->new() : Attean::IRI->new(value => "${RDF}nil", lazy => 1);
413 1 50       4 $self->_assert_triple($head, Attean::IRI->new(value => "${RDF}rest", lazy => 1), $next);
414 1         18 $head = $next;
415             }
416 0         0 }
417              
418             my $self = shift;
419 1         4 my $l = shift;
420             my $subj = shift;
421             my $t = $self->_next_nonws($l);
422             while (1) {
423 1     1   2 my $type = $t->type;
424 1         1 unless ($type==IRI or $type==PREFIXNAME or $type==A) {
425 1         3 $self->_throw_error("Expecting verb but got " . decrypt_constant($type), $t, $l);
426 1         2 }
427 1         3 my $pred = $self->_token_to_node($t);
428 2         4 $self->_objectList($l, $subj, $pred);
429 2         34
430 2 100       35 $t = $self->_next_nonws($l);
431 2         140 last unless ($t);
432 2         7 if ($t->type == SEMICOLON) {
433             my $sc = $t;
434             SEMICOLON_REPEAT:
435             $t = $self->_next_nonws($l);
436             unless ($t) {
437 56     56   105 $l->_throw_error("Expecting token after semicolon, but got EOF");
438 56         81 }
439 56         93 goto SEMICOLON_REPEAT if ($t->type == SEMICOLON);
440 56         150 if ($t->type == IRI or $t->type == PREFIXNAME or $t->type == A) {
441 56         125 next;
442 85         220 } else {
443 85 50 100     455 $self->_unget_token($t);
      66        
444 0         0 return;
445             }
446 85         262 } else {
447 85         351 $self->_unget_token($t);
448             return;
449 85         173 }
450 85 50       196 }
451 85 100       234 }
452 29         49  
453 29         65 my $self = shift;
454             my $l = shift;
455 29 50       84 my $subj = shift;
456 0         0 my $pred = shift;
457             while (1) {
458 29 50       103 my $t = $self->_next_nonws($l);
459 29 50 33     192 last unless ($t);
      33        
460 29         108 my $obj = $self->_object($l, $t);
461             $self->_assert_triple_with_optional_annotation($l, $subj, $pred, $obj);
462 0         0
463 0         0 $t = $self->_next_nonws($l);
464             if ($t and $t->type == COMMA) {
465             next;
466 56         152 } else {
467 56         152 $self->_unget_token($t);
468             return;
469             }
470             }
471             }
472              
473 85     85   153 my $self = shift;
474 85         142 my $l = shift;
475 85         121 my $subj = shift;
476 85         115 my $pred = shift;
477 85         133 my $obj = shift;
478 90         232 my $qt = $self->_assert_triple($subj, $pred, $obj);
479 90 50       245
480 90         308 my $t = $self->_next_nonws($l);
481 90         354 if ($t->type != LANNOT) {
482             $self->_unget_token($t);
483 90         195 return;
484 90 100 66     456 }
485 5         15
486             $self->_predicateObjectList( $l, $qt );
487 85         220 $self->_get_token_type($l, RANNOT);
488 85         160 }
489            
490             my $self = shift;
491             my $subj = shift;
492             my $pred = shift;
493             my $obj = shift;
494 90     90   522 if ($self->canonicalize and blessed($obj) and $obj->does('Attean::API::Literal')) {
495 90         128 $obj = $obj->canonicalize;
496 90         133 }
497 90         142
498 90         117 my $t = Attean::Triple->new($subj, $pred, $obj);
499 90         242 $self->handler->($t);
500             return $t;
501 90         243 }
502 90 100       332  
503 89         311  
504 89         171 my $self = shift;
505             my $l = shift;
506             my $t = shift;
507 1         7 my $tcopy = $t;
508 1         5 my $obj;
509             my $type = $t->type;
510             if ($type==LTLT) {
511             return $self->_quotedTriple($l);
512 94     94   376 } elsif ($type==LBRACKET) {
513 94         140 $obj = Attean::Blank->new();
514 94         138 my $t = $self->_next_nonws($l);
515 94         126 unless ($t) {
516 94 0 33     1576 $self->_throw_error("Expecting object but got only opening bracket", $tcopy, $l);
      33        
517 0         0 }
518             if ($t->type != RBRACKET) {
519             $self->_unget_token($t);
520 94         2127 $self->_predicateObjectList( $l, $obj );
521 94         3765 $t = $self->_get_token_type($l, RBRACKET);
522 94         189 }
523             } elsif ($type == LPAREN) {
524             my $t = $self->_next_nonws($l);
525             unless ($t) {
526             $self->_throw_error("Expecting object but got only opening paren", $tcopy, $l);
527 104     104   180 }
528 104         744 if ($t->type == RPAREN) {
529 104         155 $obj = Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1);
530 104         159 } else {
531 104         152 $obj = Attean::Blank->new();
532 104         257 my @objects = $self->_object($l, $t);
533 104 50 0     1096
    100          
    100          
    50          
534 0         0 while (1) {
535             my $t = $self->_next_nonws($l);
536 3         53 if ($t->type == RPAREN) {
537 3         207 last;
538 3 50       11 } else {
539 0         0 push(@objects, $self->_object($l, $t));
540             }
541 3 50       11 }
542 3         9 $self->_assert_list($obj, @objects);
543 3         13 }
544 3         9 } elsif (not($type==IRI or $type==PREFIXNAME or $type==STRING1D or $type==STRING3D or $type==STRING1S or $type==STRING3S or $type==BNODE or $type==INTEGER or $type==DECIMAL or $type==DOUBLE or $type==BOOLEAN)) {
545             $self->_throw_error("Expecting object but got " . decrypt_constant($type), $t, $l);
546             } else {
547 1         4 if ($type==STRING1D or $type==STRING3D or $type==STRING1S or $type==STRING3S) {
548 1 50       6 my $value = $t->value;
549 0         0 my $t = $self->_next_nonws($l);
550             my $dt;
551 1 50       6 my $lang;
552 0         0 if ($t) {
553             if ($t->type == HATHAT) {
554 1         17 my $t = $self->_next_nonws($l);
555 1         53 if ($t->type == IRI or $t->type == PREFIXNAME) {
556             $dt = $self->_token_to_node($t);
557 1         4 }
558 2         5 } elsif ($t->type == LANG) {
559 2 100       15 $lang = $t->value;
560 1         3 } else {
561             $self->_unget_token($t);
562 1         3 }
563             }
564             my %args = (value => $value);
565 1         5 $args{language} = $lang if (defined($lang));
566             $args{datatype} = $dt if (defined($dt));
567             $obj = Attean::Literal->new(%args);
568 0         0 } else {
569             $obj = $self->_token_to_node($t, $type);
570 100 100 100     602 }
      66        
      66        
571 24         81 }
572 24         67 return $obj;
573 24         50 }
574              
575 24 100       74 my $self = shift;
576 23 50       155 my $t = shift;
    100          
577 0         0 my $type = shift || $t->type;
578 0 0 0     0 if ($type eq A) {
579 0         0 state $rdftype = Attean::IRI->new(value => "${RDF}type", lazy => 1);
580             return $rdftype;
581             }
582 4         15 elsif ($type eq IRI) {
583             my $value = $t->value;
584 19         65 my %args = (value => $value);
585             my $iri;
586             if ($self->has_base) {
587 24         82 $args{base} = $self->base;
588 24 100       73 my $iri = $self->new_iri(%args);
589 24 50       64 return $iri;
590 24         495 }
591            
592 76         188 state %cache;
593             if (my $n = $cache{$value}) {
594             return $n;
595 104         11080 } else {
596             my $iri = $self->new_iri(%args);
597             if (rand() < 0.02) {
598             # clear out the cache roughly every 50 IRIs
599 213     213   325 %cache = ();
600 213         291 }
601 213   66     605 $cache{$value} = $iri;
602 213 100       952 return $iri;
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
603 22         176 }
604 22         515 }
605             elsif ($type eq INTEGER) {
606             return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}integer", lazy => 1));
607 52         140 }
608 52         181 elsif ($type eq DECIMAL) {
609 52         98 return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}decimal", lazy => 1));
610 52 100       179 }
611 5         90 elsif ($type eq DOUBLE) {
612 5         46 return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}double", lazy => 1));
613 5         763 }
614             elsif ($type eq BOOLEAN) {
615             return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}boolean", lazy => 1));
616 47         73 }
617 47 100       140 elsif ($type eq PREFIXNAME) {
618 24         68 my ($ns, $local) = @{ $t->args };
619             $ns =~ s/:$//;
620 23         107 unless (exists $self->_map->{$ns}) {
621 23 50       4262 $self->_throw_error("Use of undeclared prefix '$ns'", $t);
622             }
623 0         0 my $prefix = $self->_map->{$ns};
624             no warnings 'uninitialized';
625 23         79 my $iri = $self->new_iri("${prefix}${local}");
626 23         77 return $iri;
627             }
628             elsif ($type eq BNODE) {
629             return Attean::Blank->new($t->value);
630 10         36 }
631             elsif ($type eq STRING1D) {
632             return Attean::Literal->new($t->value);
633 0         0 }
634             elsif ($type eq STRING1S) {
635             return Attean::Literal->new($t->value);
636 0         0 }
637             else {
638             $self->_throw_error("Converting $type to node not implemented", $t);
639 0         0 }
640             }
641              
642 103         131 my $self = shift;
  103         276  
643 103         436 my $message = shift;
644 103 50       346 my $t = shift;
645 0         0 my $l = shift;
646             my $line = $t->start_line;
647 103         210 my $col = $t->start_column;
648 12     12   135 # Carp::cluck "$message at $line:$col";
  12         59  
  12         3168  
649 103         425 my $text = "$message at $line:$col";
650 103         18444 if (defined($t->value)) {
651             $text .= " (near '" . $t->value . "')";
652             }
653 26         89 die $text;
654             }
655             }
656 0            
657             1;
658              
659 0            
660             =back
661              
662 0           =head1 BUGS
663              
664             Please report any bugs or feature requests to through the GitHub web interface
665             at L<https://github.com/kasei/perlrdf/issues>.
666              
667 0     0     =head1 AUTHOR
668 0            
669 0           Gregory Todd Williams C<< <gwilliams@cpan.org> >>
670 0            
671 0           =head1 COPYRIGHT
672 0            
673             Copyright (c) 2014--2022 Gregory Todd Williams. This
674 0           program is free software; you can redistribute it and/or modify it under
675 0 0         the same terms as Perl itself.
676 0            
677             =cut