sparql 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -6
- data/VERSION +1 -1
- data/lib/sparql/algebra/expression.rb +28 -2
- data/lib/sparql/algebra/extensions.rb +73 -0
- data/lib/sparql/algebra/operator.rb +73 -9
- data/lib/sparql/algebra/operator/alt.rb +58 -0
- data/lib/sparql/algebra/operator/extend.rb +15 -3
- data/lib/sparql/algebra/operator/filter.rb +18 -1
- data/lib/sparql/algebra/operator/group.rb +22 -1
- data/lib/sparql/algebra/operator/join.rb +16 -5
- data/lib/sparql/algebra/operator/left_join.rb +12 -1
- data/lib/sparql/algebra/operator/notin.rb +1 -1
- data/lib/sparql/algebra/operator/notoneof.rb +52 -0
- data/lib/sparql/algebra/operator/path.rb +49 -0
- data/lib/sparql/algebra/operator/path_opt.rb +112 -0
- data/lib/sparql/algebra/operator/path_plus.rb +99 -0
- data/lib/sparql/algebra/operator/path_star.rb +42 -0
- data/lib/sparql/algebra/operator/reverse.rb +54 -0
- data/lib/sparql/algebra/operator/seq.rb +73 -0
- data/lib/sparql/algebra/operator/sequence.rb +63 -0
- data/lib/sparql/algebra/operator/union.rb +12 -1
- data/lib/sparql/algebra/query.rb +1 -0
- data/lib/sparql/grammar/meta.rb +4593 -4582
- data/lib/sparql/grammar/parser11.rb +301 -107
- metadata +13 -4
| @@ -55,17 +55,17 @@ module SPARQL::Grammar | |
| 55 55 |  | 
| 56 56 | 
             
                # Terminals passed to lexer. Order matters!
         | 
| 57 57 | 
             
                terminal(:ANON,                 ANON) do |prod, token, input|
         | 
| 58 | 
            -
                   | 
| 58 | 
            +
                  input[:BlankNode] = bnode
         | 
| 59 59 | 
             
                end
         | 
| 60 60 | 
             
                terminal(:NIL,                  NIL) do |prod, token, input|
         | 
| 61 | 
            -
                   | 
| 61 | 
            +
                  input[:NIL] = RDF['nil']
         | 
| 62 62 | 
             
                end
         | 
| 63 63 | 
             
                terminal(:BLANK_NODE_LABEL,     BLANK_NODE_LABEL) do |prod, token, input|
         | 
| 64 | 
            -
                   | 
| 64 | 
            +
                  input[:BlankNode] = bnode(token.value[2..-1])
         | 
| 65 65 | 
             
                end
         | 
| 66 66 | 
             
                terminal(:IRIREF,               IRIREF, unescape: true) do |prod, token, input|
         | 
| 67 67 | 
             
                  begin
         | 
| 68 | 
            -
                     | 
| 68 | 
            +
                    input[:iri] = iri(token.value[1..-2])
         | 
| 69 69 | 
             
                  rescue ArgumentError => e
         | 
| 70 70 | 
             
                    raise Error, e.message
         | 
| 71 71 | 
             
                  end
         | 
| @@ -74,75 +74,74 @@ module SPARQL::Grammar | |
| 74 74 | 
             
                  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
         | 
| 75 75 | 
             
                  # zero if necessary
         | 
| 76 76 | 
             
                  value = token.value.sub(/\.([eE])/, '.0\1')
         | 
| 77 | 
            -
                   | 
| 77 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.double)
         | 
| 78 78 | 
             
                end
         | 
| 79 79 | 
             
                terminal(:DECIMAL_POSITIVE,     DECIMAL_POSITIVE) do |prod, token, input|
         | 
| 80 80 | 
             
                  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
         | 
| 81 81 | 
             
                  # zero if necessary
         | 
| 82 82 | 
             
                  value = token.value
         | 
| 83 83 | 
             
                  value = "0#{token.value}" if token.value[0,1] == "."
         | 
| 84 | 
            -
                   | 
| 84 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.decimal)
         | 
| 85 85 | 
             
                end
         | 
| 86 86 | 
             
                terminal(:INTEGER_POSITIVE,     INTEGER_POSITIVE) do |prod, token, input|
         | 
| 87 | 
            -
                   | 
| 87 | 
            +
                  input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
         | 
| 88 88 | 
             
                end
         | 
| 89 89 | 
             
                terminal(:DOUBLE_NEGATIVE,      DOUBLE_NEGATIVE) do |prod, token, input|
         | 
| 90 90 | 
             
                  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
         | 
| 91 91 | 
             
                  # zero if necessary
         | 
| 92 92 | 
             
                  value = token.value.sub(/\.([eE])/, '.0\1')
         | 
| 93 | 
            -
                   | 
| 93 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.double)
         | 
| 94 94 | 
             
                end
         | 
| 95 95 | 
             
                terminal(:DECIMAL_NEGATIVE,     DECIMAL_NEGATIVE) do |prod, token, input|
         | 
| 96 96 | 
             
                  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
         | 
| 97 97 | 
             
                  # zero if necessary
         | 
| 98 98 | 
             
                  value = token.value
         | 
| 99 99 | 
             
                  value = "0#{token.value}" if token.value[0,1] == "."
         | 
| 100 | 
            -
                   | 
| 100 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.decimal)
         | 
| 101 101 | 
             
                end
         | 
| 102 102 | 
             
                terminal(:INTEGER_NEGATIVE,     INTEGER_NEGATIVE) do |prod, token, input|
         | 
| 103 | 
            -
                   | 
| 103 | 
            +
                  input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
         | 
| 104 104 | 
             
                end
         | 
| 105 105 | 
             
                terminal(:DOUBLE,               DOUBLE) do |prod, token, input|
         | 
| 106 106 | 
             
                  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
         | 
| 107 107 | 
             
                  # zero if necessary
         | 
| 108 108 | 
             
                  value = token.value.sub(/\.([eE])/, '.0\1')
         | 
| 109 | 
            -
                   | 
| 109 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.double)
         | 
| 110 110 | 
             
                end
         | 
| 111 111 | 
             
                terminal(:DECIMAL,              DECIMAL) do |prod, token, input|
         | 
| 112 112 | 
             
                  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
         | 
| 113 113 | 
             
                  # zero if necessary
         | 
| 114 114 | 
             
                  value = token.value
         | 
| 115 115 | 
             
                  #value = "0#{token.value}" if token.value[0,1] == "."
         | 
| 116 | 
            -
                   | 
| 116 | 
            +
                  input[:literal] = literal(value, datatype: RDF::XSD.decimal)
         | 
| 117 117 | 
             
                end
         | 
| 118 118 | 
             
                terminal(:INTEGER,              INTEGER) do |prod, token, input|
         | 
| 119 | 
            -
                   | 
| 119 | 
            +
                  input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
         | 
| 120 120 | 
             
                end
         | 
| 121 121 | 
             
                terminal(:LANGTAG,              LANGTAG) do |prod, token, input|
         | 
| 122 122 | 
             
                  add_prod_datum(:language, token.value[1..-1])
         | 
| 123 123 | 
             
                end
         | 
| 124 124 | 
             
                terminal(:PNAME_LN,             PNAME_LN, unescape: true) do |prod, token, input|
         | 
| 125 125 | 
             
                  prefix, suffix = token.value.split(":", 2)
         | 
| 126 | 
            -
                   | 
| 126 | 
            +
                  input[:iri] = ns(prefix, suffix)
         | 
| 127 127 | 
             
                end
         | 
| 128 128 | 
             
                terminal(:PNAME_NS,             PNAME_NS) do |prod, token, input|
         | 
| 129 129 | 
             
                  prefix = token.value[0..-2]
         | 
