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   83902 use v5.14;
  12         46  
2 12     12   66 use warnings;
  12         24  
  12         598  
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.033
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   72 use Types::Standard qw(Bool ArrayRef HashRef Str Maybe InstanceOf);
  12         25  
  12         88  
62 12     12   4319 use Types::Namespace qw( NamespaceMap );
  12         29  
  12         141  
63 12     12   13385 use utf8;
  12         25  
  12         103  
64 12     12   3939 use Carp qw(carp);
  12         26  
  12         86  
65 12     12   304 use Encode qw(encode);
  12         26  
  12         592  
66 12     12   68 use Scalar::Util qw(blessed);
  12         24  
  12         410  
67 12     12   62 use AtteanX::Parser::Turtle::Constants;
  12         28  
  12         476  
68 12     12   74 use AtteanX::Parser::Turtle::Lexer;
  12         24  
  12         1731  
69 12     12   5244 use AtteanX::Parser::Turtle::Token;
  12         45  
  12         386  
70 12     12   92 use Attean::API::Parser;
  12         51  
  12         282  
71 12     12   66 use namespace::clean;
  12         29  
  12         248  
72 12     12   59  
  12         24  
  12         82  
73              
74 1     1 1 865 return [qw(application/x-turtle application/turtle text/turtle)];
75             }
76              
77 3     3 1 15  
78             has 'canonicalize' => (is => 'rw', isa => Bool, default => 0);
79             has '_map' => (is => 'ro', isa => HashRef[Str], default => sub { +{} });
80 2     2 1 9  
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 12 undef $fh;
116 4         10 open( $fh, '<', $filename ) or die $!;
117             }
118 4 50       22
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         70  
125 4         725 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 149 }
138 28         71  
139             =item C<< parse_term_from_bytes ( $bytes ) >>
140 6     6   45  
  6     3   14  
  6         48  
  3         2671  
  3         8  
  3         18  
  28         892  
141 28         8304 =item C<< parse_node ( $bytes ) >>
142 28         5211  
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 811 my $self = shift;
156 12 50       32 my $string = shift;
157 0         0 my %args = @_;
158            
159 12         46 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         20 }
165 12         25  
166             my $self = shift;
167 12         248 my $l = shift;
168 12         813 $l->check_for_bom;
169 12         1764 while (my $t = $self->_next_nonws($l)) {
170 12         56 $self->_statement($l, $t);
171 12         179 }
172             }
173              
174             ################################################################################
175 32     32   85  
176 32         60 my $self = shift;
177 32         226 my $t = shift;
178 32         240 push(@{ $self->_stack }, $t);
179 86         372 # push(@{ $self->{ stack } }, $t);
180             }
181              
182             my $self = shift;
183             if (scalar(@{ $self->_stack })) {
184             return pop(@{ $self->_stack });
185             }
186 254     254   344 my $l = shift;
187 254         338 while (1) {
188 254         458 my $t = $l->get_token;
  254         513  
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   12198 return $t;
194 761 100       893 }
  761         1837  
195 254         349 }
  254         823  
196              
197 507         722 my $self = shift;
198 507         594 my $l = shift;
199 507         1381 my $type = shift;
200 507 100       41877 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         1049 }
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   256 }
210 155         223  
211 155         251 my $self = shift;
212 155         314 my $l = shift;
213 155 50       413 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       492 $t = $self->_get_token_type($l, PREFIXNAME);
218 0         0 use Data::Dumper;
219             unless (defined($t->value)) {
220 155         750 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   180 chop($name) if (substr($name, -1) eq ':');
225 86         255 # $name =~ s/:$//;
226 86         149 $t = $self->_get_token_type($l, IRI);
227 86         290 my %args = (value => $t->value);
228             if ($self->has_base) {
229 86 100 100     666 $args{base} = $self->base;
    100 66        
230 33         109 }
231 12     12   17677 my $r = $self->new_iri(%args);
  12         34  
  12         32797  
232 33 50       123 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         114 # if ($t and $t->type != DOT) {
237 33 50       145 # $self->_unget_token($t);
238             # }
239 33         107 }
240 33         134 $self->_map->{$name} = $iri;
241 33 100       178 if ($self->has_namespaces) {
242 1         36 my $ns = $self->namespaces;
243             unless ($ns->namespace_uri($name)) {
244 33         194 $ns->add_mapping($name, $iri);
245 33         7792 }
246 33 100       8546 }
247 31         104 }
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         243 }
254 33 100       384 my $r = $self->new_iri(%args);
255 6         102 my $iri = $r->as_string;
256 6 50       56 if ($type == TURTLEBASE) {
257 6         47 $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         6 }
263 1         8 $self->base($iri);
264 1 50       10 }
265 0         0 else {
266             $self->_triple( $l, $t );
267 1         9 $t = $self->_get_token_type($l, DOT);
268 1         278 }
269 1 50       360 # }
270 0         0 }
271              
272             my $self = shift;
273             my $l = shift;
274             my $t = shift;
275             my $type = $t->type;
276 1         27 # subject
277             my $subj;
278             my $bnode_plist = 0;
279 52         242 if ($type == LTLT) {
280 52         219 $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   123 $self->_unget_token($t);
287 52         108 $self->_predicateObjectList( $l, $subj );
288 52         90 $t = $self->_get_token_type($l, RBRACKET);
289 52         119 }
290             } elsif ($type == LPAREN) {
291 52         105 my $t = $self->_next_nonws($l);
292 52         114 if ($t->type == RPAREN) {
293 52 100 66     520 $subj = Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1);
    100          
    50          
    50          
294 1         8 } else {
295             $subj = Attean::Blank->new();
296 1         3 my @objects = $self->_object($l, $t);
297 1         27
298 1         84 while (1) {
299 1 50       8 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         258 }
326             }
327              
328             my $self = shift;
329 52 100       1149 my $l = shift;
330             my $subj = $self->_qtSubject($l);
331 1         6  
332 1         7 my $t = $self->_next_nonws($l);
333 1 50       8 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         231 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   4
344 1         2 my $self = shift;
345 1         5 my $l = shift;
346             my $t = $self->_next_nonws($l);
347 1         6 my $type = $t->type;
348 1         14  
349 1 50 33     8 my $subj;
      33        
