diff --git a/etc/turtle.bnf b/etc/turtle.bnf index 3faf101..9dfe3d0 100644 --- a/etc/turtle.bnf +++ b/etc/turtle.bnf @@ -26,11 +26,14 @@ iri ::= IRIREF | PrefixedName PrefixedName ::= PNAME_LN | PNAME_NS BlankNode ::= BLANK_NODE_LABEL | ANON reifier ::= '~' (iri | BlankNode)? -reifiedTriple ::= '<<' (subject | reifiedTriple) predicate object reifier? '>>' -tripleTerm ::= '<<(' ttSubject predicate ttObject ')>>' +reifiedTriple ::= '<<' rtSubject verb rtObject reifier? '>>' +rtSubject ::= iri | BlankNode | reifiedTriple +rtObject ::= iri | BlankNode | literal | tripleTerm | reifiedTriple +tripleTerm ::= '<<(' ttSubject verb ttObject ')>>' ttSubject ::= iri | BlankNode ttObject ::= iri | BlankNode | literal | tripleTerm -annotation ::= (reifier | '{|' predicateObjectList '|}')* +annotation ::= (reifier | annotationBlock)* +annotationBlock ::= '{|' predicateObjectList '|}' @terminals diff --git a/lib/rdf/turtle/reader.rb b/lib/rdf/turtle/reader.rb index 369b695..7e64b80 100644 --- a/lib/rdf/turtle/reader.rb +++ b/lib/rdf/turtle/reader.rb @@ -461,7 +461,7 @@ def read_reifiedTriple @lexer.shift # eat << subject = read_ttSubject || read_reifiedTriple || error("Failed to parse subject", production: :reifiedTriple, token: @lexer.first) predicate = read_verb || error("Failed to parse predicate", production: :reifiedTriple, token: @lexer.first) - object = read_object || error("Failed to parse object", production: :reifiedTriple, token: @lexer.first) + object = read_ttObject || read_tripleTerm || read_reifiedTriple || error("Failed to parse object", production: :reifiedTriple, token: @lexer.first) tt = RDF::Statement(subject, predicate, object, tripleTerm: true) # An optional reifier. If not specified it is a new blank node. diff --git a/spec/reader_spec.rb b/spec/reader_spec.rb index ca7b7b2..6a6c5ac 100644 --- a/spec/reader_spec.rb +++ b/spec/reader_spec.rb @@ -1435,6 +1435,29 @@ _:bn2 . ) ], + 'included triple terms': [ + %( + PREFIX : + :s :p <<( :s1 :p1 <<( :s2 :p2 :o2 )>> )>>, <<( :s3 :p3 :o3)>> . + ), + %( + <<( <<( )>>)>> . + <<( )>> + ) + ], + 'included reified triples': [ + %( + PREFIX : + :s :p << :s1 :p1 << :s2 :p2 :o2 >> >>, << :s3 :p3 :o3 >> . + ), + %( + _:r0 . + _:r1 <<( )>> . + _:r0 <<( _:r1 )>> . + _:r2 . + _:r2 <<( )>> . + ) + ], }.each do |name, (ttl, nt)| it name do if nt.is_a?(String)