Attean
view release on metacpan or search on metacpan
lib/AtteanX/Functions/CompositeMaps.pm view on Meta::CPAN
=head1 NAME
AtteanX::Functions::CompositeMaps - Functions and aggregates to work with composite maps
=head1 VERSION
This document describes AtteanX::Functions::CompositeMaps version 0.032
=head1 SYNOPSIS
use v5.14;
use Attean;
=head1 DESCRIPTION
This is a utility package that defines functions and aggregates to work with
composite map datatypes.
=over 4
=cut
package AtteanX::Functions::CompositeMaps::TurtleLexerWithNull {
use Moo;
use AtteanX::Serializer::TurtleTokens;
use AtteanX::Parser::Turtle;
use AtteanX::SPARQL::Constants;
extends 'AtteanX::Parser::Turtle::Lexer';
sub get_token {
my $self = shift;
while (1) {
$self->fill_buffer unless (length($self->buffer));
my $start_column = $self->column;
my $start_line = $self->line;
if ($self->buffer =~ /^[ \r\n\t]+/o) {
my $ws = $self->read_length($+[0]);
# we're ignoring whitespace tokens, but we could return them here instead of falling through to the 'next':
unless ($self->ignore_whitespace) {
return $self->new_token(WS, $start_line, $start_column, $ws);
}
next;
}
my $c = $self->peek_char();
return unless (defined($c));
if ($c eq ':') {
$self->read_length(1);
return AtteanX::Parser::Turtle::Token->fast_constructor(PREFIXNAME, -1, -1, -1, -1, [':']);
}
if ($self->buffer =~ /^null\b/) {
$self->read_length($+[0]);
return 1;
} elsif ($self->buffer =~ /^(true|false)\b/) {
my $bool = $self->read_length($+[0]);
return $self->new_token(BOOLEAN, $start_line, $start_column, $bool);
}
return $self->SUPER::get_token();
}
}
}
package AtteanX::Functions::CompositeMaps 0.032 {
use Attean;
use Attean::RDF;
use Encode qw(decode_utf8);
use Scalar::Util qw(blessed);
use Digest::SHA qw(sha1_hex);
use AtteanX::Serializer::TurtleTokens;
use AtteanX::Parser::Turtle;
use AtteanX::SPARQL::Constants;
use AtteanX::Functions::CompositeLists;
our $CDT_BASE = 'http://w3id.org/awslabs/neptune/SPARQL-CDTs/';
our $MAP_TYPE_IRI = "${CDT_BASE}Map";
# Assume the opening token of the cdt has already been consumed.
# Return either a HASH or ARRAY reference, depending on the closing token.
# Does not validate the lexical form with respect to balanced cdt tokens.
sub _recursive_lexer_parse_cdt {
my $p = shift;
my $lexer = shift;
my @nodes;
my $s = AtteanX::Serializer::TurtleTokens->new( suppress_whitespace => 1 );
while (my $t = $p->_next_nonws($lexer)) {
if ($t and not blessed($t)) {
# this is the special value returned from our lexer subclass that indicates a null values
push(@nodes, undef);
} else {
next if ($t->type == COMMA);
next if ($t->type == PREFIXNAME and $t->value eq ':'); # COLON
if ($t->type == LBRACE) {
my $hash = _recursive_lexer_parse_cdt($p, $lexer);
push(@nodes, AtteanX::Functions::CompositeMaps::map_to_lex(%$hash));
} elsif ($t->type == RBRACE) {
my %hash;
die "odd number of map elements" unless (scalar(@nodes) % 2 == 0);
while (my ($k, $v) = splice(@nodes, 0, 2)) {
my @tokens;
push(@tokens, $k->sparql_tokens->elements);
my $iter = Attean::ListIterator->new( values => \@tokens, item_type => 'AtteanX::Parser::Turtle::Token' );
my $bytes = $s->serialize_iter_to_bytes($iter);
my $key_string = decode_utf8($bytes);
$hash{ $key_string } = $v;
}
return \%hash;
} elsif ($t->type == LBRACKET) {
my $subnodes = _recursive_lexer_parse_cdt($p, $lexer);
push(@nodes, AtteanX::Functions::CompositeLists::list_to_lex(@$subnodes));
} elsif ($t->type == RBRACKET) {
return \@nodes;
} else {
my $t = $p->_object($lexer, $t);
push(@nodes, $t);
}
( run in 2.603 seconds using v1.01-cache-2.11-cpan-97f6503c9c8 )