| 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 |