| 130 130 | 
             
                  # [68] PrefixedName ::= PNAME_LN | PNAME_NS
         | 
| 131 | 
            -
                   | 
| 132 | 
            -
                   | 
| 133 | 
            -
                  add_prod_datum(:prefix, prefix && prefix.to_sym)
         | 
| 131 | 
            +
                  input[:iri] = ns(prefix, nil)
         | 
| 132 | 
            +
                  input[:prefix] = prefix && prefix.to_sym
         | 
| 134 133 | 
             
                end
         | 
| 135 134 | 
             
                terminal(:STRING_LITERAL_LONG1, STRING_LITERAL_LONG1, unescape: true) do |prod, token, input|
         | 
| 136 | 
            -
                   | 
| 135 | 
            +
                  input[:string] = token.value[3..-4]
         | 
| 137 136 | 
             
                end
         | 
| 138 137 | 
             
                terminal(:STRING_LITERAL_LONG2, STRING_LITERAL_LONG2, unescape: true) do |prod, token, input|
         | 
| 139 | 
            -
                   | 
| 138 | 
            +
                  input[:string] = token.value[3..-4]
         | 
| 140 139 | 
             
                end
         | 
| 141 140 | 
             
                terminal(:STRING_LITERAL1,      STRING_LITERAL1, unescape: true) do |prod, token, input|
         | 
| 142 | 
            -
                   | 
| 141 | 
            +
                  input[:string] = token.value[1..-2]
         | 
| 143 142 | 
             
                end
         | 
| 144 143 | 
             
                terminal(:STRING_LITERAL2,      STRING_LITERAL2, unescape: true) do |prod, token, input|
         | 
| 145 | 
            -
                   | 
| 144 | 
            +
                  input[:string] = token.value[1..-2]
         | 
| 146 145 | 
             
                end
         | 
| 147 146 | 
             
                terminal(:VAR1,                 VAR1) do |prod, token, input|
         | 
| 148 147 | 
             
                  add_prod_datum(:Var, variable(token.value[1..-1]))
         | 
| @@ -160,19 +159,23 @@ module SPARQL::Grammar | |
| 160 159 | 
             
                      add_prod_datum(:AdditiveExpression, token.value)
         | 
| 161 160 | 
             
                    when :_UnaryExpression_2, :_UnaryExpression_3
         | 
| 162 161 | 
             
                      add_prod_datum(:UnaryExpression, token.value)
         | 
| 162 | 
            +
                    when :PathMod
         | 
| 163 | 
            +
                      add_prod_datum(:PathMod, token.value)
         | 
| 163 164 | 
             
                    else
         | 
| 164 165 | 
             
                      raise "Unexpected production #{prod} for #{token}"
         | 
| 165 166 | 
             
                    end
         | 
| 167 | 
            +
                  when '?'             then add_prod_datum(:PathMod, token.value)
         | 
| 168 | 
            +
                  when '^'             then input[:reverse] = token.value
         | 
| 166 169 | 
             
                  when '*', '/'        then add_prod_datum(:MultiplicativeExpression, token.value)
         | 
| 167 170 | 
             
                  when '=', '!=', '<',
         | 
| 168 171 | 
             
                       '>', '<=', '>=' then add_prod_datum(:RelationalExpression, token.value)
         | 
| 169 172 | 
             
                  when '&&'            then add_prod_datum(:ConditionalAndExpression, token.value)
         | 
| 170 173 | 
             
                  when '||'            then add_prod_datum(:ConditionalOrExpression, token.value)
         | 
| 171 174 | 
             
                  when '!'             then add_prod_datum(:UnaryExpression, token.value)
         | 
| 172 | 
            -
                  when 'a'             then  | 
| 173 | 
            -
                  when /true|false/    then  | 
| 174 | 
            -
                  when /ASC|DESC/      then  | 
| 175 | 
            -
                  when /DISTINCT|REDUCED/  then  | 
| 175 | 
            +
                  when 'a'             then input[:Verb] = (a = RDF.type.dup; a.lexical = 'a'; a)
         | 
| 176 | 
            +
                  when /true|false/    then input[:literal] = RDF::Literal::Boolean.new(token.value.downcase)
         | 
| 177 | 
            +
                  when /ASC|DESC/      then input[:OrderDirection] = token.value.downcase.to_sym
         | 
| 178 | 
            +
                  when /DISTINCT|REDUCED/  then input[:DISTINCT_REDUCED] = token.value.downcase.to_sym
         | 
| 176 179 | 
             
                  when %r{
         | 
| 177 180 | 
             
                      ABS|ALL|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
         | 
| 178 181 | 
             
                     |CONTAINS|COUNT|DATATYPE|DAY|DEFAULT|ENCODE_FOR_URI|EXISTS
         | 
| @@ -220,7 +223,7 @@ module SPARQL::Grammar | |
| 220 223 |  | 
| 221 224 | 
             
                # [5]  	BaseDecl	  ::=  	'BASE' IRI_REF
         | 
| 222 225 | 
             
                production(:BaseDecl) do |input, data, callback|
         | 
| 223 | 
            -
                  iri = data[:iri] | 
| 226 | 
            +
                  iri = data[:iri]
         | 
| 224 227 | 
             
                  debug("BaseDecl") {"Defined base as #{iri}"}
         | 
| 225 228 | 
             
                  self.base_uri = iri(iri)
         | 
| 226 229 | 
             
                  add_prod_datum(:BaseDecl, iri) unless resolve_iris?
         | 
| @@ -229,14 +232,14 @@ module SPARQL::Grammar | |
| 229 232 | 
             
                # [6] PrefixDecl	  ::=  	'PREFIX' PNAME_NS IRI_REF
         | 
| 230 233 | 
             
                production(:PrefixDecl) do |input, data, callback|
         | 
| 231 234 | 
             
                  if data[:iri]
         | 
| 232 | 
            -
                    pfx = data[:prefix] | 
| 233 | 
            -
                    self.prefix(pfx, data[:iri] | 
| 234 | 
            -
                    prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, data[:iri] | 
| 235 | 
            +
                    pfx = data[:prefix]
         | 
| 236 | 
            +
                    self.prefix(pfx, data[:iri])
         | 
| 237 | 
            +
                    prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, data[:iri]]], [])
         | 
| 235 238 | 
             
                    add_prod_datum(:PrefixDecl, prefix_op)
         | 
| 236 239 | 
             
                  end
         | 
| 237 240 | 
             
                end
         | 
| 238 241 |  | 
| 239 | 
            -
                # [7]  	SelectQuery	  ::=  	SelectClause DatasetClause* WhereClause SolutionModifier | 
| 242 | 
            +
                # [7]  	SelectQuery	  ::=  	SelectClause DatasetClause* WhereClause SolutionModifier
         | 
| 240 243 | 
             
                production(:SelectQuery) do |input, data, callback|
         | 
| 241 244 | 
             
                  query = merge_modifiers(data)
         | 
| 242 245 | 
             
                  add_prod_datum :query, query
         | 
| @@ -263,7 +266,6 @@ module SPARQL::Grammar | |
| 263 266 | 
             
                #                            'WHERE' '{' TriplesTemplate? '}'
         | 
| 264 267 | 
             
                #                            SolutionModifier
         | 
| 265 268 | 
             
                #                          )
         | 
| 266 | 
            -
                #                          ValuesClause
         | 
| 267 269 | 
             
                production(:ConstructQuery) do |input, data, callback|
         | 
| 268 270 | 
             
                  data[:query] ||= [SPARQL::Algebra::Operator::BGP.new(*data[:pattern])]
         | 
| 269 271 | 
             
                  query = merge_modifiers(data)
         | 
| @@ -272,14 +274,14 @@ module SPARQL::Grammar | |
| 272 274 | 
             
                end
         | 
