Add support for Turtle-star decoding

This commit is contained in:
Marcel Otto 2021-10-01 23:12:52 +02:00
parent 0aa0128434
commit e95c5c685d
67 changed files with 732 additions and 79 deletions

View file

@ -69,9 +69,8 @@ defmodule RDF.Turtle.Decoder do
{graph, %State{namespaces: namespaces, base_iri: base_iri}} =
Enum.reduce(ast, {RDF.Graph.new(), %State{base_iri: base_iri}}, fn
{:triples, triples_ast}, {graph, state} ->
with {statements, state} = triples(triples_ast, state) do
{RDF.Graph.add(graph, statements), state}
end
{statements, state} = triples(triples_ast, state)
{RDF.Graph.add(graph, statements), state}
{:directive, directive_ast}, {graph, state} ->
{graph, directive(directive_ast, state)}
@ -89,49 +88,49 @@ defmodule RDF.Turtle.Decoder do
end
defp directive({:prefix, {:prefix_ns, _, ns}, iri}, state) do
if IRI.absolute?(iri) do
State.add_namespace(state, ns, iri)
else
with absolute_iri = IRI.absolute(iri, state.base_iri) do
State.add_namespace(state, ns, to_string(absolute_iri))
absolute_iri =
if IRI.absolute?(iri) do
iri
else
iri |> IRI.absolute(state.base_iri) |> to_string()
end
end
State.add_namespace(state, ns, absolute_iri)
end
defp directive({:base, iri}, %State{base_iri: base_iri} = state) do
cond do
IRI.absolute?(iri) ->
%State{state | base_iri: RDF.iri(iri)}
base_iri != nil ->
with absolute_iri = IRI.absolute(iri, base_iri) do
%State{state | base_iri: absolute_iri}
end
true ->
raise "Could not resolve relative IRI '#{iri}', no base iri provided"
IRI.absolute?(iri) -> %State{state | base_iri: RDF.iri(iri)}
not is_nil(base_iri) -> %State{state | base_iri: IRI.absolute(iri, base_iri)}
true -> raise "Could not resolve relative IRI '#{iri}', no base iri provided"
end
end
defp triples({:blankNodePropertyList, _} = ast, state) do
with {_, statements, state} = resolve_node(ast, [], state) do
{statements, state}
end
{_, statements, state} = resolve_node(ast, [], state)
{statements, state}
end
defp triples({subject, predications}, state) do
with {subject, statements, state} = resolve_node(subject, [], state) do
Enum.reduce(predications, {statements, state}, fn {predicate, objects},
{statements, state} ->
with {predicate, statements, state} = resolve_node(predicate, statements, state) do
Enum.reduce(objects, {statements, state}, fn object, {statements, state} ->
with {object, statements, state} = resolve_node(object, statements, state) do
{[{subject, predicate, object} | statements], state}
end
end)
end
end)
end
{subject, statements, state} = resolve_node(subject, [], state)
predications(subject, predications, statements, state)
end
defp predications(subject, predications, statements, state) do
Enum.reduce(predications, {statements, state}, fn
{predicate, objects}, {statements, state} ->
{predicate, statements, state} = resolve_node(predicate, statements, state)
Enum.reduce(objects, {statements, state}, fn
{:annotation, annotation}, {[last_statement | _] = statements, state} ->
predications(last_statement, annotation, statements, state)
object, {statements, state} ->
{object, statements, state} = resolve_node(object, statements, state)
{[{subject, predicate, object} | statements], state}
end)
end)
end
defp resolve_node({:prefix_ln, line_number, {prefix, name}}, statements, state) do
@ -159,16 +158,14 @@ defmodule RDF.Turtle.Decoder do
end
defp resolve_node({:anon}, statements, state) do
with {node, state} = State.next_bnode(state) do
{node, statements, state}
end
{node, state} = State.next_bnode(state)
{node, statements, state}
end
defp resolve_node({:blankNodePropertyList, property_list}, statements, state) do
with {subject, state} = State.next_bnode(state),
{new_statements, state} = triples({subject, property_list}, state) do
{subject, statements ++ new_statements, state}
end
{subject, state} = State.next_bnode(state)
{new_statements, state} = triples({subject, property_list}, state)
{subject, statements ++ new_statements, state}
end
defp resolve_node(
@ -176,9 +173,8 @@ defmodule RDF.Turtle.Decoder do
statements,
state
) do
with {datatype, statements, state} = resolve_node(datatype, statements, state) do
{RDF.literal(value, datatype: datatype), statements, state}
end
{datatype, statements, state} = resolve_node(datatype, statements, state)
{RDF.literal(value, datatype: datatype), statements, state}
end
defp resolve_node({:collection, []}, statements, state) do
@ -186,29 +182,36 @@ defmodule RDF.Turtle.Decoder do
end
defp resolve_node({:collection, elements}, statements, state) do
with {first_list_node, state} = State.next_bnode(state),
[first_element | rest_elements] = elements,
{first_element_node, statements, state} = resolve_node(first_element, statements, state),
first_statement = [{first_list_node, RDF.first(), first_element_node}] do
{last_list_node, statements, state} =
Enum.reduce(
rest_elements,
{first_list_node, statements ++ first_statement, state},
fn element, {list_node, statements, state} ->
with {element_node, statements, state} = resolve_node(element, statements, state),
{next_list_node, state} = State.next_bnode(state) do
{next_list_node,
statements ++
[
{list_node, RDF.rest(), next_list_node},
{next_list_node, RDF.first(), element_node}
], state}
end
end
)
{first_list_node, state} = State.next_bnode(state)
[first_element | rest_elements] = elements
{first_element_node, statements, state} = resolve_node(first_element, statements, state)
first_statement = [{first_list_node, RDF.first(), first_element_node}]
{first_list_node, statements ++ [{last_list_node, RDF.rest(), RDF.nil()}], state}
end
{last_list_node, statements, state} =
Enum.reduce(
rest_elements,
{first_list_node, statements ++ first_statement, state},
fn element, {list_node, statements, state} ->
{element_node, statements, state} = resolve_node(element, statements, state)
{next_list_node, state} = State.next_bnode(state)
{next_list_node,
statements ++
[
{list_node, RDF.rest(), next_list_node},
{next_list_node, RDF.first(), element_node}
], state}
end
)
{first_list_node, statements ++ [{last_list_node, RDF.rest(), RDF.nil()}], state}
end
defp resolve_node({:quoted_triple, s_node, p_node, o_node}, statements, state) do
{subject, statements, state} = resolve_node(s_node, statements, state)
{predicate, statements, state} = resolve_node(p_node, statements, state)
{object, statements, state} = resolve_node(o_node, statements, state)
{{subject, predicate, object}, statements, state}
end
defp resolve_node(node, statements, state), do: {node, statements, state}

View file

@ -70,6 +70,10 @@ a : {token, {'a', TokenLine}}.
\( : {token, {'(', TokenLine}}.
\) : {token, {')', TokenLine}}.
\^\^ : {token, {'^^', TokenLine}}.
\<\< : {token, {'<<', TokenLine}}.
\>\> : {token, {'>>', TokenLine}}.
\{\| : {token, {'{|', TokenLine}}.
\|\} : {token, {'|}', TokenLine}}.
{WS}+ : skip_token.
{COMMENT} : skip_token.

View file

@ -3,11 +3,13 @@
Nonterminals turtleDoc statement directive prefixID base sparqlPrefix sparqlBase
triples predicateObjectList objectList blankNodePropertyList semicolonSequence
verb subject predicate object collection collection_elements
literal numericLiteral rdfLiteral booleanLiteral iri prefixedName blankNode.
literal numericLiteral rdfLiteral booleanLiteral iri prefixedName blankNode
annotation quotedTriple qtSubject qtObject .
Terminals prefix_ns prefix_ln iriref blank_node_label anon
string_literal_quote langtag integer decimal double boolean
'.' ';' ',' '[' ']' '(' ')' '^^' '@prefix' '@base' 'PREFIX' 'BASE' 'a' .
'.' ';' ',' '[' ']' '(' ')' '^^' '@prefix' '@base' 'PREFIX' 'BASE' 'a'
'<<' '>>' '{|' '|}' .
Rootsymbol turtleDoc.
@ -37,10 +39,11 @@ predicateObjectList -> verb objectList semicolonSequence : [{'$1', '$2'}] .
predicateObjectList -> verb objectList semicolonSequence predicateObjectList : [{'$1', '$2'} | '$4'] .
semicolonSequence -> ';' .
semicolonSequence -> ';' semicolonSequence .
%%: '$1' .
objectList -> object : ['$1'] .
objectList -> object ',' objectList : ['$1' | '$3'] .
objectList -> object annotation : ['$1', {annotation, '$2'}] .
objectList -> object annotation ',' objectList : ['$1', {annotation, '$2'} | '$4'] .
blankNodePropertyList -> '[' predicateObjectList ']' : {blankNodePropertyList, '$2'} .
@ -49,12 +52,24 @@ verb -> predicate : '$1' .
subject -> iri : '$1' .
subject -> blankNode : '$1' .
subject -> collection : '$1' .
subject -> quotedTriple : '$1' .
predicate -> iri : '$1' .
object -> iri : '$1' .
object -> blankNode : '$1' .
object -> collection : '$1' .
object -> blankNodePropertyList : '$1' .
object -> literal : '$1' .
object -> quotedTriple : '$1' .
quotedTriple -> '<<' qtSubject verb qtObject '>>' : {quoted_triple, '$2', '$3', '$4' } .
qtSubject -> iri : '$1' .
qtSubject -> blankNode : '$1' .
qtSubject -> quotedTriple : '$1' .
qtObject -> iri : '$1' .
qtObject -> blankNode : '$1' .
qtObject -> literal : '$1' .
qtObject -> quotedTriple : '$1' .
annotation -> '{|' predicateObjectList '|}' : '$2' .
collection -> '(' ')' : {collection, []} .
collection -> '(' collection_elements ')' : {collection, '$2'} .

View file

@ -0,0 +1,40 @@
defmodule RDF.Star.Turtle.W3C.EvalTest do
@moduledoc """
The official RDF-star Turtle eval test suite.
from <https://w3c.github.io/rdf-star/tests/turtle/eval/>
"""
use ExUnit.Case, async: false
@turtle_star_eval_test_suite Path.join(RDF.TestData.dir(), "rdf-star/turtle/eval")
ExUnit.Case.register_attribute(__ENV__, :turtle_test)
@turtle_star_eval_test_suite
|> File.ls!()
|> Enum.filter(fn file -> Path.extname(file) == ".ttl" and file != "manifest.ttl" end)
|> Enum.each(fn file ->
base = Path.basename(file, ".ttl")
if base in [
"turtle-star-eval-bnode-1",
"turtle-star-eval-bnode-2",
# TODO: this one just fails, because our blank node counter starts at 0 instead of 1
"turtle-star-eval-annotation-2"
] do
@tag skip: """
The produced graphs are correct, but have different blank node labels than the result graph.
TODO: Implement a graph isomorphism algorithm.
"""
end
@turtle_test ttl_file: Path.join(@turtle_star_eval_test_suite, file),
nt_file: Path.join(@turtle_star_eval_test_suite, base <> ".nt")
test "eval test: #{file}", context do
assert RDF.Turtle.read_file!(context.registered.turtle_test[:ttl_file])
|> RDF.Graph.clear_metadata() ==
RDF.NTriples.read_file!(context.registered.turtle_test[:nt_file])
end
end)
end

View file

@ -0,0 +1,29 @@
defmodule RDF.Star.Turtle.W3C.SyntaxTest do
@moduledoc """
The official RDF-star Turtle syntax test suite.
from <https://w3c.github.io/rdf-star/tests/turtle/syntax/>
"""
use ExUnit.Case, async: false
@turtle_star_syntax_test_suite Path.join(RDF.TestData.dir(), "rdf-star/turtle/syntax")
ExUnit.Case.register_attribute(__ENV__, :turtle_test)
@turtle_star_syntax_test_suite
|> File.ls!()
|> Enum.filter(fn file -> Path.extname(file) == ".ttl" and file != "manifest.ttl" end)
|> Enum.each(fn file ->
@turtle_test file: Path.join(@turtle_star_syntax_test_suite, file)
if file |> String.contains?("-bad-") do
test "Negative syntax test: #{file}", context do
assert {:error, _} = RDF.Turtle.read_file(context.registered.turtle_test[:file])
end
else
test "Positive syntax test: #{file}", context do
assert {:ok, %RDF.Graph{}} = RDF.Turtle.read_file(context.registered.turtle_test[:file])
end
end
end)
end

View file

@ -0,0 +1,101 @@
## Distributed under both the "W3C Test Suite License" [1]
## and the "W3C 3-clause BSD License".
## [1] https://www.w3.org/Consortium/Legal/2008/04-testsuite-license
## [2] https://www.w3.org/Consortium/Legal/2008/03-bsd-license
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#>
PREFIX test: <http://www.w3.org/2001/sw/DataAccess/tests/>
PREFIX rdft: <http://www.w3.org/ns/rdftest#>
PREFIX trs: <https://w3c.github.io/rdf-star/tests/turtle/eval#>
trs:manifest rdf:type mf:Manifest ;
rdfs:label "Turtle-star Evaluation Tests" ;
mf:entries
(
trs:turtle-star-1
trs:turtle-star-2
trs:turtle-star-bnode-1
trs:turtle-star-bnode-2
trs:turtle-star-annotation-1
trs:turtle-star-annotation-2
trs:turtle-star-annotation-3
trs:turtle-star-annotation-4
trs:turtle-star-annotation-5
trs:turtle-star-quoted-annotation-1
trs:turtle-star-quoted-annotation-2
trs:turtle-star-quoted-annotation-3
) .
trs:turtle-star-1 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - subject quoted triple" ;
mf:action <turtle-star-eval-01.ttl> ;
mf:result <turtle-star-eval-01.nt> ;
.
trs:turtle-star-2 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - object quoted triple" ;
mf:action <turtle-star-eval-02.ttl> ;
mf:result <turtle-star-eval-02.nt> ;
.
trs:turtle-star-bnode-1 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - blank node label" ;
mf:action <turtle-star-eval-bnode-1.ttl> ;
mf:result <turtle-star-eval-bnode-1.nt> ;
.
trs:turtle-star-bnode-2 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - blank node labels" ;
mf:action <turtle-star-eval-bnode-2.ttl> ;
mf:result <turtle-star-eval-bnode-2.nt> ;
.
trs:turtle-star-annotation-1 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation form" ;
mf:action <turtle-star-eval-annotation-1.ttl> ;
mf:result <turtle-star-eval-annotation-1.nt> ;
.
trs:turtle-star-annotation-2 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation example" ;
mf:action <turtle-star-eval-annotation-2.ttl> ;
mf:result <turtle-star-eval-annotation-2.nt> ;
.
trs:turtle-star-annotation-3 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation - predicate and object lists" ;
mf:action <turtle-star-eval-annotation-3.ttl> ;
mf:result <turtle-star-eval-annotation-3.nt> ;
.
trs:turtle-star-annotation-4 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation - nested" ;
mf:action <turtle-star-eval-annotation-4.ttl> ;
mf:result <turtle-star-eval-annotation-4.nt> ;
.
trs:turtle-star-annotation-5 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation object list" ;
mf:action <turtle-star-eval-annotation-5.ttl> ;
mf:result <turtle-star-eval-annotation-5.nt> ;
.
trs:turtle-star-quoted-annotation-1 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation with quoting" ;
mf:action <turtle-star-eval-quoted-annotation-1.ttl> ;
mf:result <turtle-star-eval-quoted-annotation-1.nt> ;
.
trs:turtle-star-quoted-annotation-2 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation on triple with quoted subject" ;
mf:action <turtle-star-eval-quoted-annotation-2.ttl> ;
mf:result <turtle-star-eval-quoted-annotation-2.nt> ;
.
trs:turtle-star-quoted-annotation-3 rdf:type rdft:TestTurtleEval ;
mf:name "Turtle-star - Annotation on triple with quoted object" ;
mf:action <turtle-star-eval-quoted-annotation-3.ttl> ;
mf:result <turtle-star-eval-quoted-annotation-3.nt> ;
.

View file

@ -0,0 +1 @@
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
<<:s :p :o>> :q :z .

View file

@ -0,0 +1 @@
<http://example/a> <http://example/q> << <http://example/s> <http://example/p> <http://example/o> >> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:a :q <<:s :p :o>> .

View file

@ -0,0 +1,2 @@
<http://example/s> <http://example/p> <http://example/o> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/r> <http://example/z> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p :o {| :r :z |} .

View file

@ -0,0 +1,7 @@
<http://example/s> <http://example/p> <http://example/o> .
_:b1 <http://example/graph> <http://host1/> .
_:b1 <http://example/date> "2020-01-20"^^<http://www.w3.org/2001/XMLSchema#date> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/source> _:b1 .
_:b2 <http://example/graph> <http://host2/> .
_:b2 <http://example/date> "2020-12-31"^^<http://www.w3.org/2001/XMLSchema#date> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/source> _:b2 .

View file

@ -0,0 +1,10 @@
PREFIX : <http://example/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
:s :p :o {| :source [ :graph <http://host1/> ;
:date "2020-01-20"^^xsd:date
] ;
:source [ :graph <http://host2/> ;
:date "2020-12-31"^^xsd:date
]
|} .

View file

@ -0,0 +1,6 @@
<http://example/s> <http://example/p> <http://example/o> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/a> <http://example/b> .
<http://example/s> <http://example/p2> <http://example/o2> .
<< <http://example/s> <http://example/p2> <http://example/o2> >> <http://example/a2> <http://example/b2> .
<http://example/s> <http://example/p2> <http://example/o3> .
<< <http://example/s> <http://example/p2> <http://example/o3> >> <http://example/a3> <http://example/b3> .

View file

@ -0,0 +1,5 @@
PREFIX : <http://example/>
:s :p :o {| :a :b |};
:p2 :o2 {| :a2 :b2 |},
:o3 {| :a3 :b3 |}.

View file

@ -0,0 +1,3 @@
<http://example/s> <http://example/p> <http://example/o> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/a> <http://example/b> .
<< << <http://example/s> <http://example/p> <http://example/o> >> <http://example/a> <http://example/b> >> <http://example/a2> <http://example/b2> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p :o {| :a :b {| :a2 :b2 |} |}.

View file

@ -0,0 +1,3 @@
<http://example/s> <http://example/p> <http://example/o1> .
<http://example/s> <http://example/p> <http://example/o2> .
<< <http://example/s> <http://example/p> <http://example/o2> >> <http://example/a> <http://example/b> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o1, :o2 {| :a :b |} .

View file

@ -0,0 +1,2 @@
_:b9 <http://example/p> <http://example/o> .
<< _:b9 <http://example/p> <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
_:b :p :o .
<<_:b :p :o>> :q :z .

View file

@ -0,0 +1,2 @@
_:label1 <http://example/p1> _:label1 .
<< _:label1 <http://example/p1> _:label1 >> <http://example/q> << _:label1 <http://example/p2> <http://example/o> >> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
_:a :p1 _:a .
<<_:a :p1 _:a >> :q <<_:a :p2 :o>> .

View file

@ -0,0 +1,2 @@
<http://example/s> <http://example/p> <http://example/o> .
<<<http://example/s> <http://example/p> <http://example/o>>> <http://example/r> <<<http://example/s1> <http://example/p1> <http://example/o1>>> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p :o {| :r <<:s1 :p1 :o1>> |} .

View file

@ -0,0 +1,2 @@
<<<http://example/s1> <http://example/p1> <http://example/o1>>> <http://example/p> <http://example/o> .
<<<<<http://example/s1> <http://example/p1> <http://example/o1>>> <http://example/p> <http://example/o>>> <http://example/r> <http://example/z> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
<<:s1 :p1 :o1>> :p :o {| :r :z |} .

View file

@ -0,0 +1,2 @@
<http://example/s> <http://example/p> <<<http://example/s2> <http://example/p2> <http://example/o2>>> .
<<<http://example/s> <http://example/p> <<<http://example/s2> <http://example/p2> <http://example/o2>>>>> <http://example/r> <http://example/z> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p <<:s2 :p2 :o2>> {| :r :z |} .

View file

@ -0,0 +1,259 @@
## Distributed under both the "W3C Test Suite License" [1]
## and the "W3C 3-clause BSD License".
## [1] https://www.w3.org/Consortium/Legal/2008/04-testsuite-license
## [2] https://www.w3.org/Consortium/Legal/2008/03-bsd-license
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#>
PREFIX test: <http://www.w3.org/2001/sw/DataAccess/tests/>
PREFIX rdft: <http://www.w3.org/ns/rdftest#>
PREFIX trs: <https://w3c.github.io/rdf-star/tests/turtle/syntax#>
trs:manifest rdf:type mf:Manifest ;
rdfs:label "Turtle-star Syntax Tests" ;
mf:entries
(
trs:turtle-star-1
trs:turtle-star-2
trs:turtle-star-inside-1
trs:turtle-star-inside-2
trs:turtle-star-nested-1
trs:turtle-star-nested-2
trs:turtle-star-compound-1
trs:turtle-star-bnode-1
trs:turtle-star-bnode-2
trs:turtle-star-bnode-3
trs:turtle-star-bad-1
trs:turtle-star-bad-2
trs:turtle-star-bad-3
trs:turtle-star-bad-4
trs:turtle-star-bad-5
trs:turtle-star-bad-6
trs:turtle-star-bad-7
trs:turtle-star-bad-8
trs:turtle-star-ann-1
trs:turtle-star-ann-2
trs:turtle-star-bad-ann-1
trs:turtle-star-bad-ann-2
## The same data as the N-Triples-star syntax tests,
## except in file *.ttl and "TestTurtle"
trs:nt-ttl-star-1
trs:nt-ttl-star-2
trs:nt-ttl-star-3
trs:nt-ttl-star-4
trs:nt-ttl-star-5
trs:nt-ttl-star-bnode-1
trs:nt-ttl-star-bnode-2
trs:nt-ttl-star-nested-1
trs:nt-ttl-star-nested-2
trs:nt-ttl-star-bad-1
trs:nt-ttl-star-bad-2
trs:nt-ttl-star-bad-3
trs:nt-ttl-star-bad-4
) .
## Good Syntax
trs:turtle-star-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - subject quoted triple" ;
mf:action <turtle-star-syntax-basic-01.ttl> ;
.
trs:turtle-star-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - object quoted triple" ;
mf:action <turtle-star-syntax-basic-02.ttl> ;
.
trs:turtle-star-inside-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - quoted triple inside blankNodePropertyList" ;
mf:action <turtle-star-syntax-inside-01.ttl> ;
.
trs:turtle-star-inside-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - quoted triple inside collection" ;
mf:action <turtle-star-syntax-inside-02.ttl> ;
.
trs:turtle-star-nested-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - nested quoted triple, subject position" ;
mf:action <turtle-star-syntax-nested-01.ttl> ;
.
trs:turtle-star-nested-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - nested quoted triple, object position" ;
mf:action <turtle-star-syntax-nested-02.ttl> ;
.
trs:turtle-star-compound-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - compound forms" ;
mf:action <turtle-star-syntax-compound.ttl> ;
.
trs:turtle-star-bnode-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - blank node subject" ;
mf:action <turtle-star-syntax-bnode-01.ttl> ;
.
trs:turtle-star-bnode-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - blank node object" ;
mf:action <turtle-star-syntax-bnode-02.ttl> ;
.
trs:turtle-star-bnode-3 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - blank node" ;
mf:action <turtle-star-syntax-bnode-03.ttl> ;
.
## Bad Syntax
trs:turtle-star-bad-1 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - quoted triple as predicate" ;
mf:action <turtle-star-syntax-bad-01.ttl> ;
.
trs:turtle-star-bad-2 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - quoted triple outside triple" ;
mf:action <turtle-star-syntax-bad-02.ttl> ;
.
trs:turtle-star-bad-3 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - collection list in quoted triple" ;
mf:action <turtle-star-syntax-bad-03.ttl> ;
.
trs:turtle-star-bad-4 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - literal in subject position of quoted triple" ;
mf:action <turtle-star-syntax-bad-04.ttl> ;
.
trs:turtle-star-bad-5 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - blank node as predicate in quoted triple";
mf:action <turtle-star-syntax-bad-05.ttl> ;
.
trs:turtle-star-bad-6 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - compound blank node expression";
mf:action <turtle-star-syntax-bad-06.ttl> ;
.
trs:turtle-star-bad-7 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - incomplete quoted triple";
mf:action <turtle-star-syntax-bad-07.ttl> ;
.
trs:turtle-star-bad-8 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - over-long quoted triple";
mf:action <turtle-star-syntax-bad-08.ttl> ;
.
## Annotation syntax
trs:turtle-star-ann-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - Annotation form" ;
mf:action <turtle-star-annotation-1.ttl> ;
.
trs:turtle-star-ann-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "Turtle-star - Annotation example" ;
mf:action <turtle-star-annotation-2.ttl> ;
.
## Bad annotation syntax
trs:turtle-star-bad-ann-1 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - empty annotation" ;
mf:action <turtle-star-syntax-bad-ann-1.ttl> ;
.
trs:turtle-star-bad-ann-2 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "Turtle-star - bad - triple as annotation" ;
mf:action <turtle-star-syntax-bad-ann-2.ttl> ;
.
## --------------------------------------------------
## Same data as the N-triples-star tests.
## N-Triples is a subset of Turtle, and the same is true for the "star" feature.
## Good Syntax
trs:nt-ttl-star-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - subject quoted triple" ;
mf:action <nt-ttl-star-syntax-1.ttl> ;
.
trs:nt-ttl-star-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - object quoted triple" ;
mf:action <nt-ttl-star-syntax-2.ttl> ;
.
trs:nt-ttl-star-3 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - subject and object quoted triples" ;
mf:action <nt-ttl-star-syntax-3.ttl> ;
.
trs:nt-ttl-star-4 rdf:type rdft:TestNTriplesPositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - whitespace and terms" ;
mf:action <nt-ttl-star-syntax-4.ttl> ;
.
trs:nt-ttl-star-5 rdf:type rdft:TestNTriplesPositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - Nested, no whitespace" ;
mf:action <nt-ttl-star-syntax-5.ttl> ;
.
# Blank nodes
trs:nt-ttl-star-bnode-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - Blank node subject" ;
mf:action <nt-ttl-star-bnode-1.ttl> ;
.
trs:nt-ttl-star-bnode-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - Blank node object" ;
mf:action <nt-ttl-star-bnode-2.ttl> ;
.
trs:nt-ttl-star-nested-1 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - Nested subject term" ;
mf:action <nt-ttl-star-nested-1.ttl> ;
.
trs:nt-ttl-star-nested-2 rdf:type rdft:TestTurtlePositiveSyntax ;
mf:name "N-Triples-star as Turtle-star - Nested object term" ;
mf:action <nt-ttl-star-nested-2.ttl> ;
.
## Bad syntax
trs:nt-ttl-star-bad-1 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "N-Triples-star as Turtle-star - Bad - quoted triple as predicate" ;
mf:action <nt-ttl-star-bad-syntax-1.ttl> ;
.
trs:nt-ttl-star-bad-2 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "N-Triples-star as Turtle-star - Bad - quoted triple, literal subject" ;
mf:action <nt-ttl-star-bad-syntax-2.ttl> ;
.
trs:nt-ttl-star-bad-3 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "N-Triples-star as Turtle-star - Bad - quoted triple, literal predicate" ;
mf:action <nt-ttl-star-bad-syntax-3.ttl> ;
.
trs:nt-ttl-star-bad-4 rdf:type rdft:TestTurtleNegativeSyntax ;
mf:name "N-Triples-star as Turtle-star - Bad - quoted triple, blank node predicate" ;
mf:action <nt-ttl-star-bad-syntax-4.ttl> ;
.

View file

@ -0,0 +1 @@
<http://example/a> << <http://example/s> <http://example/p> <http://example/o> >> <http://example/z> .

View file

@ -0,0 +1 @@
<< "XYZ" <http://example/p> <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1 @@
<< <http://example/s> "XYZ" <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1 @@
<< <http://example/s> _:label <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1,2 @@
_:b0 <http://example/p> <http://example/o> .
<< _:b0 <http://example/p> <http://example/o> >> <http://example/q> "ABC" .

View file

@ -0,0 +1,2 @@
<http://example/s> <http://example/p> _:b1 .
<< <http://example/s> <http://example/p> _:b1 >> <http://example/q> "456"^^<http://www.w3.org/2001/XMLSchema#integer> .

View file

@ -0,0 +1,3 @@
<http://example/s> <http://example/p> <http://example/o> .
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/r> <http://example/z> .
<< << <http://example/s> <http://example/p> <http://example/o> >> <http://example/r> <http://example/z> >> <http://example/q> "1"^^<http://www.w3.org/2001/XMLSchema#integer> .

View file

@ -0,0 +1,3 @@
<http://example/s> <http://example/p> <http://example/o> .
<http://example/a> <http://example/q> << <http://example/s> <http://example/p> <http://example/o> >> .
<< <http://example/a> <http://example/q> << <http://example/s> <http://example/p> <http://example/o> >> >> <http://example/r> <http://example/z> .

View file

@ -0,0 +1 @@
<< <http://example/s> <http://example/p> <http://example/o> >> <http://example/q> <http://example/z> .

View file

@ -0,0 +1 @@
<http://example/x> <http://example/p> << <http://example/s> <http://example/p> <http://example/o> >> .

View file

@ -0,0 +1 @@
<< <http://example/s1> <http://example/p1> <http://example/o1> >> <http://example/q> << <http://example/s2> <http://example/p2> <http://example/o2> >> .

View file

@ -0,0 +1 @@
<<<http://example/s1><http://example/p1><http://example/o1>>><http://example/q><<<http://example/s2><http://example/p2><http://example/o2>>>.

View file

@ -0,0 +1 @@
<<<<<http://example/s1><http://example/p1><http://example/o1>>><http://example/q1><<<http://example/s2><http://example/p2><http://example/o2>>>>><http://example/q2><<<<<http://example/s3><http://example/p3><http://example/o3>>><http://example/q3><<<http://example/s4><http://example/p4><http://example/o4>>>>>.

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p :o {| :r :z |} .

View file

@ -0,0 +1,10 @@
PREFIX : <http://example/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
:s :p :o {| :source [ :graph <http://host1/> ;
:date "2020-01-20"^^xsd:date
] ;
:source [ :graph <http://host2/> ;
:date "2020-12-31"^^xsd:date
]
|} .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
:x <<:s :p :o>> 123 .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
<<:s :p :o>> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p ("abc") .
<<:s :p ("abc") >> :q 123 .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
<<3 :p :o >> :q :z .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
<<:s [] :o>> :q 123 .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
<<:s :p [ :p1 :o1 ] >> :q 123 .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p << :p :r >> .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
:s :p << :g :s :p :o >> .

View file

@ -0,0 +1,6 @@
PREFIX : <http://example.com/ns#>
SELECT * {
:s :p :o {| |} .
}

View file

@ -0,0 +1,3 @@
PREFIX : <http://example.com/ns#>
:a :b :c {| :s :p :o |} .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
<<:s :p :o>> :q 123 .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
:x :p <<:s :p :o>> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
_:a :p :o .
<<_:a :p :o >> :q 456 .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p _:a .
<<:s :p _:a >> :q 456 .

View file

@ -0,0 +1,3 @@
PREFIX : <http://example/>
<<[] :p [] >> :q :z .

View file

@ -0,0 +1,11 @@
PREFIX : <http://example/>
:x :r :z .
:a :b :c .
<<:a :b :c>> :r :z .
<<:x :r :z >> :p <<:a :b :c>> .
<< <<:x :r :z >> :p <<:a :b :c>> >>
:q
<< <<:x :r :z >> :p <<:a :b :c>> >> .

View file

@ -0,0 +1,4 @@
PREFIX : <http://example/>
:s :p :o .
[ :q <<:s :p :o>> ] :b :c .

View file

@ -0,0 +1,5 @@
PREFIX : <http://example/>
:s :p :o1 .
:s :p :o2 .
( <<:s :p :o1>> <<:s :p :o2>> ) :q 123 .

View file

@ -0,0 +1,7 @@
PREFIX : <http://example/>
:s :p :o .
<<:s :p :o >> :r :z .
<< <<:s :p :o >> :r :z >> :q 1 .

View file

@ -0,0 +1,5 @@
PREFIX : <http://example/>
:s :p :o .
:a :q <<:s :p :o >> .
<< :a :q <<:s :p :o >>>> :r :z .

View file

@ -11,15 +11,15 @@ defmodule RDF.Star.NTriples.EncoderTest do
end
test "annotations of triples on object position" do
assert NTriples.Encoder.encode!(
Graph.new([
statement(),
{EX.AS, EX.ap(), statement()},
])
) ==
"""
<http://example.com/AS> <http://example.com/ap> << <http://example.com/S> <http://example.com/P> "Foo" >> .
<http://example.com/S> <http://example.com/P> "Foo" .
"""
assert NTriples.Encoder.encode!(
Graph.new([
statement(),
{EX.AS, EX.ap(), statement()}
])
) ==
"""
<http://example.com/AS> <http://example.com/ap> << <http://example.com/S> <http://example.com/P> "Foo" >> .
<http://example.com/S> <http://example.com/P> "Foo" .
"""
end
end