rdf-n3 0.2.3.2 → 0.3.0

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.
Files changed (44) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +4 -3
  3. data/{History.txt → History.md} +30 -6
  4. data/{README.rdoc → README.md} +56 -19
  5. data/Rakefile +15 -29
  6. data/VERSION +1 -1
  7. data/example-files/sp2b.n3 +50177 -0
  8. data/lib/rdf/n3.rb +2 -2
  9. data/lib/rdf/n3/reader.rb +560 -367
  10. data/lib/rdf/n3/reader/meta.rb +640 -0
  11. data/lib/rdf/n3/reader/n3-selectors.n3 +0 -0
  12. data/lib/rdf/n3/reader/parser.rb +229 -0
  13. data/lib/rdf/n3/vocab.rb +1 -0
  14. data/lib/rdf/n3/writer.rb +324 -265
  15. data/rdf-n3.gemspec +24 -26
  16. data/script/build_meta +242 -0
  17. data/script/parse +62 -13
  18. data/script/tc +4 -4
  19. data/spec/cwm_spec.rb +11 -3
  20. data/spec/n3reader_spec.rb +233 -63
  21. data/spec/rdf_helper.rb +15 -15
  22. data/spec/spec_helper.rb +10 -4
  23. data/spec/swap_spec.rb +11 -35
  24. data/spec/swap_test/n3parser.tests +14 -14
  25. data/spec/swap_test/n3parser.yml +0 -19
  26. data/spec/swap_test/nodeID/classes.ref.rdf +1 -1
  27. data/spec/swap_test/ref/contexts-1.n3 +12 -0
  28. data/spec/swap_test/ref/prefix2.rdf +33 -0
  29. data/spec/swap_test/ref/strquot.n3 +0 -1
  30. data/spec/swap_test/ref/xml-syntax-basic-serialization.rdf +1 -1
  31. data/spec/swap_test/regression.n3 +5 -5
  32. data/spec/swap_test/regression.yml +53 -23
  33. data/spec/turtle/manifest-bad.yml +91 -0
  34. data/spec/turtle/manifest.yml +187 -0
  35. data/spec/turtle_spec.rb +12 -20
  36. data/spec/writer_spec.rb +39 -37
  37. metadata +43 -48
  38. data/lib/rdf/n3/patches/qname_hacks.rb +0 -57
  39. data/lib/rdf/n3/patches/seq.rb +0 -34
  40. data/lib/rdf/n3/reader/n3_grammar.rb +0 -3764
  41. data/lib/rdf/n3/reader/n3_grammar.treetop +0 -227
  42. data/lib/rdf/n3/reader/n3_grammar_18.rb +0 -3764
  43. data/lib/rdf/n3/reader/n3_grammar_18.treetop +0 -227
  44. data/spec/literal_spec.rb +0 -245
data/script/tc CHANGED
@@ -2,12 +2,12 @@
2
2
  require 'rubygems'
3
3
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
4
4
  require 'rdf/n3'
5
- require 'spec/rdf_helper'
5
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", 'spec', 'rdfa_helper'))
6
6
  require 'getoptlong'
7
7
 
8
8
  def run_tc(tc)
9
9
  puts "run #{tc.name}"