350 0         0 if ($type == LTLT) {
351             $subj = $self->_quotedTriple($l);
352 1         5 } elsif ($type == LBRACKET) {
353 1         5 $self->_get_token_type($l, RBRACKET);
354 1         7 return Attean::Blank->new();
355 1         22 } elsif (not($type==IRI or $type==PREFIXNAME or $type==BNODE)) {
356 1         30 $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   3 return $subj;
361 1         3 }
362 1         3  
363 1         4 my $self = shift;
364             my $l = shift;
365 1         4 my $t = shift;
366 1 50 33     17 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         7 } 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         70 } 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   4 my $dt;
381 1         3 my $lang;
382 1         4 if ($t) {
383 1         2 if ($t->type == HATHAT) {
384 1         3 my $t = $self->_next_nonws($l);
385 1         5 if ($t->type == IRI or $t->type == PREFIXNAME) {
386 1 50 0     19 $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     6 my %args = (value => $value);
      33        
      0        
395 1         6 $args{language} = $lang if (defined($lang));
396 1         4 $args{datatype} = $dt if (defined($dt));
397 1         3 $obj = Attean::Literal->new(%args);
398             } else {
399 1 50       3 $obj = $self->_token_to_node($t, $type);
400 1 50       9 }
    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         6 my $head = $subj;
409             while (@objects) {
410             my $obj = shift(@objects);
411 1         6 $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       5 $self->_assert_triple($head, Attean::IRI->new(value => "${RDF}rest", lazy => 1), $next);
414 1         25 $head = $next;
415             }
416 0         0 }
417              
418             my $self = shift;
419 1         3 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         4 $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         3 $self->_objectList($l, $subj, $pred);
429 2         37
430 2 100       38 $t = $self->_next_nonws($l);
431 2         535 last unless ($t);
432 2         10 if ($t->type == SEMICOLON) {
433             my $sc = $t;
434             SEMICOLON_REPEAT:
435             $t = $self->_next_nonws($l);
436             unless ($t) {
437 56     56   125 $l->_throw_error("Expecting token after semicolon, but got EOF");
438 56         110 }
439 56         186 goto SEMICOLON_REPEAT if ($t->type == SEMICOLON);
440 56         172 if ($t->type == IRI or $t->type == PREFIXNAME or $t->type == A) {
441 56         131 next;
442 85         240 } else {
443 85 50 100     512 $self->_unget_token($t);
      66        
444 0         0 return;
445             }
446 85         275 } else {
447 85         377 $self->_unget_token($t);
448             return;
449 85         200 }
450 85 50       238 }
451 85 100       301 }
452 29         57  
453 29         71 my $self = shift;
454             my $l = shift;
455 29 50       91 my $subj = shift;
456 0         0 my $pred = shift;
457             while (1) {
458 29 50       132 my $t = $self->_next_nonws($l);
459 29 50 33     228 last unless ($t);
      33        
460 29         102 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         174 } else {
467 56         202 $self->_unget_token($t);
468             return;
469             }
470             }
471             }
472              
473 85     85   160 my $self = shift;
474 85         155 my $l = shift;
475 85         130 my $subj = shift;
476 85         160 my $pred = shift;
477 85         133 my $obj = shift;
478 90         224 my $qt = $self->_assert_triple($subj, $pred, $obj);
479 90 50       250
480 90         361 my $t = $self->_next_nonws($l);
481 90         405 if ($t->type != LANNOT) {
482             $self->_unget_token($t);
483 90         211 return;
484 90 100 66     498 }
485 5         16
486             $self->_predicateObjectList( $l, $qt );
487 85         255 $self->_get_token_type($l, RANNOT);
488 85         192 }
489            
490             my $self = shift;
491             my $subj = shift;
492             my $pred = shift;
493             my $obj = shift;
494 90     90   556 if ($self->canonicalize and blessed($obj) and $obj->does('Attean::API::Literal')) {
495 90         266 $obj = $obj->canonicalize;
496 90         165 }
497 90         152
498 90         266 my $t = Attean::Triple->new($subj, $pred, $obj);
499 90         340 $self->handler->($t);
500             return $t;
501 90         323 }
502 90 100       380  
503 89         372  
504 89         176 my $self = shift;
505             my $l = shift;
506             my $t = shift;
507 1         9 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   480 } elsif ($type==LBRACKET) {
513 94         139 $obj = Attean::Blank->new();
514 94         133 my $t = $self->_next_nonws($l);
515 94         136 unless ($t) {
516 94 0 33     1923 $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         2356 $self->_predicateObjectList( $l, $obj );
521 94         4108 $t = $self->_get_token_type($l, RBRACKET);
522 94         219 }
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   205 }
528 104         703 if ($t->type == RPAREN) {
529 104         172 $obj = Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1);
530 104         182 } else {
531 104         152 $obj = Attean::Blank->new();
532 104         297 my @objects = $self->_object($l, $t);
533 104 50 0     1290
    100          
    100          
    50          
534 0         0 while (1) {
535             my $t = $self->_next_nonws($l);
536 3         59 if ($t->type == RPAREN) {
537 3         187 last;
538 3 50       13 } else {
539 0         0 push(@objects, $self->_object($l, $t));
540             }
541 3 50       14 }
542 3         11 $self->_assert_list($obj, @objects);
543 3         18 }
544 3         13 } 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         3 if ($type==STRING1D or $type==STRING3D or $type==STRING1S or $type==STRING3S) {
548 1 50       5 my $value = $t->value;
549 0         0 my $t = $self->_next_nonws($l);
550             my $dt;
551 1 50       7 my $lang;
552 0         0 if ($t) {
553             if ($t->type == HATHAT) {
554 1         19 my $t = $self->_next_nonws($l);
555 1         60 if ($t->type == IRI or $t->type == PREFIXNAME) {
556             $dt = $self->_token_to_node($t);
557 1         2 }
558 2         6 } elsif ($t->type == LANG) {
559 2 100       11 $lang = $t->value;
560 1         3 } else {
561             $self->_unget_token($t);
562 1         5 }
563             }
564             my %args = (value => $value);
565 1         6 $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     807 }
      66        
      66        