| 273 275 |  | 
| 274 276 | 
             
                # [11]  	DescribeQuery	  ::=  	'DESCRIBE' ( VarOrIri+ | '*' )
         | 
| 275 | 
            -
                #                             DatasetClause* WhereClause? SolutionModifier | 
| 277 | 
            +
                #                             DatasetClause* WhereClause? SolutionModifier
         | 
| 276 278 | 
             
                production(:DescribeQuery) do |input, data, callback|
         | 
| 277 279 | 
             
                  query = merge_modifiers(data)
         | 
| 278 | 
            -
                  to_describe = data[:VarOrIri] | 
| 280 | 
            +
                  to_describe = Array(data[:VarOrIri])
         | 
| 279 281 | 
             
                  add_prod_datum :query, SPARQL::Algebra::Expression[:describe, to_describe, query]
         | 
| 280 282 | 
             
                end
         | 
| 281 283 |  | 
| 282 | 
            -
                # [12]  	AskQuery	  ::=  	'ASK' DatasetClause* WhereClause | 
| 284 | 
            +
                # [12]  	AskQuery	  ::=  	'ASK' DatasetClause* WhereClause
         | 
| 283 285 | 
             
                production(:AskQuery) do |input, data, callback|
         | 
| 284 286 | 
             
                  query = merge_modifiers(data)
         | 
| 285 287 | 
             
                  add_prod_datum :query, SPARQL::Algebra::Expression[:ask, query]
         | 
| @@ -292,7 +294,7 @@ module SPARQL::Grammar | |
| 292 294 |  | 
| 293 295 | 
             
                # [15]  	NamedGraphClause	  ::=  	'NAMED' SourceSelector
         | 
| 294 296 | 
             
                production(:NamedGraphClause) do |input, data, callback|
         | 
| 295 | 
            -
                  add_prod_data :dataset, data[:iri] | 
| 297 | 
            +
                  add_prod_data :dataset, [:named, data[:iri]]
         | 
| 296 298 | 
             
                end
         | 
| 297 299 |  | 
| 298 300 | 
             
                # [18]  	SolutionModifier	  ::=  	GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
         | 
| @@ -336,7 +338,7 @@ module SPARQL::Grammar | |
| 336 338 | 
             
                #                               | ( Constraint | Var )
         | 
| 337 339 | 
             
                production(:OrderCondition) do |input, data, callback|
         | 
| 338 340 | 
             
                  if data[:OrderDirection]
         | 
