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 )