~ migrating to SPARQL graph pattern parse tree
authorEric Prud'hommeaux <bertails@w3.org>
Mon, 28 Dec 2009 11:45:54 -0500
changeset 75 82826db7819c
parent 74 462bd3ddfc3f
child 76 505042d3085e
~ migrating to SPARQL graph pattern parse tree
src/main/scala/RDB2RDFMain.scala
src/main/scala/SPARQL.scala
src/test/scala/SparqlTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Sun Dec 27 16:44:52 2009 -0800
+++ b/src/main/scala/RDB2RDFMain.scala	Mon Dec 28 11:45:54 2009 -0500
@@ -198,7 +198,7 @@
 
   def findVars(gp:GraphPattern):Set[Var] = {
     gp match {
-      case BasicGraphPattern(triplepatterns, filter:SparqlExpression) => {
+      case TriplesBlock(triplepatterns, filter:SparqlExpression) => {
 	/* Examine each triple, updating the compilation state. */
 	triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
       }
@@ -254,7 +254,7 @@
   def mapGraphPattern(db:DatabaseDesc, stateP:R2RState, gp:GraphPattern, pk:PrimaryKey, enforeForeignKeys:Boolean):R2RState = {
     var state = stateP
     gp match {
-      case BasicGraphPattern(triplepatterns, filter:SparqlExpression) => {
+      case TriplesBlock(triplepatterns, filter:SparqlExpression) => {
 	/* Examine each triple, updating the compilation state. */
 	triplepatterns.foreach(s => state = bindOnPredicate(db, state, s, pk, true))
 
--- a/src/main/scala/SPARQL.scala	Sun Dec 27 16:44:52 2009 -0800
+++ b/src/main/scala/SPARQL.scala	Mon Dec 28 11:45:54 2009 -0500
@@ -15,8 +15,13 @@
 case class SparqlAttributeList(attributelist:List[Var])
 
 sealed abstract class GraphPattern
-case class BasicGraphPattern(triplepatterns:List[TriplePattern], filter:SparqlExpression) extends GraphPattern
-case class GroupGraphPattern(gps:List[GraphPattern]) extends GraphPattern
+case class TriplesBlock(triplepatterns:List[TriplePattern], filter:SparqlExpression) extends GraphPattern
+case class TableConjunction(gps:List[GraphPattern]) extends GraphPattern
+case class TableDisjunction(gps:List[GraphPattern]) extends GraphPattern
+case class ParserTableFilter(expr:SparqlExpression) extends GraphPattern
+case class TableFilter(gp:GraphPattern, expr:SparqlExpression) extends GraphPattern
+case class OptionalGraphPattern(gp:GraphPattern) extends GraphPattern
+case class GraphGraphPattern(gp:GraphPattern) extends GraphPattern
 
 case class TriplePattern(s:S, p:P, o:O)
 case class ObjUri(stem:Stem, rel:Rel, attr:Attr, v:CellValue)
@@ -58,7 +63,7 @@
 case class Sparql() extends JavaTokenParsers {
 
   def select:Parser[SparqlSelect] =
-    "SELECT" ~ attributelist ~ "{" ~ graphpattern ~ "}" ^^ { case "SELECT"~a~"{"~t~"}" => SparqlSelect(a, t) }
+    "SELECT" ~ attributelist ~ groupgraphpattern ^^ { case "SELECT"~a~gp => SparqlSelect(a, gp) }
 
   def filter:Parser[SparqlExpression] =
     "FILTER" ~ "(" ~ expression ~ ")" ^^ { case "FILTER"~"("~expression~")" => expression }
@@ -83,24 +88,45 @@
   def attributelist:Parser[SparqlAttributeList] =
     rep(varr) ^^ { SparqlAttributeList(_) }
 
-  def graphpattern:Parser[GraphPattern] = (
-      // "{"~graphpattern~"}" ^^ { case "{"~x~"}" => GroupGraphPattern(List(x)) }
-      groupgraphpattern ^^ { ggp => ggp }
-    | basicgraphpattern ^^ { bgp => bgp }
+  def groupgraphpattern:Parser[GraphPattern] = (
+    "{" ~ opt(triplesblock) ~ rep(graphpatternnottriplesORfilter ~ opt(triplesblock)) ~ "}" ^^
+    //"{" ~ opt(triplesblock) ~ rep(graphpatternnottriplesORfilter_OPTtriplesblock) ~ "}" ^^
+    {
+      case "{"~tbOPT~gpntORf_tbOPT~"}" => {
+	val l:Option[GraphPattern] = tbOPT
+	val r:List[~[GraphPattern,Option[TriplesBlock]]] = gpntORf_tbOPT
+	(tbOPT, gpntORf_tbOPT) match {
+	  case (Some(x), list) => {
+	    if (list.size == 0)
+	      x
+	    else {
+	      println("ignoring " + list)
+	      TableConjunction(List[GraphPattern](x))
+	    }
+	  }
+	}
+      }
+    }
   )
 
-  def groupgraphpattern:Parser[GraphPattern] = (
-      "{"~graphpattern~"}" ^^ { case "{"~x~"}" => GroupGraphPattern(List(x)) }
+  def graphpatternnottriplesORfilter_OPTtriplesblock:Parser[(GraphPattern, Option[TriplesBlock])] =
+    graphpatternnottriplesORfilter ~ opt(triplesblock) ^^ { case a~b => (a, b) }
+
+  def graphpatternnottriplesORfilter:Parser[GraphPattern] = (
+      "OPTIONAL"~groupgraphpattern ^^ { case "OPTIONAL"~ggp => OptionalGraphPattern(ggp) }
+    | rep1sep(groupgraphpattern, "UNION") ^^ { x => if (x.size > 1) TableDisjunction(x) else x(0) }
+    | "GRAPH"~uri~groupgraphpattern ^^ { case "GRAPH"~u~ggp => GraphGraphPattern(ggp) }
+    | filter ^^ { x => ParserTableFilter(x) }
   )
 
-  def basicgraphpattern:Parser[BasicGraphPattern] =
+  def triplesblock:Parser[TriplesBlock] =
     repsep(triplepattern, ".") ~ opt(filter) ^^ {
       case pats~filter =>
 	val sparqlExpression:SparqlExpression = filter match {
 	  case None => SparqlExpression(List())
 	  case Some(f) => f
 	}
-      BasicGraphPattern(pats, sparqlExpression)
+      TriplesBlock(pats, sparqlExpression)
     }
 
   def triplepattern:Parser[TriplePattern] =
--- a/src/test/scala/SparqlTest.scala	Sun Dec 27 16:44:52 2009 -0800
+++ b/src/test/scala/SparqlTest.scala	Mon Dec 28 11:45:54 2009 -0500
@@ -10,8 +10,8 @@
     val e = """
 ?emp      <http://hr.example/DB/Employee#lastName>   "bob"^^<http://www.w3.org/2001/XMLSchema#string>
 """
-    val expected = BasicGraphPattern(List(TriplePattern(SVar(Var("emp")),PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("lastName")),OLit(SparqlLiteral(RDFLiteral("bob",Datatype(new URI("http://www.w3.org/2001/XMLSchema#string"))))))), SparqlExpression(List()))
-    assert(expected === (a.parseAll(a.basicgraphpattern, e).get))
+    val expected = TriplesBlock(List(TriplePattern(SVar(Var("emp")),PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("lastName")),OLit(SparqlLiteral(RDFLiteral("bob",Datatype(new URI("http://www.w3.org/2001/XMLSchema#string"))))))), SparqlExpression(List()))
+    assert(expected === (a.parseAll(a.triplesblock, e).get))
   }
 
   test("parse a litint") {
@@ -19,11 +19,11 @@
     val e = """
 ?emp      <http://hr.example/DB/Employee#age>   "21"^^<http://www.w3.org/2001/XMLSchema#integer>
 """
-    val expected = BasicGraphPattern(List(TriplePattern(SVar(Var("emp")),PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("age")),OLit(SparqlLiteral(RDFLiteral("21",Datatype(new URI("http://www.w3.org/2001/XMLSchema#integer"))))))), SparqlExpression(List()))
-    assert(expected === (a.parseAll(a.basicgraphpattern, e).get))
+    val expected = TriplesBlock(List(TriplePattern(SVar(Var("emp")),PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("age")),OLit(SparqlLiteral(RDFLiteral("21",Datatype(new URI("http://www.w3.org/2001/XMLSchema#integer"))))))), SparqlExpression(List()))
+    assert(expected === (a.parseAll(a.triplesblock, e).get))
   }
 
-  test("parse a basicgraphpattern") {
+  test("parse a triplesblock") {
     val a = Sparql()
     val e = """
 ?emp      <http://hr.example/DB/Employee#lastName>   ?empName .
@@ -31,7 +31,7 @@
 ?manager  <http://hr.example/DB/Employee#lastName>   ?managName
 """
     val tps =
-      BasicGraphPattern(
+      TriplesBlock(
 	List(
 	  TriplePattern(
 	    SVar(Var("emp")),
@@ -45,7 +45,7 @@
 	    SVar(Var("manager")),
 	    PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("lastName")),
 	    OVar(Var("managName")))), SparqlExpression(List()))
-    assert(tps === a.parseAll(a.basicgraphpattern, e).get)
+    assert(tps === a.parseAll(a.triplesblock, e).get)
   }
 
   // ?manBday < ?empBday && ?grandManBday < ?manBday
@@ -89,6 +89,25 @@
     assert(expected === (a.parseAll(a.filter, e).get))
   }
 
+  test("SELECT") {
+    val a = Sparql()
+    val e = """
+SELECT ?empName ?manageName {
+?emp      <http://hr.example/DB/Employee#lastName>   ?empName
+}
+"""
+    val tps =
+      SparqlSelect(
+	SparqlAttributeList(List(Var("empName"), Var("manageName"))),
+	TriplesBlock(
+	  List(
+	    TriplePattern(
+	      SVar(Var("emp")),
+		PUri(Stem("http://hr.example/DB"),Rel("Employee"),Attr("lastName")),
+	      OVar(Var("empName")))), SparqlExpression(List())))
+    assert(tps === a.parseAll(a.select, e).get)
+  }
+
   test("SELECT with FILTER") {
     val a = Sparql()
     val e = """
@@ -100,7 +119,7 @@
     val tps =
       SparqlSelect(
 	SparqlAttributeList(List(Var("empName"), Var("manageName"))),
-	BasicGraphPattern(
+	TriplesBlock(
 	  List(
 	    TriplePattern(
 	      SVar(Var("emp")),
@@ -126,7 +145,7 @@
     val tps =
       SparqlSelect(
 	SparqlAttributeList(List(Var("empName"), Var("manageName"))),
-	BasicGraphPattern(
+	TriplesBlock(
 	  List(
 	    TriplePattern(
 	      SVar(Var("emp")),