10
- puts RDF::Writer.for($format.to_sym).buffer { |writer|
10
+ puts RDF::Writer.for($output_format.to_sym).buffer { |writer|
11
11
  RDF::N3::Reader.new(tc.input, :base_uri => tc.about, :strict => $strict).each do |statement|
12
12
  writer << statement
13
13
  end
@@ -15,7 +15,7 @@ def run_tc(tc)
15
15
  end
16
16
 
17
17
  $verbose = false
18
- $format = :ntriples
18
+ $output_format = :ntriples
19
19
  $strict = false
20
20
  suite = "turtle"
21
21
  opts = GetoptLong.new(
@@ -31,7 +31,7 @@ opts.each do |opt, arg|
31
31
  when '--verbose' then $verbose = true
32
32
  when '--quiet' then $quiet = true
33
33
  when '--debug' then ::RDF::N3::debug = true
34
- when '--format' then $format = arg
34
+ when '--format' then $output_format = arg
35
35
  when '--suite' then suite = arg
36
36
  when '--strict' then $strict = true
37
37
  end
@@ -12,11 +12,19 @@ describe RDF::N3::Reader do
12
12
 
13
13
  # Negative parser tests should raise errors.
14
14
  test_cases.each do |t|
15
+ next unless t.about.to_s =~ /n3$/
15
16
  #next unless t.about.uri.to_s =~ /rdfms-rdf-names-use/
16
- #next unless t.name =~ /11/
17
+ #next unless t.name =~ /1018/
17
18
  #puts t.inspect
18
- specify "test #{t.name}: " + (t.description || "#{t.inputDocument} against #{t.outputDocument}") do
19
+ specify "test #{t.name}: #{t.description}: #{t.inputDocument} against #{t.outputDocument}" do
19
20
  begin
21
+ if t.name =~ /1018/
22
+ pending("matcher does not stop")
23
+ next
24
+ elsif t.rdf_type == "CwmProofTest"
25
+ pending("proofs not supported")
26
+ next
27
+ end
20
28
  t.run_test do |rdf_string|
21
29
  t.debug = []
22
30
  g = RDF::Graph.new
@@ -28,7 +36,7 @@ describe RDF::N3::Reader do
28
36
  end
29
37
  g
30
38
  end
31
- rescue #Spec::Expectations::ExpectationNotMetError => e
39
+ rescue RSpec::Expectations::ExpectationNotMetError => e
32
40
  if t.status == "pending"
33
41
  pending("Formulae not supported") { raise }
34
42
  else
@@ -264,7 +264,7 @@ describe "RDF::N3::Reader" do
264
264
  it "should allow mixed-case language" do
265
265
  n3doc = %(:x2 :p "xyz"@EN .)
266
266
  statement = parse(n3doc).statements.first
267
- statement.object.to_ntriples.should == %("xyz"@en)
267
+ statement.object.to_ntriples.should == %("xyz"@EN)
268
268
  end
269
269
 
270
270
  it "should create typed literals" do
@@ -343,32 +343,13 @@ describe "RDF::N3::Reader" do
343
343
  end
344
344
  end
345
345
 
346
- # describe "with illegal syntax" do
347
- # {
348
- # %(:y :p1 "xyz"^^xsd:integer .) => %r(Typed literal has an invalid lexical value: .* "xyz"),
349
- # %(:y :p1 "12xyz"^^xsd:integer .) => %r(Typed literal has an invalid lexical value: .* "12xyz"),
350
- # %(:y :p1 "xy.z"^^xsd:double .) => %r(Typed literal has an invalid lexical value: .* "xy\.z"),
351
- # %(:y :p1 "+1.0z"^^xsd:double .) => %r(Typed literal has an invalid lexical value: .* "\+1.0z"),
352
- # %(:a :b .) => %r(Illegal statment: ".*" missing object),
353
- # %(:a :b 'single quote' .) => RDF::ReaderError,
354
- # %(:a "literal value" :b .) => RDF::ReaderError,
355
- # %(@keywords prefix. :e prefix :f .) => %r(Keyword ".*" used as expression)
356
- # }.each_pair do |n3, error|
357
- # it "should raise error for '#{n3}'" do
358
- # lambda {
359
- # parse("@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{n3}", :base_uri => "http://a/b")
360
- # }.should raise_error(error)
361
- # end
362
- # end
363
- # end
364
-
365
- describe "with n3 grammer" do
346
+ describe "with n3 grammar" do
366
347
  describe "syntactic expressions" do
367
348
  it "should create typed literals with qname" do
368
349
  n3doc = %(
369
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
370
- @prefix foaf: <http://xmlns.com/foaf/0.1/>
371
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#>
350
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
351
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
352
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
372
353
  <http://example.org/joe> foaf:name \"Joe\"^^xsd:string .
373
354
  )
374
355
  statement = parse(n3doc).statements.first
@@ -482,16 +463,50 @@ describe "RDF::N3::Reader" do
482
463
  parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
483
464
  end
484
465
 
485
- it "should do something for @forAll" do
486
- pending
466
+ it "substitutes variable for URI with @forAll" do
467
+ n3 = %(@forAll :x . :x :y :z .)
468
+ g = parse(n3, :base_uri => "http://a/b")
469
+ statement = g.statements.first
470
+ statement.subject.should be_a(RDF::Query::Variable)
471
+ statement.predicate.to_s.should == "http://a/b#y"
472
+ statement.object.to_s.should == "http://a/b#z"
473
+ end
474
+
475
+ it "substitutes variable for URIs with @forAll" do
476
+ n3 = %(@forAll :x, :y, :z . :x :y :z .)
477
+ g = parse(n3, :base_uri => "http://a/b")
478
+ statement = g.statements.first
479
+ statement.subject.should be_a(RDF::Query::Variable)
480
+ statement.predicate.should be_a(RDF::Query::Variable)
481
+ statement.object.should be_a(RDF::Query::Variable)
482
+ statement.subject.should_not == statement.predicate
483
+ statement.object.should_not == statement.predicate
484
+ statement.predicate.should_not == statement.object
487
485
  end
488
486
 
489
- it "should do something for @forSome" do
490
- pending
487
+ it "substitutes node for URI with @forEach" do
488
+ n3 = %(@forSome :x . :x :y :z .)
489
+ g = parse(n3, :base_uri => "http://a/b")
490
+ statement = g.statements.first
491
+ statement.subject.should be_a(RDF::Node)
492
+ statement.predicate.to_s.should == "http://a/b#y"
493
+ statement.object.to_s.should == "http://a/b#z"
494
+ end
495
+
496
+ it "substitutes node for URIs with @forEach" do
497
+ n3 = %(@forSome :x, :y, :z . :x :y :z .)
498
+ g = parse(n3, :base_uri => "http://a/b")
499
+ statement = g.statements.first
500
+ statement.subject.should be_a(RDF::Node)
501
+ statement.predicate.should be_a(RDF::Node)
502
+ statement.object.should be_a(RDF::Node)
503
+ statement.subject.should_not == statement.predicate
504
+ statement.object.should_not == statement.predicate
505
+ statement.predicate.should_not == statement.object
491
506
  end
492
507
  end
493
508
 
494
- describe "namespaces" do
509
+ describe "prefixes" do
495
510
  it "should not append # for http://foo/bar" do
496
511
  n3 = %(@prefix : <http://foo/bar> . :a : :b .)
497
512
  nt = %(
@@ -562,11 +577,27 @@ describe "RDF::N3::Reader" do
562
577
  )
563
578
  parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
564
579
  end
580
+
581
+ it "returns defined prefixes" do
582
+ n3 = %(
583
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
584
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
585
+ @prefix : <http://test/> .
586
+ :foo a rdfs:Class.
587
+ :bar :d :c.
588
+ :a :d :c.
589
+ )
590
+ reader = RDF::N3::Reader.new(n3)
591
+ reader.each {|statement|}
592
+ reader.prefixes.should == {
593
+ :rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
594
+ :rdfs => "http://www.w3.org/2000/01/rdf-schema#",
595
+ nil => "http://test/"}
596
+ end
565
597
  end
566
598
 
567
599
  describe "keywords" do
568
600
  [
569
- %(prefix :<>.),
570
601
  %(base <>.),
571
602
  %(keywords a.),
572
603
  %(:a is :b of :c.),
@@ -577,10 +608,19 @@ describe "RDF::N3::Reader" do
577
608
  it "should require @ if keywords set to empty for '#{n3}'" do
578
609
  lambda do
579
610
  parse("@keywords . #{n3}", :base_uri => "http://a/b")
580
- end.should raise_error(/unqualified keyword '\w+' used without @keyword directive/)
611
+ end.should raise_error(RDF::ReaderError)
581
612
  end
582
613
  end
583
614
 
615
+ [
616
+ %(prefix :<>.),
617
+ ].each do |n3|
618
+ it "parses as local name if keywords set to empty for '#{n3}'" do
619
+ lambda do
620
+ parse("@keywords . #{n3}", :base_uri => "http://a/b")
621
+ end.should_not raise_error(RDF::ReaderError)
622
+ end
623
+ end
584
624
  {
585
625
  %(:a a :b) => %(<http://a/b#a> <http://a/b#a> <http://a/b#b> .),
586
626
  %(:a :b true) => %(<http://a/b#a> <http://a/b#b> <http://a/b#true> .),
@@ -611,7 +651,7 @@ describe "RDF::N3::Reader" do
611
651
  n3 = %(@keywords foo.)
612
652
  lambda do
613
653
  parse(n3, :base_uri => "http://a/b")
614
- end.should raise_error(RDF::ReaderError, "undefined keywords used: foo")
654
+ end.should raise_error(RDF::ReaderError, /Undefined keywords used: foo/)
615
655
  end
616
656
  end
617
657
 
@@ -744,12 +784,6 @@ describe "RDF::N3::Reader" do
744
784
  end
745
785
 
746
786
  describe "from paths" do
747
- it "should create bnode for path x.p" do
748
- n3 = %(:x2.:y2 :p2 "3" .)
749
- nt = %(:x2 :y2 _:bnode0 . _:bnode0 :p2 "3" .)
750
- parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
751
- end
752
-
753
787
  it "should create bnode for path x!p" do
754
788
  n3 = %(:x2!:y2 :p2 "3" .)
755
789
  nt = %(:x2 :y2 _:bnode0 . _:bnode0 :p2 "3" .)
@@ -794,7 +828,7 @@ describe "RDF::N3::Reader" do
794
828
  it "should decode path with property list." do
795
829
  n3 = %(
796
830
  @prefix a: <http://a/ns#>.
797
- :a2.a:b2.a:c2 :q1 "3" ; :q2 "4" , "5" .
831
+ :a2!a:b2!a:c2 :q1 "3" ; :q2 "4" , "5" .
798
832
  )
799
833
  nt = %(
800
834
  :a2 <http://a/ns#b2> _:bnode0 .
@@ -816,7 +850,7 @@ describe "RDF::N3::Reader" do
816
850
  end
817
851
 
818
852
  it "should decode path as object(2)" do
819
- n3 = %(@prefix a: <http://a/ns#>. :r :p :o.a:p1.a:p2 .)
853
+ n3 = %(@prefix a: <http://a/ns#>. :r :p :o!a:p1!a:p2 .)
820
854
  nt = %(
821
855
  :o <http://a/ns#p1> _:bnode0 .
822
856
  _:bnode0 <http://a/ns#p2> _:bnode1 .
@@ -828,12 +862,67 @@ describe "RDF::N3::Reader" do
828
862
  end
829
863
 
830
864
  describe "formulae" do
831
- it "should require that graph be formula_aware when encountering a formlua" do
832
- pending
865
+ before(:each) { @repo = RDF::Repository.new }
866
+
867
+ it "creates an RDF::Graph instance for formula" do
868
+ n3 = %(:a :b {})
869
+ parse(n3, :graph => @repo, :base_uri => "http://a/b")
870
+ statement = @repo.statements.first
871
+ statement.object.should be_a(RDF::Node)
872
+ end
873
+
874
+ it "adds statements with context" do
875
+
876
+ end
877
+
878
+ it "creates variables with ?" do
879
+
833
880
  end
834
881
 
835
- it "should separate triples between specified and quoted graphs" do
836
- pending
882
+ context "contexts" do
883
+ before(:each) do
884
+ n3 = %(
885
+ # Test data in notation3 http://www.w3.org/DesignIssues/Notation3.html
886
+ #
887
+ @prefix u: <http://www.example.org/utilities#> .
888
+ @prefix : <#> .
889
+
890
+ :assumption = { :fred u:knows :john .
891
+ :john u:knows :mary .} .
892
+
893
+ :conclusion = { :fred u:knows :mary . } .
894
+
895
+ # The empty context is trivially true.
896
+ # Check that we can input it and output it!
897
+
898
+ :trivialTruth = { }.
899
+
900
+ # ENDS
901
+ )
902
+ @repo = RDF::Repository.new
903
+ parse(n3, :graph => @repo, :base_uri => "http://a/b")
904
+ end
905
+
906
+ it "assumption graph has 2 statements" do
907
+ tt = @repo.first(:subject => RDF::URI.new("http://a/b#assumption"), :predicate => RDF::OWL.sameAs)
908
+ tt.object.should be_a(RDF::Node)
909
+ @repo.query(:context => tt.object).to_a.length.should == 2
910
+ end
911
+
912
+ it "conclusion graph has 1 statements" do
913
+ tt = @repo.first(:subject => RDF::URI.new("http://a/b#conclusion"), :predicate => RDF::OWL.sameAs)
914
+ tt.object.should be_a(RDF::Node)
915
+ @repo.query(:context => tt.object).to_a.length.should == 1
916
+ end
917
+
918
+ it "trivialTruth equivalent to empty graph" do
919
+ tt = @repo.first(:subject => RDF::URI.new("http://a/b#trivialTruth"), :predicate => RDF::OWL.sameAs)
920
+ tt.object.should be_a(RDF::Node)
921
+ @repo.query(:context => tt.object) do |s|
922
+ puts "statement: #{s}"
923
+ end
924
+ end
925
+
837
926
  end
838
927
  end
839
928
 
@@ -919,34 +1008,43 @@ describe "RDF::N3::Reader" do
919
1008
  nt = %(<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://foo/a#prop> "nilProp" .)
920
1009
  parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
921
1010
  end
1011
+
922
1012
  it "should parse with compound items" do
923
1013
  n3 = %(
924
- @prefix a: <http://foo/a#> .
925
-
926
- a:a a:p ( [ a:p2 "v1" ]
927
- <http://resource1>
928
- <http://resource2>
929
- ("inner list") ) .
930
-
931
- <http://resource1> a:p "value" .
1014
+ @prefix a: <http://foo/a#> .
1015
+ a:a a:p (
1016
+ [ a:p2 "v1" ]
1017
+ <http://resource1>
1018
+ <http://resource2>
1019
+ ("inner list")
1020
+ ) .
1021
+ <http://resource1> a:p "value" .
932
1022
  )
933
1023
  nt = %(
934
- <http://foo/a#a> <http://foo/a#p> _:bnode5 .
935
- _:bnode5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:bnode4 .
936
- _:bnode5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:bnode2 .
937
- _:bnode4 <http://foo/a#p2> "v1" .
938
- _:bnode2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://resource1> .
1024
+ <http://foo/a#a> <http://foo/a#p> _:bnode3 .
939
1025
  <http://resource1> <http://foo/a#p> "value" .
1026
+ _:bnode3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:bnode5 .
1027
+ _:bnode3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:bnode2 .
1028
+ _:bnode5 <http://foo/a#p2> "v1" .
1029
+ _:bnode2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://resource1> .
940
1030
  _:bnode2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:bnode1 .
941
1031
  _:bnode1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://resource2> .
942
1032
  _:bnode1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:bnode0 .
943
- _:bnode0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:bnode3 .
1033
+ _:bnode0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:bnode4 .
944
1034
  _:bnode0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
945
- _:bnode3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "inner list" .
946
- _:bnode3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
1035
+ _:bnode4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "inner list" .
1036
+ _:bnode4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
947
1037
  )
948
1038
  g = parse(n3, :base_uri => "http://a/b")
949
- normalize_bnodes(g, "bnode0").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array)
1039
+ g.subjects.to_a.length.should == 8
1040
+ n = g.first_object(:subject => RDF::URI.new("http://foo/a#a"), :predicate => RDF::URI.new("http://foo/a#p"))
1041
+ n.should be_a(RDF::Node)
1042
+ seq = RDF::List.new(n, g)
1043
+ seq.to_a.length.should == 4
1044
+ seq.first.should be_a(RDF::Node)
1045
+ seq.second.should == RDF::URI.new("http://resource1")
1046
+ seq.third.should == RDF::URI.new("http://resource2")
1047
+ seq.fourth.should be_a(RDF::Node)
950
1048
  end
951
1049
 
952
1050
  end
@@ -1031,6 +1129,78 @@ describe "RDF::N3::Reader" do
1031
1129
  end
1032
1130
  end
1033
1131
 
1132
+ describe "canonicalization" do
1133
+ # {
1134
+ # "<http://foo>" => "<http://foo>",
1135
+ # "<http://foo/a>" => "<http://foo/a>",
1136
+ # "<http://foo#a>" => "<http://foo#a>",
1137
+ #
1138
+ # "<http://foo/>" => "<http://foo/>",
1139
+ # "<http://foo/#a>" => "<http://foo/#a>",
1140
+ #
1141
+ # "<http://foo#>" => "<http://foo#>",
1142
+ # "<http://foo#a>" => "<http://foo/a>",
1143
+ # "<http://foo#/a>" => "<http://foo/a>",
1144
+ # "<http://foo##a>" => "<http://foo#a>",
1145
+ #
1146
+ # "<http://foo/bar>" => "<http://foo/bar>",
1147
+ # "<http://foo/bar>" => "<http://foo/a>",
1148
+ # "<http://foo/bar/a>" => "<http://foo/a>",
1149
+ # "<http://foo/bar#a>" => "<http://foo/bar#a>",
1150
+ #
1151
+ # "<http://foo/bar/>" => "<http://foo/bar/>",
1152
+ # "<http://foo/bar/a>" => "<http://foo/bar/a>",
1153
+ # "<http://foo/bar//a>" => "<http://foo/a>",
1154
+ # "<http://foo/bar/#a>" => "<http://foo/bar/#a>",
1155
+ #
1156
+ # "<http://foo/bar#>" => "<http://foo/bar#>",
1157
+ # "<http://foo/bar#a>" => "<http://foo/a>",
1158
+ # "<http://foo/bar#/a>" => "<http://foo/a>",
1159
+ # "<http://foo/bar##a>" => "<http://foo/bar#a>",
1160
+ #
1161
+ # "<http://foo/bar##D%C3%BCrst>" => "<http://foo/bar#D%C3%BCrst>",
1162
+ # "<http://foo/bar##Dürst>" => "<http://foo/bar#D\\u00FCrst>",
1163
+ # }.each_pair do |input, result|
1164
+ # it "returns subject #{result} given #{input}" do
1165
+ # n3 = %(#{input} a :b)
1166
+ # nt = %(#{result} <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://a/b#b> .)
1167
+ # parse(n3, :base_uri => "http://a/b", :canonicalize => true).should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
1168
+ # end
1169
+ # end
1170
+
1171
+ {
1172
+ %("+1"^^xsd:integer) => %("1"^^<http://www.w3.org/2001/XMLSchema#integer>),
1173
+ %(+1) => %("1"^^<http://www.w3.org/2001/XMLSchema#integer>),
1174
+ %(true) => %("true"^^<http://www.w3.org/2001/XMLSchema#boolean>),
1175
+ %("lang"@EN) => %("lang"@en),
1176
+ }.each_pair do |input, result|
1177
+ it "returns object #{result} given #{input}" do
1178
+ n3 = %(@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . :a :b #{input} .)
1179
+ nt = %(<http://a/b#a> <http://a/b#b> #{result} .)
1180
+ parse(n3, :base_uri => "http://a/b", :canonicalize => true).should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug)
1181
+ end
1182
+ end
1183
+ end
1184
+
1185
+ describe "validation" do
1186
+ {
1187
+ %(:y :p1 "xyz"^^xsd:integer .) => %r("xyz" is not a valid .*),
1188
+ %(:y :p1 "12xyz"^^xsd:integer .) => %r("12xyz" is not a valid .*),
1189
+ %(:y :p1 "xy.z"^^xsd:double .) => %r("xy\.z" is not a valid .*),
1190
+ %(:y :p1 "+1.0z"^^xsd:double .) => %r("\+1.0z" is not a valid .*),
1191
+ %(:a :b .) =>RDF::ReaderError,
1192
+ %(:a :b 'single quote' .) => RDF::ReaderError,
1193
+ %(:a "literal value" :b .) => RDF::ReaderError,
1194
+ %(@keywords prefix. :e prefix :f .) => RDF::ReaderError
1195
+ }.each_pair do |n3, error|
1196
+ it "should raise '#{error}' for '#{n3}'" do
1197
+ lambda {
1198
+ parse("@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{n3}", :base_uri => "http://a/b", :validate => true)
1199
+ }.should raise_error(error)
1200
+ end
1201
+ end
1202
+ end
1203
+
1034
1204
  it "should parse rdf_core testcase" do
1035
1205
  sampledoc = <<-EOF;
1036
1206
  <http://www.w3.org/2000/10/rdf-tests/rdfcore/xmlbase/Manifest.rdf#test001> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/10/rdf-tests/rdfcore/testSchema#PositiveParserTest> .
@@ -1052,8 +1222,8 @@ EOF
1052
1222
 
1053
1223
  def parse(input, options = {})
1054
1224
  @debug = []
1055
- graph = RDF::Graph.new
1056
- RDF::N3::Reader.new(input, options.merge(:debug => @debug, :strict => true)).each do |statement|
1225
+ graph = options[:graph] || RDF::Graph.new
1226
+ RDF::N3::Reader.new(input, {:debug => @debug, :validate => true, :canonicalize => false}.merge(options)).each do |statement|
1057
1227
  graph << statement
1058
1228
  end
1059
1229
  graph