571 24         80 }
572 24         65 return $obj;
573 24         58 }
574              
575 24 100       80 my $self = shift;
576 23 50       148 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         71 my %args = (value => $value);
585             my $iri;
586             if ($self->has_base) {
587 24         96 $args{base} = $self->base;
588 24 100       69 my $iri = $self->new_iri(%args);
589 24 50       64 return $iri;
590 24         514 }
591            
592 76         236 state %cache;
593             if (my $n = $cache{$value}) {
594             return $n;
595 104         11290 } 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   319 %cache = ();
600 213         348 }
601 213   66     658 $cache{$value} = $iri;
602 213 100       1121 return $iri;
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
603 22         195 }
604 22         559 }
605             elsif ($type eq INTEGER) {
606             return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}integer", lazy => 1));
607 52         156 }
608 52         157 elsif ($type eq DECIMAL) {
609 52         86 return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}decimal", lazy => 1));
610 52 100       200 }
611 5         90 elsif ($type eq DOUBLE) {
612 5         41 return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}double", lazy => 1));
613 5         759 }
614             elsif ($type eq BOOLEAN) {
615             return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}boolean", lazy => 1));
616 47         75 }
617 47 100       150 elsif ($type eq PREFIXNAME) {
618 24         73 my ($ns, $local) = @{ $t->args };
619             $ns =~ s/:$//;
620 23         129 unless (exists $self->_map->{$ns}) {
621 23 50       4243 $self->_throw_error("Use of undeclared prefix '$ns'", $t);
622             }
623 0         0 my $prefix = $self->_map->{$ns};
624             no warnings 'uninitialized';
625 23         86 my $iri = $self->new_iri("${prefix}${local}");
626 23         72 return $iri;
627             }
628             elsif ($type eq BNODE) {
629             return Attean::Blank->new($t->value);
630 10         34 }
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         165 my $self = shift;
  103         361  
643 103         479 my $message = shift;
644 103 50       414 my $t = shift;
645 0         0 my $l = shift;
646             my $line = $t->start_line;
647 103         247 my $col = $t->start_column;
648 12     12   118 # Carp::cluck "$message at $line:$col";
  12         39  
  12         2917  
649 103         607 my $text = "$message at $line:$col";
650 103         20673 if (defined($t->value)) {
651             $text .= " (near '" . $t->value . "')";
652             }
653 26         122 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