| 339 | 
            -
                    add_prod_datum(:OrderCondition, SPARQL::Algebra::Expression | 
| 341 | 
            +
                    add_prod_datum(:OrderCondition, SPARQL::Algebra::Expression(data[:OrderDirection], *data[:Expression]))
         | 
| 340 342 | 
             
                  else
         | 
| 341 343 | 
             
                    add_prod_datum(:OrderCondition, data[:Constraint] || data[:Var])
         | 
| 342 344 | 
             
                  end
         | 
| @@ -367,7 +369,7 @@ module SPARQL::Grammar | |
| 367 369 | 
             
                  debug("ValuesClause") {"vars: #{data[:Var].inspect}, row: #{data[:row].inspect}"}
         | 
| 368 370 | 
             
                  if data[:row]
         | 
| 369 371 | 
             
                    add_prod_datum :ValuesClause, SPARQL::Algebra::Expression.for(:table,
         | 
| 370 | 
            -
                      data[:Var]. | 
| 372 | 
            +
                      Array(data[:Var]).unshift(:vars),
         | 
| 371 373 | 
             
                      *data[:row]
         | 
| 372 374 | 
             
                    )
         | 
| 373 375 | 
             
                  else
         | 
| @@ -413,9 +415,13 @@ module SPARQL::Grammar | |
| 413 415 | 
             
                production(:Load) do |input, data, callback|
         | 
| 414 416 | 
             
                  args = []
         | 
| 415 417 | 
             
                  args << :silent if data[:silent]
         | 
| 416 | 
            -
                  args  | 
| 418 | 
            +
                  args << data[:iri]
         | 
| 419 | 
            +
                  args << data[:into] if data[:into]
         | 
| 417 420 | 
             
                  input[:update_op] = SPARQL::Algebra::Expression(:load, *args)
         | 
| 418 421 | 
             
                end
         | 
| 422 | 
            +
                production(:_Load_2) do |input, data, callback|
         | 
| 423 | 
            +
                  input[:into] = data[:iri]
         | 
| 424 | 
            +
                end
         | 
| 419 425 |  | 
| 420 426 | 
             
                # [32]	Clear	::=	"CLEAR" "SILENT"? GraphRefAll
         | 
| 421 427 | 
             
                production(:Clear) do |input, data, callback|
         | 
| @@ -496,7 +502,7 @@ module SPARQL::Grammar | |
| 496 502 | 
             
                  query = data[:query].first if data[:query]
         | 
| 497 503 | 
             
                  query = SPARQL::Algebra::Expression.for(:using, data[:using], query) if data[:using]
         | 
| 498 504 | 
             
                  operands = [query, data[:delete], data[:insert]].compact
         | 
| 499 | 
            -
                  operands = [SPARQL::Algebra::Expression.for(:with, data[:iri] | 
| 505 | 
            +
                  operands = [SPARQL::Algebra::Expression.for(:with, data[:iri], *operands)] if data[:iri]
         | 
| 500 506 | 
             
                  input[:update_op] = SPARQL::Algebra::Expression(:modify, *operands)
         | 
| 501 507 | 
             
                end
         | 
| 502 508 |  | 
| @@ -518,10 +524,10 @@ module SPARQL::Grammar | |
| 518 524 |  | 
| 519 525 | 
             
                # [44]	UsingClause	::=	"USING" ( iri | "NAMED" iri)
         | 
| 520 526 | 
             
                production(:UsingClause) do |input, data, callback|
         | 
| 521 | 
            -
                  add_prod_data(:using, data[:iri] | 
| 527 | 
            +
                  add_prod_data(:using, data[:iri])
         | 
| 522 528 | 
             
                end
         | 
| 523 529 | 
             
                production(:_UsingClause_2) do |input, data, callback|
         | 
| 524 | 
            -
                   | 
| 530 | 
            +
                  input[:iri] = [:named, data[:iri]]
         | 
| 525 531 | 
             
                end
         | 
| 526 532 |  | 
| 527 533 | 
             
                # [45]	GraphOrDefault	::=	"DEFAULT" | "GRAPH"? iri
         | 
| @@ -529,18 +535,14 @@ module SPARQL::Grammar | |
| 529 535 | 
             
                  if data[:default]
         | 
| 530 536 | 
             
                    add_prod_datum(:GraphOrDefault, :default)
         | 
| 531 537 | 
             
                  else
         | 
| 532 | 
            -
                    add_prod_data(:GraphOrDefault, data[:iri] | 
| 538 | 
            +
                    add_prod_data(:GraphOrDefault, data[:iri])
         | 
| 533 539 | 
             
                  end
         | 
| 534 540 | 
             
                end
         | 
| 535 541 |  | 
| 536 542 | 
             
                # [46]	GraphRef	::=	"GRAPH" iri
         | 
| 537 543 | 
             
                production(:GraphRef) do |input, data, callback|
         | 
| 538 | 
            -
                   | 
| 544 | 
            +
                  input[:iri] = data[:iri]
         | 
| 539 545 | 
             
                end
         | 
| 540 | 
            -
                # [47]	GraphRefAll	::=	GraphRef | "DEFAULT" | "NAMED" | "ALL"
         | 
| 541 | 
            -
                #production(:GraphRefAll) do |input, data, callback|
         | 
| 542 | 
            -
                #  add_prod_datum(:GraphRefAll, data)
         | 
| 543 | 
            -
                #end
         | 
| 544 546 |  | 
| 545 547 | 
             
                # [49]	QuadData	::=	"{" Quads "}"
         | 
| 546 548 | 
             
                # QuadData is like QuadPattern, except without BNodes
         | 
| @@ -584,15 +586,19 @@ module SPARQL::Grammar | |
| 584 586 | 
             
                # [55]  	TriplesBlock	  ::=  	TriplesSameSubjectPath
         | 
| 585 587 | 
             
                #                               ( '.' TriplesBlock? )?
         | 
| 586 588 | 
             
                production(:TriplesBlock) do |input, data, callback|
         | 
| 587 | 
            -
                   | 
| 588 | 
            -
             | 
| 589 | 
            -
             | 
| 590 | 
            -
             | 
| 591 | 
            -
             | 
| 592 | 
            -
             | 
| 593 | 
            -
                     | 
| 589 | 
            +
                  if data[:pattern]
         | 
| 590 | 
            +
                    query = SPARQL::Algebra::Operator::BGP.new
         | 
| 591 | 
            +
                    Array(data[:pattern]).each {|p| query << p}
         | 
| 592 | 
            +
             | 
| 593 | 
            +
                    # Append triples from ('.' TriplesBlock? )?
         | 
| 594 | 
            +
                    Array(data[:query]).each {|q| query += q}
         | 
| 595 | 
            +
                    if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
         | 
| 596 | 
            +
                      query = SPARQL::Algebra::Expression.for(:join, lhs, query)
         | 
| 597 | 
            +
                    end
         | 
| 598 | 
            +
                    add_prod_datum(:query, query)
         | 
| 599 | 
            +
                  else
         | 
| 600 | 
            +
                    add_prod_datum(:query, data[:path])
         | 
| 594 601 | 
             
                  end
         | 
| 595 | 
            -
                  add_prod_datum(:query, query)
         | 
| 596 602 | 
             
                end
         | 
| 597 603 |  | 
| 598 604 | 
             
                # [56]  	GraphPatternNotTriples	  ::=  	GroupOrUnionGraphPattern
         | 
| @@ -684,10 +690,10 @@ module SPARQL::Grammar | |
| 684 690 | 
             
                  vars = data[:Var]
         | 
| 685 691 | 
             
                  add_prod_datum :Var, vars
         | 
| 686 692 |  | 
| 687 | 
            -
                  if data[: | 
| 693 | 
            +
                  if data[:nilrow]
         | 
| 688 694 | 
             
                    add_prod_data :row, [:row]
         | 
| 689 695 | 
             
                  else
         | 
| 690 | 
            -
                    data[: | 
| 696 | 
            +
                    Array(data[:rowdata]).each do |ds|
         | 
| 691 697 | 
             
                      r = [:row]
         | 
| 692 698 | 
             
                      ds.each_with_index do |d, i|
         | 
| 693 699 | 
             
                        r << [vars[i], d] if d
         | 
| @@ -697,9 +703,13 @@ module SPARQL::Grammar | |
| 697 703 | 
             
                  end
         | 
| 698 704 | 
             
                end
         | 
| 699 705 |  | 
| 700 | 
            -
                #  | 
| 701 | 
            -
                production(: | 
| 702 | 
            -
                   | 
| 706 | 
            +
                # _InlineDataFull_6	        ::=  '(' '(' DataBlockValue* ')' | NIL ')'
         | 
| 707 | 
            +
                production(:_InlineDataFull_6) do |input, data, callback|
         | 
| 708 | 
            +
                  if data[:DataBlockValue]
         | 
| 709 | 
            +
                    add_prod_data :rowdata, data[:DataBlockValue].map {|v| v unless v == :undef}
         | 
| 710 | 
            +
                  else
         | 
| 711 | 
            +
                    input[:nilrow] = true
         | 
| 712 | 
            +
                  end
         | 
| 703 713 | 
             
                end
         | 
| 704 714 |  | 
| 705 715 | 
             
                # [65]  DataBlockValue	        ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
         | 
| @@ -716,7 +726,7 @@ module SPARQL::Grammar | |
| 716 726 | 
             
                # [67]  	GroupOrUnionGraphPattern	  ::=  	GroupGraphPattern
         | 
| 717 727 | 
             
                #                                           ( 'UNION' GroupGraphPattern )*
         | 
| 718 728 | 
             
                production(:GroupOrUnionGraphPattern) do |input, data, callback|
         | 
| 719 | 
            -
                  res = data[:query]. | 
| 729 | 
            +
                  res = Array(data[:query]).first
         | 
| 720 730 | 
             
                  if data[:union]
         | 
| 721 731 | 
             
                    while !data[:union].empty?
         | 
| 722 732 | 
             
                      # Join union patterns together as Union operators
         | 
| @@ -731,7 +741,7 @@ module SPARQL::Grammar | |
| 731 741 |  | 
| 732 742 | 
             
                # ( 'UNION' GroupGraphPattern )*
         | 
| 733 743 | 
             
                production(:_GroupOrUnionGraphPattern_1) do |input, data, callback|
         | 
| 734 | 
            -
                  input[:union] = data[:union]. | 
| 744 | 
            +
                  input[:union] = Array(data[:union]).unshift(data[:query].first)
         | 
| 735 745 | 
             
                end
         | 
| 736 746 |  | 
| 737 747 | 
             
                # [68]  	Filter	  ::=  	'FILTER' Constraint
         | 
| @@ -744,7 +754,7 @@ module SPARQL::Grammar | |
| 744 754 | 
             
                production(:Constraint) do |input, data, callback|
         | 
| 745 755 | 
             
                  if data[:Expression]
         | 
| 746 756 | 
             
                    # Resolve expression to the point it is either an atom or an s-exp
         | 
| 747 | 
            -
                    add_prod_data(:Constraint, data[:Expression]. | 
| 757 | 
            +
                    add_prod_data(:Constraint, Array(data[:Expression]).first)
         | 
| 748 758 | 
             
                  elsif data[:BuiltInCall]
         | 
| 749 759 | 
             
                    add_prod_datum(:Constraint, data[:BuiltInCall])
         | 
| 750 760 | 
             
                  elsif data[:Function]
         | 
| @@ -754,7 +764,7 @@ module SPARQL::Grammar | |
| 754 764 |  | 
| 755 765 | 
             
                # [70]  	FunctionCall	  ::=  	iri ArgList
         | 
| 756 766 | 
             
                production(:FunctionCall) do |input, data, callback|
         | 
| 757 | 
            -
                  add_prod_data(:Function, data[:iri] + data[:ArgList])
         | 
| 767 | 
            +
                  add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
         | 
| 758 768 | 
             
                end
         | 
| 759 769 |  | 
| 760 770 | 
             
                # [71]  	ArgList	  ::=  	NIL
         | 
| @@ -798,46 +808,76 @@ module SPARQL::Grammar | |
| 798 808 | 
             
                  add_prod_datum(:pattern, data[:pattern])
         | 
| 799 809 | 
             
                end
         | 
| 800 810 |  | 
| 811 | 
            +
                # [78]  	Verb	  ::=  	VarOrIri | 'a'
         | 
| 812 | 
            +
                production(:Verb) do |input, data, callback|
         | 
| 813 | 
            +
                  input[:Verb] = data.values.first
         | 
| 814 | 
            +
                end
         | 
| 815 | 
            +
             | 
| 801 816 | 
             
                # [79]  	ObjectList	  ::=  	Object ( ',' Object )*
         | 
| 802 817 | 
             
                start_production(:ObjectList) do |input, data, callback|
         | 
| 803 818 | 
             
                  # Called after Verb. The prod_data stack should have Subject and Verb elements
         | 
| 804 819 | 
             
                  data[:Subject] = prod_data[:Subject]
         | 
| 805 820 | 
             
                  error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
         | 
| 806 | 
            -
                  error(nil, "Expected Verb", production: :ObjectList) if !prod_data[:Verb] && validate?
         | 
| 821 | 
            +
                  error(nil, "Expected Verb", production: :ObjectList) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
         | 
| 807 822 | 
             
                  data[:Subject] = prod_data[:Subject]
         | 
| 808 | 
            -
                   | 
| 823 | 
            +
                  if prod_data[:Verb]
         | 
| 824 | 
            +
                    data[:Verb] = prod_data[:Verb]
         | 
| 825 | 
            +
                  else
         | 
| 826 | 
            +
                    data[:VerbPath] = prod_data[:VerbPath]
         | 
| 827 | 
            +
                  end
         | 
| 809 828 | 
             
                end
         | 
| 810 829 | 
             
                production(:ObjectList) do |input, data, callback|
         | 
| 811 830 | 
             
                  add_prod_datum(:pattern, data[:pattern])
         | 
| 831 | 
            +
                  add_prod_datum(:path, data[:path])
         | 
| 812 832 | 
             
                end
         | 
| 813 833 |  | 
| 814 834 | 
             
                # [80]  	Object	  ::=  	GraphNode
         | 
| 815 835 | 
             
                production(:Object) do |input, data, callback|
         | 
| 816 836 | 
             
                  object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
         | 
| 817 837 | 
             
                  if object
         | 
| 818 | 
            -
                     | 
| 819 | 
            -
             | 
| 838 | 
            +
                    if prod_data[:Verb]
         | 
| 839 | 
            +
                      add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
         | 
| 840 | 
            +
                      add_prod_datum(:pattern, data[:pattern])
         | 
| 841 | 
            +
                    else
         | 
| 842 | 
            +
                      add_prod_datum(:path,
         | 
| 843 | 
            +
                        SPARQL::Algebra::Expression(:path,
         | 
| 844 | 
            +
                                                    prod_data[:Subject].first,
         | 
| 845 | 
            +
                                                    prod_data[:VerbPath],
         | 
| 846 | 
            +
                                                    object.first))
         | 
| 847 | 
            +
                    end
         | 
| 820 848 | 
             
                  end
         | 
| 821 849 | 
             
                end
         | 
| 822 850 |  | 
| 823 | 
            -
                # [ | 
| 824 | 
            -
                production(: | 
| 825 | 
            -
                  data | 
| 851 | 
            +
                # [81]	TriplesSameSubjectPath	::=	VarOrTerm PropertyListPathNotEmpty | TriplesNode PropertyListPath
         | 
| 852 | 
            +
                production(:TriplesSameSubjectPath) do |input, data, callback|
         | 
| 853 | 
            +
                  if data[:pattern]
         | 
| 854 | 
            +
                    add_prod_datum(:pattern, data[:pattern])
         | 
| 855 | 
            +
                  else
         | 
| 856 | 
            +
                    add_prod_datum(:path, data[:path])
         | 
| 857 | 
            +
                  end
         | 
| 826 858 | 
             
                end
         | 
| 827 859 |  | 
| 828 | 
            -
                # [83]  	 | 
| 829 | 
            -
                start_production(: | 
| 830 | 
            -
                  subject = input[:VarOrTerm]
         | 
| 831 | 
            -
                  error(nil, "Expected VarOrTerm", production:  | 
| 860 | 
            +
                # [83]  	PropertyListPathNotEmpty	  ::=  	( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
         | 
| 861 | 
            +
                start_production(:PropertyListPathNotEmpty) do |input, data, callback|
         | 
| 862 | 
            +
                  subject = input[:VarOrTerm] || input[:TriplesNode] || input[:GraphNode]
         | 
| 863 | 
            +
                  error(nil, "Expected VarOrTerm, got nothing", production: :PropertyListPathNotEmpty) if validate? && !subject
         | 
| 832 864 | 
             
                  data[:Subject] = subject
         | 
| 833 865 | 
             
                end
         | 
| 834 | 
            -
                production(: | 
| 835 | 
            -
                   | 
| 866 | 
            +
                production(:PropertyListPathNotEmpty) do |input, data, callback|
         | 
| 867 | 
            +
                  if data[:pattern]
         | 
| 868 | 
            +
                    add_prod_datum(:pattern, data[:pattern])
         | 
| 869 | 
            +
                  else
         | 
| 870 | 
            +
                    add_prod_datum(:path, data[:path])
         | 
| 871 | 
            +
                  end
         | 
| 836 872 | 
             
                end
         | 
| 837 873 |  | 
| 838 874 | 
             
                # [84]  	VerbPath	  ::=  	Path
         | 
| 839 875 | 
             
                production(:VerbPath) do |input, data, callback|
         | 
| 840 | 
            -
                  data | 
| 876 | 
            +
                  if data[:Path]
         | 
| 877 | 
            +
                    input[:VerbPath] = data[:Path]
         | 
| 878 | 
            +
                  else
         | 
| 879 | 
            +
                    input[:Verb] = data[:iri]
         | 
| 880 | 
            +
                  end
         | 
| 841 881 | 
             
                end
         | 
| 842 882 |  | 
| 843 883 | 
             
                # [85]  	VerbSimple	  ::=  	Var
         | 
| @@ -845,6 +885,134 @@ module SPARQL::Grammar | |
| 845 885 | 
             
                  data.values.each {|v| add_prod_datum(:Verb, v)}
         | 
| 846 886 | 
             
                end
         | 
| 847 887 |  | 
| 888 | 
            +
                # [86]	ObjectListPath	::=	ObjectPath ("," ObjectPath)*
         | 
| 889 | 
            +
                start_production(:ObjectListPath) do |input, data, callback|
         | 
| 890 | 
            +
                  # Called after Verb. The prod_data stack should have Subject and Verb elements
         | 
| 891 | 
            +
                  data[:Subject] = prod_data[:Subject]
         | 
| 892 | 
            +
                  error(nil, "Expected Subject", production: :ObjectListPath) if !prod_data[:Subject] && validate?
         | 
| 893 | 
            +
                  error(nil, "Expected Verb", production: :ObjectListPath) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
         | 
| 894 | 
            +
                  if prod_data[:Verb]
         | 
| 895 | 
            +
                    data[:Verb] = Array(prod_data[:Verb]).last
         | 
| 896 | 
            +
                  else
         | 
| 897 | 
            +
                    data[:VerbPath] = prod_data[:VerbPath]
         | 
| 898 | 
            +
                  end
         | 
| 899 | 
            +
                end
         | 
| 900 | 
            +
                production(:ObjectListPath) do |input, data, callback|
         | 
| 901 | 
            +
                  add_prod_datum(:pattern, data[:pattern])
         | 
| 902 | 
            +
                  add_prod_datum(:path, data[:path])
         | 
| 903 | 
            +
                end
         | 
| 904 | 
            +
             | 
| 905 | 
            +
                # [87]  	ObjectPath	  ::=  	GraphNodePath
         | 
| 906 | 
            +
                production(:ObjectPath) do |input, data, callback|
         | 
| 907 | 
            +
                  object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
         | 
| 908 | 
            +
                  if object
         | 
| 909 | 
            +
                    if prod_data[:Verb]
         | 
| 910 | 
            +
                      if data[:pattern] && data[:path]
         | 
| 911 | 
            +
                        # Generate a sequence (for collection of paths)
         | 
| 912 | 
            +
                        data[:pattern].unshift(RDF::Query::Pattern.new(prod_data[:Subject].first, prod_data[:Verb], object.first))
         | 
| 913 | 
            +
                        bgp = SPARQL::Algebra::Expression[:bgp, data[:pattern]]
         | 
| 914 | 
            +
                        add_prod_datum(:path, SPARQL::Algebra::Expression[:sequence, bgp, *data[:path]])
         | 
| 915 | 
            +
                      else
         | 
| 916 | 
            +
                        add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
         | 
| 917 | 
            +
                        add_prod_datum(:pattern, data[:pattern])
         | 
| 918 | 
            +
                      end
         | 
| 919 | 
            +
                    else
         | 
| 920 | 
            +
                      add_prod_datum(:path,
         | 
| 921 | 
            +
                        SPARQL::Algebra::Expression(:path,
         | 
| 922 | 
            +
                                                    Array(prod_data[:Subject]).first,
         | 
| 923 | 
            +
                                                    prod_data[:VerbPath],
         | 
| 924 | 
            +
                                                    object.first))
         | 
| 925 | 
            +
                    end
         | 
| 926 | 
            +
                  end
         | 
| 927 | 
            +
                end
         | 
| 928 | 
            +
                # [88]  	Path	  ::=  	PathAlternative
         | 
| 929 | 
            +
                # output is a :Path or :iri
         | 
| 930 | 
            +
                production(:Path) do |input, data, callback|
         | 
| 931 | 
            +
                  if data[:Path].is_a?(RDF::URI)
         | 
| 932 | 
            +
                    input[:iri] = data[:Path]
         | 
| 933 | 
            +
                  else
         | 
| 934 | 
            +
                    input[:Path] = data[:Path]
         | 
| 935 | 
            +
                  end
         | 
| 936 | 
            +
                end
         | 
| 937 | 
            +
             | 
| 938 | 
            +
                # [89]  	PathAlternative	  ::=  	PathSequence ( '|' PathSequence )*
         | 
| 939 | 
            +
                production(:PathAlternative) do |input, data, callback|
         | 
| 940 | 
            +
                  lhs = Array(data[:PathSequence]).shift
         | 
| 941 | 
            +
                  while data[:PathSequence] && !data[:PathSequence].empty?
         | 
| 942 | 
            +
                    rhs = data[:PathSequence].shift
         | 
| 943 | 
            +
                    lhs = SPARQL::Algebra::Expression[:alt, lhs, rhs]
         | 
| 944 | 
            +
                  end
         | 
| 945 | 
            +
                  input[:Path] = lhs
         | 
| 946 | 
            +
                end
         | 
| 947 | 
            +
             | 
| 948 | 
            +
                # ( '|' PathSequence )*
         | 
| 949 | 
            +
                production(:_PathAlternative_1) do |input, data, callback|
         | 
| 950 | 
            +
                  input[:PathSequence] += data[:PathSequence]
         | 
| 951 | 
            +
                end
         | 
| 952 | 
            +
             | 
| 953 | 
            +
                # [90]  	PathSequence	  ::=  	PathEltOrInverse ( '/' PathEltOrInverse )*
         | 
| 954 | 
            +
                production(:PathSequence) do |input, data, callback|
         | 
| 955 | 
            +
                  lhs = data[:PathEltOrInverse].shift
         | 
| 956 | 
            +
                  while data[:PathEltOrInverse] && !data[:PathEltOrInverse].empty?
         | 
| 957 | 
            +
                    rhs = data[:PathEltOrInverse].shift
         | 
| 958 | 
            +
                    lhs = SPARQL::Algebra::Expression[:seq, lhs, rhs]
         | 
| 959 | 
            +
                  end
         | 
| 960 | 
            +
                  input[:PathSequence] = [lhs]
         | 
| 961 | 
            +
                end
         | 
| 962 | 
            +
             | 
| 963 | 
            +
                # ( '/' PathEltOrInverse )*
         | 
| 964 | 
            +
                production(:_PathSequence_1) do |input, data, callback|
         | 
| 965 | 
            +
                  input[:PathEltOrInverse] += data[:PathEltOrInverse]
         | 
| 966 | 
            +
                end
         | 
| 967 | 
            +
             | 
| 968 | 
            +
                # [91]  	PathElt	  ::=  	PathPrimary PathMod?
         | 
| 969 | 
            +
                production(:PathElt) do |input, data, callback|
         | 
| 970 | 
            +
                  path_mod = data.delete(:PathMod) if data.has_key?(:PathMod)
         | 
| 971 | 
            +
                  path_mod ||= data.delete(:MultiplicativeExpression) if data.has_key?(:MultiplicativeExpression)
         | 
| 972 | 
            +
                  path_mod = path_mod.first if path_mod
         | 
| 973 | 
            +
             | 
| 974 | 
            +
                  res = data[:PathPrimary]
         | 
| 975 | 
            +
                  res = SPARQL::Algebra::Expression("path#{path_mod}", res) if path_mod
         | 
| 976 | 
            +
                  input[:Path] = res
         | 
| 977 | 
            +
                end
         | 
| 978 | 
            +
             | 
| 979 | 
            +
                # [92]  	PathEltOrInverse	  ::=  	PathElt | '^' PathElt
         | 
| 980 | 
            +
                production(:PathEltOrInverse) do |input, data, callback|
         | 
| 981 | 
            +
                  res = if data[:reverse]
         | 
| 982 | 
            +
                    SPARQL::Algebra::Expression(:reverse, data[:Path])
         | 
| 983 | 
            +
                  else
         | 
| 984 | 
            +
                    data[:Path]
         | 
| 985 | 
            +
                  end
         | 
| 986 | 
            +
                  input[:PathEltOrInverse] = [res]
         | 
| 987 | 
            +
                end
         | 
| 988 | 
            +
             | 
| 989 | 
            +
                # [94]  	PathPrimary	  ::=  	iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
         | 
| 990 | 
            +
                production(:PathPrimary) do |input, data, callback|
         | 
| 991 | 
            +
                  input[:PathPrimary] = case
         | 
| 992 | 
            +
                  when data[:Verb]                   then data[:Verb]
         | 
| 993 | 
            +
                  when data[:iri]                    then data[:iri]
         | 
| 994 | 
            +
                  when data[:PathNegatedPropertySet] then data[:PathNegatedPropertySet]
         | 
| 995 | 
            +
                  when data[:Path]                   then data[:Path]
         | 
| 996 | 
            +
                  end
         | 
| 997 | 
            +
                end
         | 
| 998 | 
            +
             | 
| 999 | 
            +
                # [95]  	PathNegatedPropertySet	  ::=  	PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
         | 
| 1000 | 
            +
                production(:PathNegatedPropertySet) do |input, data, callback|
         | 
| 1001 | 
            +
                  input[:Path] = SPARQL::Algebra::Expression(:notoneof, *Array(data[:Path]))
         | 
| 1002 | 
            +
                end
         | 
| 1003 | 
            +
             | 
| 1004 | 
            +
                # ( '|' PathOneInPropertySet )* )?
         | 
| 1005 | 
            +
                production(:_PathNegatedPropertySet_4) do |input, data, callback|
         | 
| 1006 | 
            +
                  add_prod_datum(:Path, data[:Path])
         | 
| 1007 | 
            +
                end
         | 
| 1008 | 
            +
             | 
| 1009 | 
            +
                # [96]  	PathOneInPropertySet	  ::=  	iri | 'a' | '^' ( iri | 'a' )
         | 
| 1010 | 
            +
                production(:PathOneInPropertySet) do |input, data, callback|
         | 
| 1011 | 
            +
                  term = (Array(data[:iri]) || data[:Verb]).first
         | 
| 1012 | 
            +
                  term = SPARQL::Algebra::Expression(:reverse, term) if data[:reverse]
         | 
| 1013 | 
            +
                  input[:Path] = [term]
         | 
| 1014 | 
            +
                end
         | 
| 1015 | 
            +
             | 
| 848 1016 | 
             
                # [98]  	TriplesNode	  ::=  	Collection |	BlankNodePropertyList
         | 
| 849 1017 | 
             
                start_production(:TriplesNode) do |input, data, callback|
         | 
| 850 1018 | 
             
                  # Called after Verb. The prod_data stack should have Subject and Verb elements
         | 
| @@ -855,6 +1023,17 @@ module SPARQL::Grammar | |
| 855 1023 | 
             
                  add_prod_datum(:TriplesNode, data[:TriplesNode])
         | 
| 856 1024 | 
             
                end
         | 
| 857 1025 |  | 
| 1026 | 
            +
                # [100]	TriplesNodePath	::=	CollectionPath | BlankNodePropertyListPath
         | 
| 1027 | 
            +
                start_production(:TriplesNodePath) do |input, data, callback|
         | 
| 1028 | 
            +
                  # Called after Verb. The prod_data stack should have Subject and Verb elements
         | 
| 1029 | 
            +
                  data[:TriplesNode] = bnode
         | 
| 1030 | 
            +
                end
         | 
| 1031 | 
            +
                production(:TriplesNodePath) do |input, data, callback|
         | 
| 1032 | 
            +
                  add_prod_datum(:pattern, data[:pattern])
         | 
| 1033 | 
            +
                  add_prod_datum(:path, data[:path])
         | 
| 1034 | 
            +
                  add_prod_datum(:TriplesNode, data[:TriplesNode])
         | 
| 1035 | 
            +
                end
         | 
| 1036 | 
            +
             | 
| 858 1037 | 
             
                # [102]  	Collection	  ::=  	'(' GraphNode+ ')'
         | 
| 859 1038 | 
             
                start_production(:Collection) do |input, data, callback|
         | 
| 860 1039 | 
             
                  # Tells the TriplesNode production to collect and not generate statements
         | 
| @@ -864,6 +1043,16 @@ module SPARQL::Grammar | |
| 864 1043 | 
             
                  expand_collection(data)
         | 
| 865 1044 | 
             
                end
         | 
| 866 1045 |  | 
| 1046 | 
            +
                # [103]	CollectionPath	::=	"(" GraphNodePath+ ")"
         | 
| 1047 | 
            +
                start_production(:CollectionPath) do |input, data, callback|
         | 
| 1048 | 
            +
                  # Tells the TriplesNode production to collect and not generate statements
         | 
| 1049 | 
            +
                  data[:Collection] = prod_data[:TriplesNode]
         | 
| 1050 | 
            +
                end
         | 
| 1051 | 
            +
                production(:CollectionPath) do |input, data, callback|
         | 
| 1052 | 
            +
                  expand_collection(data)
         | 
| 1053 | 
            +
                  add_prod_datum(:path, data[:path])
         | 
| 1054 | 
            +
                end
         | 
| 1055 | 
            +
             | 
| 867 1056 | 
             
                # [104]  	GraphNode	  ::=  	VarOrTerm |	TriplesNode
         | 
| 868 1057 | 
             
                production(:GraphNode) do |input, data, callback|
         | 
| 869 1058 | 
             
                  term = data[:VarOrTerm] || data[:TriplesNode]
         | 
| @@ -871,6 +1060,14 @@ module SPARQL::Grammar | |
| 871 1060 | 
             
                  add_prod_datum(:GraphNode, term)
         | 
| 872 1061 | 
             
                end
         | 
| 873 1062 |  | 
| 1063 | 
            +
                # [105]	GraphNodePath	::=	VarOrTerm | TriplesNodePath
         | 
| 1064 | 
            +
                production(:GraphNodePath) do |input, data, callback|
         | 
| 1065 | 
            +
                  term = data[:VarOrTerm] || data[:TriplesNode]
         | 
| 1066 | 
            +
                  add_prod_datum(:pattern, data[:pattern])
         | 
| 1067 | 
            +
                  add_prod_datum(:path, data[:path])
         | 
| 1068 | 
            +
                  add_prod_datum(:GraphNode, term)
         | 
| 1069 | 
            +
                end
         | 
| 1070 | 
            +
             | 
| 874 1071 | 
             
                # [106]  	VarOrTerm	  ::=  	Var | GraphTerm
         | 
| 875 1072 | 
             
                production(:VarOrTerm) do |input, data, callback|
         | 
| 876 1073 | 
             
                  data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
         | 
| @@ -986,7 +1183,7 @@ module SPARQL::Grammar | |
| 986 1183 |  | 
| 987 1184 | 
             
                # | ( NumericLiteralPositive | NumericLiteralNegative )
         | 
| 988 1185 | 
             
                production(:_AdditiveExpression_7) do |input, data, callback|
         | 
| 989 | 
            -
                  lit = data[:literal] | 
| 1186 | 
            +
                  lit = data[:literal]
         | 
| 990 1187 | 
             
                  val = lit.to_s
         | 
| 991 1188 | 
             
                  op, val = val[0,1], val[1..-1]
         | 
| 992 1189 | 
             
                  add_prod_datum(:AdditiveExpression, op)
         | 
| @@ -1106,19 +1303,18 @@ module SPARQL::Grammar | |
| 1106 1303 | 
             
                #                                 | ExistsFunc
         | 
| 1107 1304 | 
             
                #                                 | NotExistsFunc
         | 
| 1108 1305 | 
             
                production(:BuiltInCall) do |input, data, callback|
         | 
| 1109 | 
            -
                  if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
         | 
| 1110 | 
            -
                     | 
| 1111 | 
            -
                       | 
| 1112 | 
            -
             | 
| 1113 | 
            -
                        unshift(builtin)))
         | 
| 1306 | 
            +
                  input[:BuiltInCall] = if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
         | 
| 1307 | 
            +
                    SPARQL::Algebra::Expression.for(
         | 
| 1308 | 
            +
                      (data[:ExpressionList] || data[:Expression] || []).
         | 
| 1309 | 
            +
                      unshift(builtin))
         | 
| 1114 1310 | 
             
                  elsif builtin_rule = data.keys.detect {|k| BUILTIN_RULES.include?(k)}
         | 
| 1115 | 
            -
                     | 
| 1311 | 
            +
                    SPARQL::Algebra::Expression.for(data[builtin_rule].unshift(builtin_rule))
         | 
| 1116 1312 | 
             
                  elsif aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
         | 
| 1117 | 
            -
                     | 
| 1313 | 
            +
                    data[aggregate_rule].first
         | 
| 1118 1314 | 
             
                  elsif data[:bound]
         | 
| 1119 | 
            -
                     | 
| 1315 | 
            +
                    SPARQL::Algebra::Expression.for(data[:Var].unshift(:bound))
         | 
| 1120 1316 | 
             
                  elsif data[:BuiltInCall]
         | 
| 1121 | 
            -
                     | 
| 1317 | 
            +
                    SPARQL::Algebra::Expression.for(data[:BuiltInCall] + data[:Expression])
         | 
| 1122 1318 | 
             
                  end
         | 
| 1123 1319 | 
             
                end
         | 
| 1124 1320 |  | 
| @@ -1164,7 +1360,7 @@ module SPARQL::Grammar | |
| 1164 1360 | 
             
                production(:Aggregate) do |input, data, callback|
         | 
| 1165 1361 | 
             
                  if aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
         | 
| 1166 1362 | 
             
                    parts = [aggregate_rule]
         | 
| 1167 | 
            -
                    parts << [:separator, RDF::Literal(data[:string] | 
| 1363 | 
            +
                    parts << [:separator, RDF::Literal(data[:string])] if data[:separator] && data[:string]
         | 
| 1168 1364 | 
             
                    parts << :distinct if data[:DISTINCT_REDUCED]
         | 
| 1169 1365 | 
             
                    parts << data[:Expression].first if data[:Expression]
         | 
| 1170 1366 | 
             
                    add_prod_data(aggregate_rule, SPARQL::Algebra::Expression.for(parts))
         | 
| @@ -1175,9 +1371,9 @@ module SPARQL::Grammar | |
| 1175 1371 | 
             
                production(:iriOrFunction) do |input, data, callback|
         | 
| 1176 1372 | 
             
                  if data.has_key?(:ArgList)
         | 
| 1177 1373 | 
             
                    # Function is (func arg1 arg2 ...)
         | 
| 1178 | 
            -
                    add_prod_data(:Function, data[:iri] + data[:ArgList])
         | 
| 1374 | 
            +
                    add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
         | 
| 1179 1375 | 
             
                  else
         | 
| 1180 | 
            -
                     | 
| 1376 | 
            +
                    input[:iri] = data[:iri]
         | 
| 1181 1377 | 
             
                  end
         | 
| 1182 1378 | 
             
                end
         | 
| 1183 1379 |  | 
| @@ -1185,10 +1381,10 @@ module SPARQL::Grammar | |
| 1185 1381 | 
             
                production(:RDFLiteral) do |input, data, callback|
         | 
| 1186 1382 | 
             
                  if data[:string]
         | 
| 1187 1383 | 
             
                    lit = data.dup
         | 
| 1188 | 
            -
                    str = lit.delete(:string) | 
| 1189 | 
            -
                    lit[:datatype] = lit.delete(:iri) | 
| 1384 | 
            +
                    str = lit.delete(:string)
         | 
| 1385 | 
            +
                    lit[:datatype] = lit.delete(:iri) if lit[:iri]
         | 
| 1190 1386 | 
             
                    lit[:language] = lit.delete(:language).last.downcase if lit[:language]
         | 
| 1191 | 
            -
                     | 
| 1387 | 
            +
                    input[:literal] = RDF::Literal.new(str, lit) if str
         | 
| 1192 1388 | 
             
                  end
         | 
| 1193 1389 | 
             
                end
         | 
| 1194 1390 |  | 
| @@ -1197,7 +1393,7 @@ module SPARQL::Grammar | |
| 1197 1393 | 
             
                #                                       |	DOUBLE_POSITIVE
         | 
| 1198 1394 | 
             
                production(:NumericLiteralPositive) do |input, data, callback|
         | 
| 1199 1395 | 
             
                  num = data.values.flatten.last
         | 
| 1200 | 
            -
                   | 
| 1396 | 
            +
                  input[:literal] = num
         | 
| 1201 1397 |  | 
| 1202 1398 | 
             
                  # Keep track of this for parent UnaryExpression production
         | 
| 1203 1399 | 
             
                  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
         | 
| @@ -1208,17 +1404,12 @@ module SPARQL::Grammar | |
| 1208 1404 | 
             
                #                                       |	DOUBLE_NEGATIVE
         | 
| 1209 1405 | 
             
                production(:NumericLiteralNegative) do |input, data, callback|
         | 
| 1210 1406 | 
             
                  num = data.values.flatten.last
         | 
| 1211 | 
            -
                   | 
| 1407 | 
            +
                  input[:literal] = num
         | 
| 1212 1408 |  | 
| 1213 1409 | 
             
                  # Keep track of this for parent UnaryExpression production
         | 
| 1214 1410 | 
             
                  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
         | 
| 1215 1411 | 
             
                end
         | 
| 1216 1412 |  | 
| 1217 | 
            -
                # [137]  	PrefixedName	  ::=  	PNAME_LN | PNAME_NS
         | 
| 1218 | 
            -
                production(:PrefixedName) do |input, data, callback|
         | 
| 1219 | 
            -
                  add_prod_datum(:iri, data[:PrefixedName])
         | 
| 1220 | 
            -
                end
         | 
| 1221 | 
            -
             | 
| 1222 1413 | 
             
                ##
         | 
| 1223 1414 | 
             
                # Initializes a new parser instance.
         | 
| 1224 1415 | 
             
                #
         | 
| @@ -1318,10 +1509,10 @@ module SPARQL::Grammar | |
| 1318 1509 | 
             
                      level, lineno, depth, *args = data
         | 
| 1319 1510 | 
             
                      message = args.to_sse
         | 
| 1320 1511 | 
             
                      d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
         | 
| 1321 | 
            -
                      str = "[#{lineno}](#{level})#{d_str}#{message}"
         | 
| 1512 | 
            +
                      str = "[#{lineno}](#{level})#{d_str}#{message}".chop
         | 
| 1322 1513 | 
             
                      case @options[:debug]
         | 
| 1323 1514 | 
             
                      when Array
         | 
| 1324 | 
            -
                        @options[:debug] << str
         | 
| 1515 | 
            +
                        @options[:debug] << str unless level > 2
         | 
| 1325 1516 | 
             
                      when TrueClass
         | 
| 1326 1517 | 
             
                        $stderr.puts str
         | 
| 1327 1518 | 
             
                      when Integer
         | 
| @@ -1337,13 +1528,17 @@ module SPARQL::Grammar | |
| 1337 1528 | 
             
                  when prod_data.empty?
         | 
| 1338 1529 | 
             
                    nil
         | 
| 1339 1530 | 
             
                  when prod_data[:query]
         | 
| 1340 | 
            -
                    prod_data[:query]. | 
| 1531 | 
            +
                    Array(prod_data[:query]).length == 1 ? prod_data[:query].first : prod_data[:query]
         | 
| 1341 1532 | 
             
                  when prod_data[:update]
         | 
| 1342 1533 | 
             
                    prod_data[:update]
         | 
| 1343 1534 | 
             
                  else
         | 
| 1344 1535 | 
             
                    key = prod_data.keys.first
         | 
| 1345 1536 | 
             
                    [key] + Array(prod_data[key])  # Creates [:key, [:triple], ...]
         | 
| 1346 1537 | 
             
                  end
         | 
| 1538 | 
            +
             | 
| 1539 | 
            +
                  # Validate resulting expression
         | 
| 1540 | 
            +
                  @result.validate! if @result && validate?
         | 
| 1541 | 
            +
                  @result
         | 
| 1347 1542 | 
             
                end
         | 
| 1348 1543 |  | 
| 1349 1544 | 
             
                private
         | 
| @@ -1539,7 +1734,7 @@ module SPARQL::Grammar | |
| 1539 1734 |  | 
| 1540 1735 | 
             
                  # Create list items for each element in data[:GraphNode]
         | 
| 1541 1736 | 
             
                  first = data[:Collection]
         | 
| 1542 | 
            -
                  list = data[:GraphNode]. | 
| 1737 | 
            +
                  list = Array(data[:GraphNode]).flatten.compact
         | 
| 1543 1738 | 
             
                  last = list.pop
         | 
| 1544 1739 |  | 
| 1545 1740 | 
             
                  list.each do |r|
         | 
| @@ -1560,7 +1755,6 @@ module SPARQL::Grammar | |
| 1560 1755 | 
             
                # @param [String] production Production generating pattern
         | 
| 1561 1756 | 
             
                # @param [Hash{Symbol => Object}] options
         | 
| 1562 1757 | 
             
                def add_pattern(production, options)
         | 
| 1563 | 
            -
                  progress(production, "add_pattern: #{options.inspect}")
         | 
| 1564 1758 | 
             
                  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
         | 
| 1565 1759 | 
             
                  triple = {}
         | 
| 1566 1760 | 
             
                  options.each_pair do |r, v|
         | 
| @@ -1681,7 +1875,7 @@ module SPARQL::Grammar | |
| 1681 1875 |  | 
| 1682 1876 | 
             
                  query = SPARQL::Algebra::Expression[:project, vars, query] unless vars.empty?
         | 
| 1683 1877 |  | 
| 1684 | 
            -
                  query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED] | 
| 1878 | 
            +
                  query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED], query] if data[:DISTINCT_REDUCED]
         | 
| 1685 1879 |  | 
| 1686 1880 | 
             
                  query = SPARQL::Algebra::Expression[:slice, data[:slice][0], data[:slice][1], query] if data[:slice]
         | 
| 1687 1881 |  |