| line | stmt | bran | cond | sub | pod | time | code | 
| 1 | 12 |  |  | 12 |  | 86367 | use v5.14; | 
|  | 12 |  |  |  |  | 45 |  | 
| 2 | 12 |  |  | 12 |  | 66 | use warnings; | 
|  | 12 |  |  |  |  | 30 |  | 
|  | 12 |  |  |  |  | 628 |  | 
| 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 |  | 66 | use Types::Standard qw(Bool ArrayRef HashRef Str Maybe InstanceOf); | 
|  | 12 |  |  |  |  | 41 |  | 
|  | 12 |  |  |  |  | 106 |  | 
| 62 | 12 |  |  | 12 |  | 4505 | use Types::Namespace qw( NamespaceMap ); | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 139 |  | 
| 63 | 12 |  |  | 12 |  | 14273 | use utf8; | 
|  | 12 |  |  |  |  | 37 |  | 
|  | 12 |  |  |  |  | 104 |  | 
| 64 | 12 |  |  | 12 |  | 3976 | use Carp qw(carp); | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 106 |  | 
| 65 | 12 |  |  | 12 |  | 324 | use Encode qw(encode); | 
|  | 12 |  |  |  |  | 30 |  | 
|  | 12 |  |  |  |  | 811 |  | 
| 66 | 12 |  |  | 12 |  | 87 | use Scalar::Util qw(blessed); | 
|  | 12 |  |  |  |  | 38 |  | 
|  | 12 |  |  |  |  | 486 |  | 
| 67 | 12 |  |  | 12 |  | 71 | use AtteanX::Parser::Turtle::Constants; | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 436 |  | 
| 68 | 12 |  |  | 12 |  | 65 | use AtteanX::Parser::Turtle::Lexer; | 
|  | 12 |  |  |  |  | 26 |  | 
|  | 12 |  |  |  |  | 1699 |  | 
| 69 | 12 |  |  | 12 |  | 5463 | use AtteanX::Parser::Turtle::Token; | 
|  | 12 |  |  |  |  | 37 |  | 
|  | 12 |  |  |  |  | 444 |  | 
| 70 | 12 |  |  | 12 |  | 105 | use Attean::API::Parser; | 
|  | 12 |  |  |  |  | 25 |  | 
|  | 12 |  |  |  |  | 344 |  | 
| 71 | 12 |  |  | 12 |  | 79 | use namespace::clean; | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 365 |  | 
| 72 | 12 |  |  | 12 |  | 57 |  | 
|  | 12 |  |  |  |  | 24 |  | 
|  | 12 |  |  |  |  | 82 |  | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 1 |  |  | 1 | 1 | 694 | return [qw(application/x-turtle application/turtle text/turtle)]; | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 3 |  |  | 3 | 1 | 25 |  | 
| 78 |  |  |  |  |  |  | has 'canonicalize'	=> (is => 'rw', isa => Bool, default => 0); | 
| 79 |  |  |  |  |  |  | has '_map' => (is => 'ro', isa => HashRef[Str], default => sub { +{} }); | 
| 80 | 2 |  |  | 2 | 1 | 8 |  | 
| 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 | 9 | undef $fh; | 
| 116 | 4 |  |  |  |  | 9 | 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 |  |  |  |  | 59 |  | 
| 125 | 4 |  |  |  |  | 682 | 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 | 147 | } | 
| 138 | 28 |  |  |  |  | 60 |  | 
| 139 |  |  |  |  |  |  | =item C<< parse_term_from_bytes ( $bytes ) >> | 
| 140 | 6 |  |  | 6 |  | 41 |  | 
|  | 6 |  |  | 3 |  | 13 |  | 
|  | 6 |  |  |  |  | 45 |  | 
|  | 3 |  |  |  |  | 2285 |  | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 14 |  | 
|  | 28 |  |  |  |  | 612 |  | 
| 141 | 28 |  |  |  |  | 7192 | =item C<< parse_node ( $bytes ) >> | 
| 142 | 28 |  |  |  |  | 4229 |  | 
| 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 | 870 | my $self	= shift; | 
| 156 | 12 | 50 |  |  |  | 54 | my $string	= shift; | 
| 157 | 0 |  |  |  |  | 0 | my %args	= @_; | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 12 |  |  |  |  | 56 | 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 | 19 | return $node; | 
| 164 | 12 |  |  |  |  | 18 | } | 
| 165 | 12 |  |  |  |  | 23 |  | 
| 166 |  |  |  |  |  |  | my $self	= shift; | 
| 167 | 12 |  |  |  |  | 195 | my $l		= shift; | 
| 168 | 12 |  |  |  |  | 904 | $l->check_for_bom; | 
| 169 | 12 |  |  |  |  | 1895 | while (my $t = $self->_next_nonws($l)) { | 
| 170 | 12 |  |  |  |  | 46 | $self->_statement($l, $t); | 
| 171 | 12 |  |  |  |  | 132 | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | ################################################################################ | 
| 175 | 32 |  |  | 32 |  | 70 |  | 
| 176 | 32 |  |  |  |  | 65 | my $self	= shift; | 
| 177 | 32 |  |  |  |  | 139 | my $t		= shift; | 
| 178 | 32 |  |  |  |  | 131 | push(@{ $self->_stack }, $t); | 
| 179 | 86 |  |  |  |  | 258 | # 		push(@{ $self->{ stack } }, $t); | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | my $self	= shift; | 
| 183 |  |  |  |  |  |  | if (scalar(@{ $self->_stack })) { | 
| 184 |  |  |  |  |  |  | return pop(@{ $self->_stack }); | 
| 185 |  |  |  |  |  |  | } | 
| 186 | 254 |  |  | 254 |  | 339 | my $l		= shift; | 
| 187 | 254 |  |  |  |  | 285 | while (1) { | 
| 188 | 254 |  |  |  |  | 288 | my $t	= $l->get_token; | 
|  | 254 |  |  |  |  | 448 |  | 
| 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 |  | 12040 | return $t; | 
| 194 | 761 | 100 |  |  |  | 831 | } | 
|  | 761 |  |  |  |  | 1732 |  | 
| 195 | 254 |  |  |  |  | 284 | } | 
|  | 254 |  |  |  |  | 704 |  | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 507 |  |  |  |  | 691 | my $self	= shift; | 
| 198 | 507 |  |  |  |  | 591 | my $l		= shift; | 
| 199 | 507 |  |  |  |  | 1316 | my $type	= shift; | 
| 200 | 507 | 100 |  |  |  | 39212 | 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 |  |  |  |  | 1064 | } | 
| 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 |  | 222 | } | 
| 210 | 155 |  |  |  |  | 199 |  | 
| 211 | 155 |  |  |  |  | 225 | my $self	= shift; | 
| 212 | 155 |  |  |  |  | 278 | my $l		= shift; | 
| 213 | 155 | 50 |  |  |  | 331 | 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 |  |  |  | 434 | $t	= $self->_get_token_type($l, PREFIXNAME); | 
| 218 | 0 |  |  |  |  | 0 | use Data::Dumper; | 
| 219 |  |  |  |  |  |  | unless (defined($t->value)) { | 
| 220 | 155 |  |  |  |  | 540 | 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 |  | 140 | chop($name) if (substr($name, -1) eq ':'); | 
| 225 | 86 |  |  |  |  | 468 | # 			$name		=~ s/:$//; | 
| 226 | 86 |  |  |  |  | 134 | $t	= $self->_get_token_type($l, IRI); | 
| 227 | 86 |  |  |  |  | 211 | my %args	= (value => $t->value); | 
| 228 |  |  |  |  |  |  | if ($self->has_base) { | 
| 229 | 86 | 100 | 100 |  |  | 511 | $args{base}	= $self->base; | 
|  |  | 100 | 66 |  |  |  |  | 
| 230 | 33 |  |  |  |  | 98 | } | 
| 231 | 12 |  |  | 12 |  | 17022 | my $r	= $self->new_iri(%args); | 
|  | 12 |  |  |  |  | 32 |  | 
|  | 12 |  |  |  |  | 33113 |  | 
| 232 | 33 | 50 |  |  |  | 107 | 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 |  |  |  |  | 86 | # 			if ($t and $t->type != DOT) { | 
| 237 | 33 | 50 |  |  |  | 135 | # 				$self->_unget_token($t); | 
| 238 |  |  |  |  |  |  | # 			} | 
| 239 | 33 |  |  |  |  | 99 | } | 
| 240 | 33 |  |  |  |  | 135 | $self->_map->{$name}	= $iri; | 
| 241 | 33 | 100 |  |  |  | 144 | if ($self->has_namespaces) { | 
| 242 | 1 |  |  |  |  | 21 | my $ns	= $self->namespaces; | 
| 243 |  |  |  |  |  |  | unless ($ns->namespace_uri($name)) { | 
| 244 | 33 |  |  |  |  | 175 | $ns->add_mapping($name, $iri); | 
| 245 | 33 |  |  |  |  | 6843 | } | 
| 246 | 33 | 100 |  |  |  | 7893 | } | 
| 247 | 31 |  |  |  |  | 99 | } | 
| 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 |  |  |  |  | 138 | } | 
| 254 | 33 | 100 |  |  |  | 265 | my $r	= $self->new_iri(%args); | 
| 255 | 6 |  |  |  |  | 99 | my $iri	= $r->as_string; | 
| 256 | 6 | 50 |  |  |  | 52 | if ($type == TURTLEBASE) { | 
| 257 | 6 |  |  |  |  | 44 | $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 |  |  |  |  | 4 | $self->base($iri); | 
| 264 | 1 | 50 |  |  |  | 5 | } | 
| 265 | 0 |  |  |  |  | 0 | else { | 
| 266 |  |  |  |  |  |  | $self->_triple( $l, $t ); | 
| 267 | 1 |  |  |  |  | 8 | $t	= $self->_get_token_type($l, DOT); | 
| 268 | 1 |  |  |  |  | 239 | } | 
| 269 | 1 | 50 |  |  |  | 273 | # 	} | 
| 270 | 0 |  |  |  |  | 0 | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | my $self	= shift; | 
| 273 |  |  |  |  |  |  | my $l		= shift; | 
| 274 |  |  |  |  |  |  | my $t		= shift; | 
| 275 |  |  |  |  |  |  | my $type	= $t->type; | 
| 276 | 1 |  |  |  |  | 22 | # subject | 
| 277 |  |  |  |  |  |  | my $subj; | 
| 278 |  |  |  |  |  |  | my $bnode_plist	= 0; | 
| 279 | 52 |  |  |  |  | 185 | if ($type == LTLT) { | 
| 280 | 52 |  |  |  |  | 136 | $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 |  | 79 | $self->_unget_token($t); | 
| 287 | 52 |  |  |  |  | 82 | $self->_predicateObjectList( $l, $subj ); | 
| 288 | 52 |  |  |  |  | 84 | $t	= $self->_get_token_type($l, RBRACKET); | 
| 289 | 52 |  |  |  |  | 107 | } | 
| 290 |  |  |  |  |  |  | } elsif ($type == LPAREN) { | 
| 291 | 52 |  |  |  |  | 69 | my $t	= $self->_next_nonws($l); | 
| 292 | 52 |  |  |  |  | 87 | if ($t->type == RPAREN) { | 
| 293 | 52 | 100 | 66 |  |  | 361 | $subj	= Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 294 | 1 |  |  |  |  | 6 | } else { | 
| 295 |  |  |  |  |  |  | $subj	= Attean::Blank->new(); | 
| 296 | 1 |  |  |  |  | 2 | my @objects	= $self->_object($l, $t); | 
| 297 | 1 |  |  |  |  | 22 |  | 
| 298 | 1 |  |  |  |  | 61 | while (1) { | 
| 299 | 1 | 50 |  |  |  | 7 | 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 |  |  |  |  | 202 | } | 
| 326 |  |  |  |  |  |  | } | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | my $self	= shift; | 
| 329 | 52 | 100 |  |  |  | 894 | my $l		= shift; | 
| 330 |  |  |  |  |  |  | my $subj	= $self->_qtSubject($l); | 
| 331 | 1 |  |  |  |  | 3 |  | 
| 332 | 1 |  |  |  |  | 5 | my $t		= $self->_next_nonws($l); | 
| 333 | 1 | 50 |  |  |  | 6 | my $type	= $t->type; | 
| 334 | 1 |  |  |  |  | 4 | 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 |  |  |  |  | 175 | 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 |  | 2 |  | 
| 344 | 1 |  |  |  |  | 3 | my $self	= shift; | 
| 345 | 1 |  |  |  |  | 4 | my $l		= shift; | 
| 346 |  |  |  |  |  |  | my $t		= $self->_next_nonws($l); | 
| 347 | 1 |  |  |  |  | 4 | my $type	= $t->type; | 
| 348 | 1 |  |  |  |  | 5 |  | 
| 349 | 1 | 50 | 33 |  |  | 9 | my $subj; | 
|  |  |  | 33 |  |  |  |  | 
| 350 | 0 |  |  |  |  | 0 | if ($type == LTLT) { | 
| 351 |  |  |  |  |  |  | $subj	= $self->_quotedTriple($l); | 
| 352 | 1 |  |  |  |  | 4 | } elsif ($type == LBRACKET) { | 
| 353 | 1 |  |  |  |  | 5 | $self->_get_token_type($l, RBRACKET); | 
| 354 | 1 |  |  |  |  | 6 | return Attean::Blank->new(); | 
| 355 | 1 |  |  |  |  | 20 | } elsif (not($type==IRI or $type==PREFIXNAME or $type==BNODE)) { | 
| 356 | 1 |  |  |  |  | 27 | $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 |  | 4 | return $subj; | 
| 361 | 1 |  |  |  |  | 2 | } | 
| 362 | 1 |  |  |  |  | 3 |  | 
| 363 | 1 |  |  |  |  | 4 | my $self	= shift; | 
| 364 |  |  |  |  |  |  | my $l		= shift; | 
| 365 | 1 |  |  |  |  | 3 | my $t		= shift; | 
| 366 | 1 | 50 | 33 |  |  | 27 | 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 |  |  |  |  | 6 | } 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 |  |  |  |  | 60 | } 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 |  | 3 | my $dt; | 
| 381 | 1 |  |  |  |  | 3 | my $lang; | 
| 382 | 1 |  |  |  |  | 2 | if ($t) { | 
| 383 | 1 |  |  |  |  | 2 | if ($t->type == HATHAT) { | 
| 384 | 1 |  |  |  |  | 2 | my $t		= $self->_next_nonws($l); | 
| 385 | 1 |  |  |  |  | 4 | if ($t->type == IRI or $t->type == PREFIXNAME) { | 
| 386 | 1 | 50 | 0 |  |  | 15 | $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 |  |  |  |  | 4 | $args{language}	= $lang if (defined($lang)); | 
| 396 | 1 |  |  |  |  | 5 | $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 |  |  |  | 24 | } | 
|  |  | 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 |  |  |  |  | 5 | 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 |  |  |  |  | 22 | $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 |  | 3 | my $type = $t->type; | 
| 424 | 1 |  |  |  |  | 2 | 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 |  |  |  |  | 5 | my $pred	= $self->_token_to_node($t); | 
| 428 | 2 |  |  |  |  | 4 | $self->_objectList($l, $subj, $pred); | 
| 429 | 2 |  |  |  |  | 34 |  | 
| 430 | 2 | 100 |  |  |  | 32 | $t		= $self->_next_nonws($l); | 
| 431 | 2 |  |  |  |  | 137 | last unless ($t); | 
| 432 | 2 |  |  |  |  | 9 | if ($t->type == SEMICOLON) { | 
| 433 |  |  |  |  |  |  | my $sc	= $t; | 
| 434 |  |  |  |  |  |  | SEMICOLON_REPEAT: | 
| 435 |  |  |  |  |  |  | $t		= $self->_next_nonws($l); | 
| 436 |  |  |  |  |  |  | unless ($t) { | 
| 437 | 56 |  |  | 56 |  | 100 | $l->_throw_error("Expecting token after semicolon, but got EOF"); | 
| 438 | 56 |  |  |  |  | 91 | } | 
| 439 | 56 |  |  |  |  | 83 | goto SEMICOLON_REPEAT if ($t->type == SEMICOLON); | 
| 440 | 56 |  |  |  |  | 140 | if ($t->type == IRI or $t->type == PREFIXNAME or $t->type == A) { | 
| 441 | 56 |  |  |  |  | 113 | next; | 
| 442 | 85 |  |  |  |  | 214 | } else { | 
| 443 | 85 | 50 | 100 |  |  | 430 | $self->_unget_token($t); | 
|  |  |  | 66 |  |  |  |  | 
| 444 | 0 |  |  |  |  | 0 | return; | 
| 445 |  |  |  |  |  |  | } | 
| 446 | 85 |  |  |  |  | 228 | } else { | 
| 447 | 85 |  |  |  |  | 330 | $self->_unget_token($t); | 
| 448 |  |  |  |  |  |  | return; | 
| 449 | 85 |  |  |  |  | 174 | } | 
| 450 | 85 | 50 |  |  |  | 212 | } | 
| 451 | 85 | 100 |  |  |  | 212 | } | 
| 452 | 29 |  |  |  |  | 44 |  | 
| 453 | 29 |  |  |  |  | 59 | my $self	= shift; | 
| 454 |  |  |  |  |  |  | my $l		= shift; | 
| 455 | 29 | 50 |  |  |  | 81 | my $subj	= shift; | 
| 456 | 0 |  |  |  |  | 0 | my $pred	= shift; | 
| 457 |  |  |  |  |  |  | while (1) { | 
| 458 | 29 | 50 |  |  |  | 109 | my $t		= $self->_next_nonws($l); | 
| 459 | 29 | 50 | 33 |  |  | 193 | last unless ($t); | 
|  |  |  | 33 |  |  |  |  | 
| 460 | 29 |  |  |  |  | 97 | 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 |  |  |  |  | 156 | } else { | 
| 467 | 56 |  |  |  |  | 128 | $self->_unget_token($t); | 
| 468 |  |  |  |  |  |  | return; | 
| 469 |  |  |  |  |  |  | } | 
| 470 |  |  |  |  |  |  | } | 
| 471 |  |  |  |  |  |  | } | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 85 |  |  | 85 |  | 135 | my $self	= shift; | 
| 474 | 85 |  |  |  |  | 130 | my $l		= shift; | 
| 475 | 85 |  |  |  |  | 120 | my $subj	= shift; | 
| 476 | 85 |  |  |  |  | 118 | my $pred	= shift; | 
| 477 | 85 |  |  |  |  | 123 | my $obj		= shift; | 
| 478 | 90 |  |  |  |  | 194 | my $qt		= $self->_assert_triple($subj, $pred, $obj); | 
| 479 | 90 | 50 |  |  |  | 195 |  | 
| 480 | 90 |  |  |  |  | 281 | my $t	= $self->_next_nonws($l); | 
| 481 | 90 |  |  |  |  | 325 | if ($t->type != LANNOT) { | 
| 482 |  |  |  |  |  |  | $self->_unget_token($t); | 
| 483 | 90 |  |  |  |  | 187 | return; | 
| 484 | 90 | 100 | 66 |  |  | 431 | } | 
| 485 | 5 |  |  |  |  | 17 |  | 
| 486 |  |  |  |  |  |  | $self->_predicateObjectList( $l, $qt ); | 
| 487 | 85 |  |  |  |  | 718 | $self->_get_token_type($l, RANNOT); | 
| 488 | 85 |  |  |  |  | 165 | } | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | my $self	= shift; | 
| 491 |  |  |  |  |  |  | my $subj	= shift; | 
| 492 |  |  |  |  |  |  | my $pred	= shift; | 
| 493 |  |  |  |  |  |  | my $obj		= shift; | 
| 494 | 90 |  |  | 90 |  | 160 | if ($self->canonicalize and blessed($obj) and $obj->does('Attean::API::Literal')) { | 
| 495 | 90 |  |  |  |  | 130 | $obj	= $obj->canonicalize; | 
| 496 | 90 |  |  |  |  | 125 | } | 
| 497 | 90 |  |  |  |  | 136 |  | 
| 498 | 90 |  |  |  |  | 118 | my $t		= Attean::Triple->new($subj, $pred, $obj); | 
| 499 | 90 |  |  |  |  | 237 | $self->handler->($t); | 
| 500 |  |  |  |  |  |  | return $t; | 
| 501 | 90 |  |  |  |  | 224 | } | 
| 502 | 90 | 100 |  |  |  | 323 |  | 
| 503 | 89 |  |  |  |  | 278 |  | 
| 504 | 89 |  |  |  |  | 166 | my $self	= shift; | 
| 505 |  |  |  |  |  |  | my $l		= shift; | 
| 506 |  |  |  |  |  |  | my $t		= shift; | 
| 507 | 1 |  |  |  |  | 9 | my $tcopy	= $t; | 
| 508 | 1 |  |  |  |  | 4 | my $obj; | 
| 509 |  |  |  |  |  |  | my $type	= $t->type; | 
| 510 |  |  |  |  |  |  | if ($type==LTLT) { | 
| 511 |  |  |  |  |  |  | return $self->_quotedTriple($l); | 
| 512 | 94 |  |  | 94 |  | 374 | } elsif ($type==LBRACKET) { | 
| 513 | 94 |  |  |  |  | 120 | $obj	= Attean::Blank->new(); | 
| 514 | 94 |  |  |  |  | 118 | my $t	= $self->_next_nonws($l); | 
| 515 | 94 |  |  |  |  | 115 | unless ($t) { | 
| 516 | 94 | 0 | 33 |  |  | 1547 | $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 |  |  |  |  | 1918 | $self->_predicateObjectList( $l, $obj ); | 
| 521 | 94 |  |  |  |  | 3601 | $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 |  | 164 | } | 
| 528 | 104 |  |  |  |  | 153 | if ($t->type == RPAREN) { | 
| 529 | 104 |  |  |  |  | 146 | $obj	= Attean::IRI->new(value => "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil", lazy => 1); | 
| 530 | 104 |  |  |  |  | 156 | } else { | 
| 531 | 104 |  |  |  |  | 134 | $obj	= Attean::Blank->new(); | 
| 532 | 104 |  |  |  |  | 290 | my @objects	= $self->_object($l, $t); | 
| 533 | 104 | 50 | 0 |  |  | 1033 |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 534 | 0 |  |  |  |  | 0 | while (1) { | 
| 535 |  |  |  |  |  |  | my $t	= $self->_next_nonws($l); | 
| 536 | 3 |  |  |  |  | 52 | if ($t->type == RPAREN) { | 
| 537 | 3 |  |  |  |  | 155 | last; | 
| 538 | 3 | 50 |  |  |  | 8 | } else { | 
| 539 | 0 |  |  |  |  | 0 | push(@objects, $self->_object($l, $t)); | 
| 540 |  |  |  |  |  |  | } | 
| 541 | 3 | 50 |  |  |  | 11 | } | 
| 542 | 3 |  |  |  |  | 7 | $self->_assert_list($obj, @objects); | 
| 543 | 3 |  |  |  |  | 13 | } | 
| 544 | 3 |  |  |  |  | 8 | } 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 |  |  |  | 4 | 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 |  |  |  |  | 55 | if ($t->type == IRI or $t->type == PREFIXNAME) { | 
| 556 |  |  |  |  |  |  | $dt	= $self->_token_to_node($t); | 
| 557 | 1 |  |  |  |  | 2 | } | 
| 558 | 2 |  |  |  |  | 7 | } elsif ($t->type == LANG) { | 
| 559 | 2 | 100 |  |  |  | 6 | $lang	= $t->value; | 
| 560 | 1 |  |  |  |  | 3 | } else { | 
| 561 |  |  |  |  |  |  | $self->_unget_token($t); | 
| 562 | 1 |  |  |  |  | 5 | } | 
| 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 |  |  | 576 | } | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 571 | 24 |  |  |  |  | 77 | } | 
| 572 | 24 |  |  |  |  | 70 | return $obj; | 
| 573 | 24 |  |  |  |  | 68 | } | 
| 574 |  |  |  |  |  |  |  | 
| 575 | 24 | 100 |  |  |  | 66 | my $self	= shift; | 
| 576 | 23 | 50 |  |  |  | 164 | 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 |  |  |  |  | 19 | elsif ($type eq IRI) { | 
| 583 |  |  |  |  |  |  | my $value	= $t->value; | 
| 584 | 19 |  |  |  |  | 66 | my %args	= (value => $value); | 
| 585 |  |  |  |  |  |  | my $iri; | 
| 586 |  |  |  |  |  |  | if ($self->has_base) { | 
| 587 | 24 |  |  |  |  | 78 | $args{base}	= $self->base; | 
| 588 | 24 | 100 |  |  |  | 86 | my $iri	= $self->new_iri(%args); | 
| 589 | 24 | 50 |  |  |  | 65 | return $iri; | 
| 590 | 24 |  |  |  |  | 476 | } | 
| 591 |  |  |  |  |  |  |  | 
| 592 | 76 |  |  |  |  | 187 | state %cache; | 
| 593 |  |  |  |  |  |  | if (my $n = $cache{$value}) { | 
| 594 |  |  |  |  |  |  | return $n; | 
| 595 | 104 |  |  |  |  | 10670 | } 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 |  | 279 | %cache	= (); | 
| 600 | 213 |  |  |  |  | 248 | } | 
| 601 | 213 |  | 66 |  |  | 609 | $cache{$value}	= $iri; | 
| 602 | 213 | 100 |  |  |  | 929 | return $iri; | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 603 | 22 |  |  |  |  | 172 | } | 
| 604 | 22 |  |  |  |  | 490 | } | 
| 605 |  |  |  |  |  |  | elsif ($type eq INTEGER) { | 
| 606 |  |  |  |  |  |  | return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}integer", lazy => 1)); | 
| 607 | 52 |  |  |  |  | 147 | } | 
| 608 | 52 |  |  |  |  | 141 | elsif ($type eq DECIMAL) { | 
| 609 | 52 |  |  |  |  | 73 | return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}decimal", lazy => 1)); | 
| 610 | 52 | 100 |  |  |  | 161 | } | 
| 611 | 5 |  |  |  |  | 87 | elsif ($type eq DOUBLE) { | 
| 612 | 5 |  |  |  |  | 42 | return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}double", lazy => 1)); | 
| 613 | 5 |  |  |  |  | 786 | } | 
| 614 |  |  |  |  |  |  | elsif ($type eq BOOLEAN) { | 
| 615 |  |  |  |  |  |  | return Attean::Literal->new(value => $t->value, datatype => Attean::IRI->new(value => "${XSD}boolean", lazy => 1)); | 
| 616 | 47 |  |  |  |  | 68 | } | 
| 617 | 47 | 100 |  |  |  | 114 | elsif ($type eq PREFIXNAME) { | 
| 618 | 24 |  |  |  |  | 63 | my ($ns, $local)	= @{ $t->args }; | 
| 619 |  |  |  |  |  |  | $ns		=~ s/:$//; | 
| 620 | 23 |  |  |  |  | 88 | unless (exists $self->_map->{$ns}) { | 
| 621 | 23 | 50 |  |  |  | 3926 | $self->_throw_error("Use of undeclared prefix '$ns'", $t); | 
| 622 |  |  |  |  |  |  | } | 
| 623 | 0 |  |  |  |  | 0 | my $prefix			= $self->_map->{$ns}; | 
| 624 |  |  |  |  |  |  | no warnings 'uninitialized'; | 
| 625 | 23 |  |  |  |  | 71 | my $iri				= $self->new_iri("${prefix}${local}"); | 
| 626 | 23 |  |  |  |  | 70 | return $iri; | 
| 627 |  |  |  |  |  |  | } | 
| 628 |  |  |  |  |  |  | elsif ($type eq BNODE) { | 
| 629 |  |  |  |  |  |  | return Attean::Blank->new($t->value); | 
| 630 | 10 |  |  |  |  | 39 | } | 
| 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 |  |  |  |  | 137 | my $self	= shift; | 
|  | 103 |  |  |  |  | 276 |  | 
| 643 | 103 |  |  |  |  | 442 | my $message	= shift; | 
| 644 | 103 | 50 |  |  |  | 388 | my $t		= shift; | 
| 645 | 0 |  |  |  |  | 0 | my $l		= shift; | 
| 646 |  |  |  |  |  |  | my $line	= $t->start_line; | 
| 647 | 103 |  |  |  |  | 213 | my $col		= $t->start_column; | 
| 648 | 12 |  |  | 12 |  | 126 | # 	Carp::cluck "$message at $line:$col"; | 
|  | 12 |  |  |  |  | 30 |  | 
|  | 12 |  |  |  |  | 2994 |  | 
| 649 | 103 |  |  |  |  | 411 | my $text	= "$message at $line:$col"; | 
| 650 | 103 |  |  |  |  | 17635 | if (defined($t->value)) { | 
| 651 |  |  |  |  |  |  | $text	.= " (near '" . $t->value . "')"; | 
| 652 |  |  |  |  |  |  | } | 
| 653 | 26 |  |  |  |  | 91 | 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 |