Attean
view release on metacpan or search on metacpan
lib/AtteanX/Parser/SPARQL.pm view on Meta::CPAN
}
$self->_add_patterns( $pattern );
}
sub __handle_GraphPatternNotTriples {
my $self = shift;
my $data = shift;
return unless ($data);
my ($class, @args) = @$data;
if ($class =~ /^Attean::Algebra::(LeftJoin|Minus)$/) {
my ($cont, $hints) = $self->_pop_pattern_container;
my $ggp = $self->_new_join(@$cont);
$ggp->hints($hints);
$self->_push_pattern_container;
# my $ggp = $self->_remove_pattern();
unless ($ggp) {
$ggp = Attean::Algebra::BGP->new();
}
my $opt = $class->new( children => [$ggp, @args] );
$self->_add_patterns( $opt );
} elsif ($class eq 'Attean::Algebra::Table') {
my ($table) = @args;
$self->_add_patterns( $table );
} elsif ($class =~ /^Attean::Algebra::Unfold$/) {
my ($cont, $hints) = $self->_pop_pattern_container;
my $ggp = $self->_new_join(@$cont);
$ggp->hints($hints);
$self->_push_pattern_container;
# my $ggp = $self->_remove_pattern();
unless ($ggp) {
$ggp = Attean::Algebra::BGP->new();
}
my @vars = @{ $args[0] };
my $expr = $args[1];
foreach my $var (@vars) {
my %in_scope = map { $_ => 1 } $ggp->in_scope_variables;
if (exists $in_scope{ $var->value }) {
croak "Syntax error: BIND used with variable already in scope";
}
}
my $bind = $class->new( children => [$ggp], variables => \@vars, expression => $expr );
$self->_add_patterns( $bind );
} elsif ($class =~ /^Attean::Algebra::Extend$/) {
my ($cont, $hints) = $self->_pop_pattern_container;
my $ggp = $self->_new_join(@$cont);
$ggp->hints($hints);
$self->_push_pattern_container;
# my $ggp = $self->_remove_pattern();
unless ($ggp) {
$ggp = Attean::Algebra::BGP->new();
}
my ($var, $expr) = @args;
my %in_scope = map { $_ => 1 } $ggp->in_scope_variables;
if (exists $in_scope{ $var->value }) {
croak "Syntax error: BIND used with variable already in scope";
}
my $bind = $class->new( children => [$ggp], variable => $var, expression => $expr );
$self->_add_patterns( $bind );
} elsif ($class eq 'Attean::Algebra::Service') {
my ($endpoint, $pattern, $silent) = @args;
if ($endpoint->does('Attean::API::Variable')) {
# SERVICE ?var
croak "SERVICE ?var not implemented";
} else {
# SERVICE <endpoint>
# no-op
my $service = Attean::Algebra::Service->new( children => [$pattern], endpoint => $endpoint, silent => $silent );
$self->_add_patterns( $service );
}
} elsif ($class =~ /Attean::Algebra::(Union|Graph|Join)$/) {
# no-op
} else {
croak 'Unrecognized GraphPattern: ' . $class;
}
}
sub _SubSelect_test {
my $self = shift;
return $self->_test_token(KEYWORD, 'SELECT');
}
sub _SubSelect {
my $self = shift;
my $pattern;
{
local($self->{namespaces}) = $self->{namespaces};
local($self->{_stack}) = [];
local($self->{filters}) = [];
local($self->{_pattern_container_stack}) = [];
my $triples = $self->_push_pattern_container();
local($self->{build}) = { triples => $triples};
if ($self->{baseURI}) {
$self->{build}{base} = $self->{baseURI};
}
$self->_expected_token(KEYWORD, 'SELECT');
if (my $t = $self->_optional_token(KEYWORD, qr/^(DISTINCT|REDUCED)/)) {
my $mod = $t->value;
$self->{build}{options}{lc($mod)} = 1;
}
my ($star, $exprs, $vars) = $self->__SelectVars;
my @exprs = @$exprs;
$self->_WhereClause;
$self->_SolutionModifier($vars);
if ($self->{build}{options}{orderby}) {
my $order = delete $self->{build}{options}{orderby};
my $pattern = pop(@{ $self->{build}{triples} });
my @order = @$order;
my @cmps;
foreach my $o (@order) {
my ($dir, $expr) = @$o;
my $asc = ($dir eq 'ASC');
push(@cmps, Attean::Algebra::Comparator->new(ascending => $asc, expression => $expr));
}
my $sort = Attean::Algebra::OrderBy->new( children => [$pattern], comparators => \@cmps );
push(@{ $self->{build}{triples} }, $sort);
}
if ($self->_optional_token(KEYWORD, 'VALUES')) {
my @vars;
my $parens = 0;
if ($self->_optional_token(LPAREN)) {
lib/AtteanX/Parser/SPARQL.pm view on Meta::CPAN
# Turn triple patterns into ground triples.
@d{ map { $_->value } @vars } = map { (blessed($_) and $_->does('Attean::API::TriplePattern')) ? $_->as_triple : $_ } @$row;
foreach my $k (keys %d) {
unless (blessed($d{$k})) {
delete $d{$k};
}
}
my $result = Attean::Result->new(bindings => \%d);
push(@vbs, $result);
}
my $table = Attean::Algebra::Table->new( variables => \@vars, rows => \@vbs );
$self->_add_stack( ['Attean::Algebra::Table', $table] );
}
sub _Bind {
my $self = shift;
$self->_expected_token(KEYWORD, 'BIND');
my ($var, $expr) = $self->_BrackettedAliasExpression;
$self->_add_stack( ['Attean::Algebra::Extend', $var, $expr] );
}
sub _Unfold {
my $self = shift;
$self->_expected_token(KEYWORD, 'UNFOLD');
my ($var, $expr) = $self->_BrackettedAliasExpression(1);
$self->_add_stack( ['Attean::Algebra::Unfold', $var, $expr] );
}
sub _Hint {
my $self = shift;
$self->_expected_token(KEYWORD, 'HINT');
my $terms = $self->_HintTerms();
$self->_add_hint($terms);
}
sub _HintTerms {
my $self = shift;
$self->_expected_token(LPAREN);
my @terms;
while ($self->_BindingValue_test) {
$self->_BindingValue;
push(@terms, splice(@{ $self->{_stack} }));
}
$self->_expected_token(RPAREN);
return \@terms;
}
sub _ServiceGraphPattern {
my $self = shift;
$self->_expected_token(KEYWORD, 'SERVICE');
my $silent = $self->_optional_token(KEYWORD, 'SILENT') ? 1 : 0;
$self->__close_bgp_with_filters;
if ($self->_test_token(VAR)) {
$self->_Var;
} else {
$self->_IRIref;
}
my ($endpoint) = splice( @{ $self->{_stack} } );
$self->_GroupGraphPattern;
my $ggp = $self->_remove_pattern;
my $opt = ['Attean::Algebra::Service', $endpoint, $ggp, ($silent ? 1 : 0)];
$self->_add_stack( $opt );
}
# [23] OptionalGraphPattern ::= 'OPTIONAL' GroupGraphPattern
# sub _OptionalGraphPattern_test {
# my $self = shift;
# return $self->_test_token(KEYWORD, 'OPTIONAL');
# }
sub __close_bgp_with_filters {
my $self = shift;
my @filters = splice(@{ $self->{filters} });
if (@filters) {
my ($cont, $hints) = $self->_pop_pattern_container;
my $ggp = $self->_new_join(@$cont);
$ggp->hints($hints);
$self->_push_pattern_container;
# my $ggp = $self->_remove_pattern();
unless ($ggp) {
$ggp = Attean::Algebra::BGP->new();
}
while (my $f = shift @filters) {
$ggp = Attean::Algebra::Filter->new( children => [$ggp], expression => $f );
}
$self->_add_patterns($ggp);
}
}
sub _OptionalGraphPattern {
my $self = shift;
$self->_expected_token(KEYWORD, 'OPTIONAL');
$self->__close_bgp_with_filters;
$self->_GroupGraphPattern;
my $ggp = $self->_remove_pattern;
my $opt = ['Attean::Algebra::LeftJoin', $ggp];
$self->_add_stack( $opt );
}
sub _MinusGraphPattern {
my $self = shift;
$self->_expected_token(KEYWORD, 'MINUS');
$self->__close_bgp_with_filters;
$self->_GroupGraphPattern;
my $ggp = $self->_remove_pattern;
my $opt = ['Attean::Algebra::Minus', $ggp];
$self->_add_stack( $opt );
}
# [24] GraphGraphPattern ::= 'GRAPH' VarOrIRIref GroupGraphPattern
sub _GraphGraphPattern {
my $self = shift;
if ($self->{__data_pattern}) {
if ($self->{__graph_nesting_level}++) {
croak "Syntax error: Nested named GRAPH blocks not allowed in data template.";
}
}
$self->_expected_token(KEYWORD, 'GRAPH');
( run in 0.576 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )