Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made changes for making the SPARQL* parser recursive #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions examples/sample.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix prop: <http://www.example.org/pragya/sweb/assignment4/netflix/OwlProperty/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix netflix: <http://www.example.org/pragya/sweb/assignment4/netflix#> .
@prefix class: <http://www.example.org/pragya/sweb/assignment4/OwlClass> .

prop:isListedIn rdfs:domain class:ShowId ;
rdfs:range class:Genre .

prop:isOfType rdfs:domain class:ShowId ;
rdfs:range class:Movie , class:TvShow .

class:TvShow a rdfs:Class .

class:Year a rdfs:Class ;
rdfs:subClassOf class:Date .

class:Movie a rdfs:Class .

prop:hasTitle rdfs:domain class:ShowId ;
rdfs:range xsd:String .

prop:hasCast rdfs:domain class:ShowId ;
rdfs:range class:Cast .

class:Duration a rdfs:Class .

class:ShowId a rdfs:Class .

class:Person a rdfs:Class .

class:Rating a rdfs:Class .

prop:hasDirector rdfs:domain class:ShowId ;
rdfs:range class:Director .

class:Director a rdfs:Class ;
rdfs:subClassOf class:Person .

class:Genre a rdfs:Class .

class:Country a rdfs:Class .

class:ReleaseYr a rdfs:Class ;
rdfs:subClassOf class:Year .

prop:releasedIn rdfs:domain class:ShowId ;
rdfs:range class:ReleaseYr .

class:Cast a rdfs:Class ;
rdfs:subClassOf class:Person .

prop:hasDescription rdfs:domain class:ShowId ;
rdfs:range xsd:String .

class:Date a rdfs:Class .

prop:madeInCountry rdfs:domain class:ShowId ;
rdfs:range class:Country .

<1> prop:hasTitle <K3G> .

prop:wasAddedOn rdfs:domain class:ShowId ;
rdfs:range class:Date .

owl:st rdf:type rdf:Statement;
rdf:subject owl:Par ;
rdf:predicate prop:livesInCountry ;
rdf:object <Japan> .
owl:st prop:releasedIn <2016> .

owl:Par rdf:type rdf:Statement;
rdf:subject <Story> ;
rdf:predicate prop:about ;
rdf:object <Bob> .

19 changes: 19 additions & 0 deletions examples/sparql_star_recursive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""

A simple example showing how to process RDFa from the web

"""

from rdflib import Graph

if __name__ == '__main__':
g = Graph()

g.parse('sample.ttl', format='turtle')

print("Books found:")

res = g.query("SELECT ?s1 WHERE{<<<<?s1 ?p1 ?o1>> ?p2 ?o2>> ?p3 ?o3.}")
print(list(res))


71 changes: 48 additions & 23 deletions rdflib/plugins/sparql/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,29 +118,38 @@ def evalUnion(ctx, union):
for x in evalPart(ctx, union.p2):
yield x

def _convert_embedded_triple(reif, t, v):
if t[0] == reif and t[2] == reif:
return v, t[1], v
elif t[0] == reif:
return v, t[1], t[2]
elif t[2] == reif:
return t[0], t[1], v
else:
return t
def _convert_embedded_triple(t):

if isinstance(t[0], EmbeddedTriple) and isinstance(t[2], EmbeddedTriple):
v1 = Variable('__' + t[0].toPython())
v2 = Variable('__' + t[2].toPython())
return v1, t[1], v2

if isinstance(t[0], EmbeddedTriple):
v1 = Variable('__' + t[0].toPython()) #Replacing subject by a variable if Embedded Triple
return v1, t[1], t[2]

if isinstance(t[2], EmbeddedTriple):
v3 = Variable('__' + t[2].toPython()) #Replacing object by a variable if Embedded Triple
return t[0], t[1], v3

# Embedded Triple Pattern
def reifyEmbTP(ctx, reif, part):
def reifyEmbTP(ctx, reif, triples):
from rdflib import RDF
v = Variable('__' + reif.toPython())
triples = list()
for t in part.triples:
triples.append(_convert_embedded_triple(reif, t, v))

triples.append([v, RDF.type, RDF.Statement])
triples.append([v, RDF.subject,reif.subject()])
triples.append([v, RDF.predicate, reif.predicate()])
triples.append([v, RDF.object, reif.object()])
part.triples = triples
if(isinstance(reif.subject() , EmbeddedTriple)):
triples.append([v, RDF.subject, Variable('__' +reif.subject().toPython())])
else:
triples.append([v, RDF.subject,reif.subject()])

if (isinstance(reif.object(), EmbeddedTriple)):
triples.append([v, RDF.object, Variable('__' + reif.object().toPython())])
else:
triples.append([v, RDF.object, reif.object()])


def evalMinus(ctx, minus):
a = evalPart(ctx, minus.p1)
Expand Down Expand Up @@ -228,14 +237,25 @@ def evalMultiset(ctx, part):
return evalPart(ctx, part.p)


def findSetOfEmbeddedTriples(ctx, part):
setOfEmbededTriples=set()
for t in part.triples:
def findSetOfEmbeddedTriples(ctx, triples,setOfEmbededTriples):
subTriples = []
for t in triples:
if isinstance(t[0], EmbeddedTriple) and t[0] not in setOfEmbededTriples:
setOfEmbededTriples.add(t[0])

embTpl = []
embTpl.extend([t[0].subject(),t[0].predicate(),t[0].object()])
subTriples.append(embTpl)

if isinstance(t[2], EmbeddedTriple) and t[2] not in setOfEmbededTriples:
setOfEmbededTriples.add(t[2])
return setOfEmbededTriples

embTpl = []
embTpl.extend([t[2].subject(), t[2].predicate(), t[2].object()])
subTriples.append(embTpl)

if(len(subTriples)>0) :
findSetOfEmbeddedTriples(ctx, subTriples, setOfEmbededTriples)

def evalPart(ctx, part):

Expand All @@ -247,14 +267,19 @@ def evalPart(ctx, part):
pass # the given custome-function did not handle this part

if part.name == 'BGP':
set_of_embeded_triples = findSetOfEmbeddedTriples(ctx, part)
set_of_embeded_triples = set()
findSetOfEmbeddedTriples(ctx, part.triples, set_of_embeded_triples)

# Reorder triples patterns by number of bound nodes in the current ctx
# Do patterns with more bound nodes first
triples = list()
for t in part.triples:
triples.append(_convert_embedded_triple(t))

if len(set_of_embeded_triples) != 0:
for embTp in set_of_embeded_triples:
reifyEmbTP(ctx, embTp, part)
reifyEmbTP(ctx, embTp, triples)
part.triples = triples
triples = sorted(part.triples, key=lambda t: len([n for n in t if ctx[n] is None]))
return evalBGP(ctx, triples)
elif part.name == 'Filter':
Expand Down Expand Up @@ -488,4 +513,4 @@ def evalQuery(graph, query, initBindings, base=None):
g = d.named
ctx.load(g, default=False)

return evalPart(ctx, main)
return evalPart(ctx, main)
14 changes: 7 additions & 7 deletions rdflib/plugins/sparql/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,13 @@ def _hexExpand(match):
'DEFAULT')) | Optional(Keyword('GRAPH')) + ParamList('graph', iri)

# Inside a values clause the EmbeddedTriple must be fully resolvable.
KnownEmbTP = Suppress('<<') + iri + (iri | A) + (iri | RDFLiteral | NumericLiteral | BooleanLiteral) + Suppress('>>')
KnownEmbTP = Forward()
KnownEmbTP <<= Suppress('<<') + (iri | KnownEmbTP) + (iri | A) + (iri | RDFLiteral | NumericLiteral | BooleanLiteral | KnownEmbTP) + Suppress('>>')
KnownEmbTP.setParseAction(lambda x:
rdflib.EmbeddedTriple(subject=x[0],
predicate=x[1],
object=x[2]))


# [65] DataBlockValue ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
DataBlockValue = iri | RDFLiteral | NumericLiteral | BooleanLiteral | Keyword('UNDEF') | KnownEmbTP

Expand All @@ -439,16 +439,16 @@ def _hexExpand(match):
GraphNode = VarOrTerm | TriplesNode

#Should be recursive but it is not yet so
#VarOrBlankNodeOrIriOrLitOrEmbTP = Forward()
#VarOrBlankNodeOrIriOrLitOrEmbTP <<= Var | BlankNode | iri | RDFLiteral | NumericLiteral | BooleanLiteral | VarOrBlankNodeOrIriOrLitOrEmbTP
# VarOrBlankNodeOrIriOrLitOrEmbTP = Forward()
# VarOrBlankNodeOrIriOrLitOrEmbTP <<= Var | BlankNode | iri | RDFLiteral | NumericLiteral | BooleanLiteral | VarOrBlankNodeOrIriOrLitOrEmbTP
VarOrBlankNodeOrIriOrLitOrEmbTP = Var | BlankNode | iri | RDFLiteral | NumericLiteral | BooleanLiteral

EmbTP = Suppress('<<') + VarOrBlankNodeOrIriOrLitOrEmbTP + Verb + VarOrBlankNodeOrIriOrLitOrEmbTP + Suppress('>>')
EmbTP = Forward()
EmbTP <<= Suppress('<<') + (VarOrBlankNodeOrIriOrLitOrEmbTP|EmbTP) + Verb + (VarOrBlankNodeOrIriOrLitOrEmbTP|EmbTP) + Suppress('>>')
EmbTP.setParseAction(lambda x:
rdflib.EmbeddedTriple(subject=x[0],
predicate=x[1],
object=x[2])
)
object=x[2]))

VarOrTermOrEmbTP = Var | GraphTerm | EmbTP

Expand Down