From cd2b5f565bbadc7e55138157408b32728de3d566 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 30 Jan 2022 12:40:29 -0800 Subject: [PATCH 01/11] Back off on logger level in CI. --- spec/reader_spec.rb | 1 + spec/suite_extended_spec.rb | 1 + spec/suite_parser_spec.rb | 1 + spec/suite_turtle_spec.rb | 1 + spec/writer_spec.rb | 1 + 5 files changed, 5 insertions(+) diff --git a/spec/reader_spec.rb b/spec/reader_spec.rb index b6668ba..b603a20 100644 --- a/spec/reader_spec.rb +++ b/spec/reader_spec.rb @@ -8,6 +8,7 @@ let!(:doap_nt) {File.expand_path("../../etc/doap.nt", __FILE__)} let!(:doap_count) {File.open(doap_nt).each_line.to_a.length} let(:logger) {RDF::Spec.logger} + before {logger.level = Logger::INFO if ENV['CI']} after(:each) do |example| puts logger.to_s if diff --git a/spec/suite_extended_spec.rb b/spec/suite_extended_spec.rb index b6efb63..b2fac3e 100644 --- a/spec/suite_extended_spec.rb +++ b/spec/suite_extended_spec.rb @@ -6,6 +6,7 @@ # W3C N3 Test suite from http://www.w3.org/2000/10/swap/test/n3parser.tests describe "w3c n3 tests" do let(:logger) {RDF::Spec.logger} + before {logger.level = Logger::INFO if ENV['CI']} after(:each) do |example| puts logger.to_s if diff --git a/spec/suite_parser_spec.rb b/spec/suite_parser_spec.rb index 3e66336..8871445 100644 --- a/spec/suite_parser_spec.rb +++ b/spec/suite_parser_spec.rb @@ -5,6 +5,7 @@ # W3C N3 Test suite from http://www.w3.org/2000/10/swap/test/n3parser.tests describe "w3c n3 tests" do let(:logger) {RDF::Spec.logger} + before {logger.level = Logger::INFO if ENV['CI']} after(:each) do |example| puts logger.to_s if diff --git a/spec/suite_turtle_spec.rb b/spec/suite_turtle_spec.rb index 3cdc0d7..9366310 100644 --- a/spec/suite_turtle_spec.rb +++ b/spec/suite_turtle_spec.rb @@ -12,6 +12,7 @@ next if t.approval == 'rdft:Rejected' specify "#{t.rel}: #{t.name}: #{t.comment}" do t.logger = RDF::Spec.logger + t.logger.level = Logger::INFO if ENV['CI'] t.logger.info t.inspect t.logger.info "source:\n#{t.input}" diff --git a/spec/writer_spec.rb b/spec/writer_spec.rb index e1184b7..188f026 100644 --- a/spec/writer_spec.rb +++ b/spec/writer_spec.rb @@ -6,6 +6,7 @@ describe RDF::N3::Writer do let(:logger) {RDF::Spec.logger} + before {logger.level = Logger::INFO if ENV['CI']} #after(:each) do |example| # puts logger.to_s if From 2f5fdacc159961d0cb2ea914c1b653f8240b4fc1 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 23 Feb 2022 14:21:38 -0800 Subject: [PATCH 02/11] Update to operation on Temporal objects, with better support in RDF.rb 3.2.5. --- lib/rdf/n3/algebra/time/day.rb | 3 +-- lib/rdf/n3/algebra/time/hour.rb | 3 +-- lib/rdf/n3/algebra/time/in_seconds.rb | 3 +-- lib/rdf/n3/algebra/time/minute.rb | 3 +-- lib/rdf/n3/algebra/time/month.rb | 3 +-- lib/rdf/n3/algebra/time/second.rb | 3 +-- lib/rdf/n3/algebra/time/timezone.rb | 3 +-- lib/rdf/n3/algebra/time/year.rb | 3 +-- rdf-n3.gemspec | 2 +- spec/spec_helper.rb | 5 ++--- spec/suite_turtle_spec.rb | 3 +-- 11 files changed, 12 insertions(+), 22 deletions(-) diff --git a/lib/rdf/n3/algebra/time/day.rb b/lib/rdf/n3/algebra/time/day.rb index 4e15591..43eb7ea 100644 --- a/lib/rdf/n3/algebra/time/day.rb +++ b/lib/rdf/n3/algebra/time/day.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%d").to_i) + resource.as_datetime.day when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/hour.rb b/lib/rdf/n3/algebra/time/hour.rb index 1a36e8c..068a29e 100644 --- a/lib/rdf/n3/algebra/time/hour.rb +++ b/lib/rdf/n3/algebra/time/hour.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%H").to_i) + resource.as_datetime.hours when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/in_seconds.rb b/lib/rdf/n3/algebra/time/in_seconds.rb index 8fc346b..3e8c88d 100644 --- a/lib/rdf/n3/algebra/time/in_seconds.rb +++ b/lib/rdf/n3/algebra/time/in_seconds.rb @@ -21,9 +21,8 @@ def resolve(resource, position:) when RDF::Query::Variable resource when RDF::Literal - resource = resource.as_datetime # Subject evaluates to seconds from the epoc - RDF::Literal::Integer.new(resource.object.strftime("%s")) + RDF::Literal::Integer.new(resource.as_datetime.object.strftime("%s")) else nil end diff --git a/lib/rdf/n3/algebra/time/minute.rb b/lib/rdf/n3/algebra/time/minute.rb index 02dc5cf..093e9aa 100644 --- a/lib/rdf/n3/algebra/time/minute.rb +++ b/lib/rdf/n3/algebra/time/minute.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%M").to_i) + resource.as_datetime.minutes when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/month.rb b/lib/rdf/n3/algebra/time/month.rb index 222fa54..bae1c84 100644 --- a/lib/rdf/n3/algebra/time/month.rb +++ b/lib/rdf/n3/algebra/time/month.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%m").to_i) + resource.as_datetime.month when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/second.rb b/lib/rdf/n3/algebra/time/second.rb index db1a4b1..cb4b3da 100644 --- a/lib/rdf/n3/algebra/time/second.rb +++ b/lib/rdf/n3/algebra/time/second.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%S").to_i) + RDF::Literal(resource.as_datetime.seconds.to_i) when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/timezone.rb b/lib/rdf/n3/algebra/time/timezone.rb index f1de423..61e305e 100644 --- a/lib/rdf/n3/algebra/time/timezone.rb +++ b/lib/rdf/n3/algebra/time/timezone.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%Z")) + resource.as_datetime.tz when :object return nil unless resource.literal? || resource.variable? resource diff --git a/lib/rdf/n3/algebra/time/year.rb b/lib/rdf/n3/algebra/time/year.rb index 58832bd..3f9c6f6 100644 --- a/lib/rdf/n3/algebra/time/year.rb +++ b/lib/rdf/n3/algebra/time/year.rb @@ -18,8 +18,7 @@ def resolve(resource, position:) case position when :subject return nil unless resource.literal? - resource = resource.as_datetime - RDF::Literal(resource.object.strftime("%Y").to_i) + resource.as_datetime.year when :object return nil unless resource.literal? || resource.variable? resource diff --git a/rdf-n3.gemspec b/rdf-n3.gemspec index 5eb93d8..3a1034c 100755 --- a/rdf-n3.gemspec +++ b/rdf-n3.gemspec @@ -29,7 +29,7 @@ Gem::Specification.new do |gem| gem.requirements = [] gem.add_dependency 'ebnf', '~> 2.2' - gem.add_dependency 'rdf', '~> 3.2' + gem.add_dependency 'rdf', '~> 3.2', '>= 3.2.5' gem.add_dependency 'sparql', '~> 3.2' gem.add_runtime_dependency 'sxp', '~> 1.2' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 894213f..42d4288 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,13 +1,12 @@ -$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -$:.unshift File.dirname(__FILE__) +$:.unshift(File.expand_path('../../lib', __FILE__)) require "bundler/setup" require 'rspec' -require 'matchers' require 'rdf/isomorphic' require 'rdf/ntriples' require 'rdf/spec' require 'rdf/spec/matchers' +require_relative 'matchers' begin require 'simplecov' diff --git a/spec/suite_turtle_spec.rb b/spec/suite_turtle_spec.rb index 9366310..c7a75d9 100644 --- a/spec/suite_turtle_spec.rb +++ b/spec/suite_turtle_spec.rb @@ -1,5 +1,4 @@ -$:.unshift "." -require 'spec_helper' +require_relative 'spec_helper' describe RDF::N3::Reader do # W3C Turtle Test suite from http://w3c.github.io/rdf-tests/turtle/manifest.ttl From 3831a272a58b8da540315bb4416c26f61d26b132 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Tue, 29 Mar 2022 13:16:08 -0700 Subject: [PATCH 03/11] Define the format URI to http://www.w3.org/ns/formats/N3. --- lib/rdf/n3/format.rb | 5 ++++- spec/format_spec.rb | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/rdf/n3/format.rb b/lib/rdf/n3/format.rb index b67ac76..5712e24 100644 --- a/lib/rdf/n3/format.rb +++ b/lib/rdf/n3/format.rb @@ -17,7 +17,10 @@ module RDF::N3 # # @see https://www.w3.org/TR/rdf-testcases/#ntriples class Format < RDF::Format - content_type 'text/n3', extension: :n3, aliases: %w(text/rdf+n3;q=0.2 application/rdf+n3;q=0.2) + content_type 'text/n3', + extension: :n3, + aliases: %w(text/rdf+n3;q=0.2 application/rdf+n3;q=0.2), + uri: 'http://www.w3.org/ns/formats/N3' content_encoding 'utf-8' reader { RDF::N3::Reader } diff --git a/spec/format_spec.rb b/spec/format_spec.rb index e008b9d..2365bd8 100644 --- a/spec/format_spec.rb +++ b/spec/format_spec.rb @@ -42,6 +42,10 @@ specify {expect(described_class.to_sym).to eq :n3} end + describe "#to_uri" do + specify {expect(described_class.to_uri).to eq RDF::URI('http://www.w3.org/ns/formats/N3')} + end + describe ".detect" do { ntriples: " .", From c765eb974220be4d802d7fff642c5613c43052cb Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Mon, 27 Jun 2022 12:37:51 -0700 Subject: [PATCH 04/11] Add support for iriPropertyList when reading, but not yet for writing. --- README.md | 21 +++++++++++ etc/n3.ebnf | 28 +++++++++------ etc/n3.sxp | 27 +++++++------- lib/rdf/n3/reader.rb | 27 ++++++++++++++ lib/rdf/n3/terminals.rb | 3 ++ spec/reader_spec.rb | 79 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index e117b32..a75e6e9 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,27 @@ Reasoning is discussed in the [Design Issues][] document. * `time:timeZone` (See {RDF::N3::Algebra::Time::Timezone}) * `time:year` (See {RDF::N3::Algebra::Time::Year}) +## Parser features + +### Chaining with `iriPropertyList` + +Adds a proposed syntactic extension for _subject embedding_ similar to a `blankNodePropertyList`. An `iriPropertyList` begins with `[ hasId _id_`, instead of a simple `[`. This sets _id_ as the **subject** to be used for the following `propertyList`. This provides a mechanisms similar to [JSON-LD Embedding](https://www.w3.org/TR/json-ld11/#embedding). + + @prefix dc: . + @prefix : . + + :SummerReadingList a :OrderedListOfBooks ; + :toRead ( + [hasId :mobyDick dc:title "Moby Dick"; :setting :WhaleIntestines ] + [ + has_id :jaws + dc:title "Jaws"; + :setting :Beach + ] + ). + +Note that the _id_ used in the `iriPropertyList` is not delimited by a `;` + ### Formulae / Quoted Graphs N3 Formulae are introduced with the `{ statement-list }` syntax. A given formula is assigned an `RDF::Node` instance, which is also used as the graph_name for `RDF::Statement` instances provided to `RDF::N3::Reader#each_statement`. For example, the following N3 generates the associated statements: diff --git a/etc/n3.ebnf b/etc/n3.ebnf index 87d514d..86d94b2 100644 --- a/etc/n3.ebnf +++ b/etc/n3.ebnf @@ -47,6 +47,7 @@ | quickVar | collection | blankNodePropertyList + | iriPropertyList | literal | formula @@ -56,39 +57,44 @@ [20] blankNodePropertyList ::= '[' predicateObjectList ']' - [21] collection ::= '(' object* ')' + [21] iriPropertyList ::= IPLSTART iri predicateObjectList ']' - [22] formula ::= '{' formulaContent? '}' + [22] collection ::= '(' object* ')' - [23] formulaContent ::= n3Statement ('.' formulaContent?)? + [23] formula ::= '{' formulaContent? '}' + + [24] formulaContent ::= n3Statement ('.' formulaContent?)? | sparqlDirective formulaContent? - [24] numericLiteral ::= DOUBLE | DECIMAL | INTEGER + [25] numericLiteral ::= DOUBLE | DECIMAL | INTEGER - [25] rdfLiteral ::= STRING (LANGTAG | '^^' iri)? + [26] rdfLiteral ::= STRING (LANGTAG | '^^' iri)? - [26] iri ::= IRIREF | prefixedName + [27] iri ::= IRIREF | prefixedName - [27] prefixedName ::= PNAME_LN | PNAME_NS + [28] prefixedName ::= PNAME_LN | PNAME_NS # PNAME_NS will be matched for ':' (i.e., "empty") prefixedNames # hence this cannot be a lexer rule; for s/p/o of only ':', PNAME_NS will be returned # instead of PrefixedName token - [28] blankNode ::= BLANK_NODE_LABEL | ANON + [29] blankNode ::= BLANK_NODE_LABEL | ANON - [29] quickVar ::= QUICK_VAR_NAME + [30] quickVar ::= QUICK_VAR_NAME # only made this a parser rule for consistency # (all other path-items are also parser rules) @terminals - [30] BOOLEAN_LITERAL ::= 'true' | 'false' + [31] BOOLEAN_LITERAL ::= 'true' | 'false' - [31] STRING ::= STRING_LITERAL_LONG_SINGLE_QUOTE + [32] STRING ::= STRING_LITERAL_LONG_SINGLE_QUOTE | STRING_LITERAL_LONG_QUOTE | STRING_LITERAL_QUOTE | STRING_LITERAL_SINGLE_QUOTE + /* Note, this must be matched before '[' */ + [33] IPLSTART ::= '[' WS* 'hasId' + /* borrowed from SPARQL spec, which excludes newlines and other nastiness */ [139s] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR | WS)* '>' [140s] PNAME_NS ::= PN_PREFIX? ':' diff --git a/etc/n3.sxp b/etc/n3.sxp index eee7211..e270bb2 100644 --- a/etc/n3.sxp +++ b/etc/n3.sxp @@ -22,26 +22,29 @@ (rule expression "16" (seq path)) (rule path "17" (seq pathItem (opt (alt (seq "!" path) (seq "^" path))))) (rule pathItem "18" - (alt iri blankNode quickVar collection blankNodePropertyList literal formula)) + (alt iri blankNode quickVar collection blankNodePropertyList iriPropertyList + literal formula )) (rule literal "19" (alt rdfLiteral numericLiteral BOOLEAN_LITERAL)) (rule blankNodePropertyList "20" (seq "[" predicateObjectList "]")) - (rule collection "21" (seq "(" (star object) ")")) - (rule formula "22" (seq "{" (opt formulaContent) "}")) - (rule formulaContent "23" + (rule iriPropertyList "21" (seq IPLSTART iri predicateObjectList "]")) + (rule collection "22" (seq "(" (star object) ")")) + (rule formula "23" (seq "{" (opt formulaContent) "}")) + (rule formulaContent "24" (alt (seq n3Statement (opt (seq "." (opt formulaContent)))) (seq sparqlDirective (opt formulaContent))) ) - (rule numericLiteral "24" (alt DOUBLE DECIMAL INTEGER)) - (rule rdfLiteral "25" (seq STRING (opt (alt LANGTAG (seq "^^" iri))))) - (rule iri "26" (alt IRIREF prefixedName)) - (rule prefixedName "27" (alt PNAME_LN PNAME_NS)) - (rule blankNode "28" (alt BLANK_NODE_LABEL ANON)) - (rule quickVar "29" (seq QUICK_VAR_NAME)) + (rule numericLiteral "25" (alt DOUBLE DECIMAL INTEGER)) + (rule rdfLiteral "26" (seq STRING (opt (alt LANGTAG (seq "^^" iri))))) + (rule iri "27" (alt IRIREF prefixedName)) + (rule prefixedName "28" (alt PNAME_LN PNAME_NS)) + (rule blankNode "29" (alt BLANK_NODE_LABEL ANON)) + (rule quickVar "30" (seq QUICK_VAR_NAME)) (terminals _terminals (seq)) - (terminal BOOLEAN_LITERAL "30" (alt "true" "false")) - (terminal STRING "31" + (terminal BOOLEAN_LITERAL "31" (alt "true" "false")) + (terminal STRING "32" (alt STRING_LITERAL_LONG_SINGLE_QUOTE STRING_LITERAL_LONG_QUOTE STRING_LITERAL_QUOTE STRING_LITERAL_SINGLE_QUOTE )) + (terminal IPLSTART "33" (seq "[" (star WS) "hasId")) (terminal IRIREF "139s" (seq "<" (star (alt (diff (range "^<>\"{}|^`\\") (range "#x00-#x20")) UCHAR WS)) ">")) (terminal PNAME_NS "140s" (seq (opt PN_PREFIX) ":")) diff --git a/lib/rdf/n3/reader.rb b/lib/rdf/n3/reader.rb index ddd3d48..8149ed0 100644 --- a/lib/rdf/n3/reader.rb +++ b/lib/rdf/n3/reader.rb @@ -181,6 +181,7 @@ def each_triple # @!parse none terminal(:ANON, ANON) + terminal(:IPLSTART, IPLSTART) terminal(:BLANK_NODE_LABEL, BLANK_NODE_LABEL) terminal(:IRIREF, IRIREF, unescape: true) terminal(:DOUBLE, DOUBLE) @@ -311,6 +312,9 @@ def read_triples prod(:triples, %w{.}) do error("read_triples", "Unexpected end of file") unless token = @lexer.first subject = case token.type || token.value + when IPLSTART + # iriPropertyList predicateObjectList? + read_iriPropertyList || error("Failed to parse iriPropertyList", production: :triples, token: @lexer.first) when '[' # blankNodePropertyList predicateObjectList? read_blankNodePropertyList || error("Failed to parse blankNodePropertyList", production: :triples, token: @lexer.first) @@ -435,6 +439,7 @@ def read_path read_quickVar || read_collection || read_blankNodePropertyList || + read_iriPropertyList || read_literal || read_formula end @@ -523,6 +528,28 @@ def read_blankNodePropertyList end end + ## + # Read a iriPropertyList + # + # [21] iriPropertyList ::= IPLSTART iri predicateObjectList ']' + # + # @return [RDF::Node] + def read_iriPropertyList + token = @lexer.first + if token.type == :IPLSTART + prod(:iriPropertyList, %{]}) do + @lexer.shift + progress("iriPropertyList", depth: options[:depth], token: token) + node = read_iri + debug("iriPropertyList: subject", depth: options[:depth]) {node.to_sxp} + read_predicateObjectList(node) + error("iriPropertyList", "Expected closing ']'") unless @lexer.first === ']' + @lexer.shift + node + end + end + end + ## # Read a collection (`RDF::List`) # diff --git a/lib/rdf/n3/terminals.rb b/lib/rdf/n3/terminals.rb index cc6968b..4413b32 100644 --- a/lib/rdf/n3/terminals.rb +++ b/lib/rdf/n3/terminals.rb @@ -64,6 +64,9 @@ module Terminals # 25 STRING_LITERAL_LONG_QUOTE = /"""(?:(?:"|"")?(?:[^"\\]|#{ECHAR}|#{UCHAR}))*"""/um.freeze + # 33 + IPLSTART = /\[\s*hasId/um.freeze + # 28t PREFIX = /@?prefix/ui.freeze # 29t diff --git a/spec/reader_spec.rb b/spec/reader_spec.rb index b603a20..f3cb11a 100644 --- a/spec/reader_spec.rb +++ b/spec/reader_spec.rb @@ -983,6 +983,85 @@ end end + describe "iriPropertyList" do + { + "not embedded": [ + %([hasId :s :p :o] .), + %(:s :p :o .) + ], + "with whitespace": [ + %([ hasId :s :p :o] .), + %(:s :p :o .) + ], + "with linefeed": [ + %([ + hasId :s + :p :o + ] .), + %(:s :p :o .) + ], + "as a single object": [ + %( + @prefix a: . + a:b a:oneRef [ + hasId a:node0 + a:pp "1" ; + a:qq "2" + ] . + ), + %( + "1" . + "2" . + . + ) + ], + "nested resources": [ + %( + @prefix a: . + + a:a a:p [ + hasId a:node1 + a:p2 [ + hasId a:node0 + a:p3 "v1" , "v2" ; + a:p4 "v3" ] ; + a:p5 "v4" ] . + ), + %( + "v1" . + "v2" . + "v3" . + . + "v4" . + . + ), + ], + "illegal semicolon": [ + %([ hasId :s ; :p :o]), + :error + ], + "illegal subject list": [ + %([ hasId :s1, :s2 :p :o]), + :error + ], + "illegal bnode subject": [ + %([ hasId _:bn :p :o]), + :error + ], + }.each do |title, (n3, res)| + it title do + if res == :error + expect { + parse(n3, base_uri: "http://a/b", validate: true) + }.to raise_error(RDF::ReaderError) + else + expected = RDF::Graph.new {|g| g << RDF::N3::Reader.new(res, base_uri: "http://a/b")} + expect(parse(n3, base_uri: "http://a/b")).to be_equivalent_graph(expected, logger: logger, format: :n3) + end + end + end + end + describe "formulae" do before(:each) { @repo = RDF::N3:: Repository.new } From a55d2ffecc58a34c320d3cd523bc11bf953daef7 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Mon, 27 Jun 2022 12:47:35 -0700 Subject: [PATCH 05/11] Use `id` instead of `hasId` in `iriPropertyList`. --- README.md | 6 +++--- etc/n3.ebnf | 2 +- etc/n3.sxp | 2 +- lib/rdf/n3/terminals.rb | 2 +- spec/reader_spec.rb | 18 +++++++++--------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a75e6e9..98a30e1 100644 --- a/README.md +++ b/README.md @@ -163,16 +163,16 @@ Reasoning is discussed in the [Design Issues][] document. ### Chaining with `iriPropertyList` -Adds a proposed syntactic extension for _subject embedding_ similar to a `blankNodePropertyList`. An `iriPropertyList` begins with `[ hasId _id_`, instead of a simple `[`. This sets _id_ as the **subject** to be used for the following `propertyList`. This provides a mechanisms similar to [JSON-LD Embedding](https://www.w3.org/TR/json-ld11/#embedding). +Adds a proposed syntactic extension for _subject embedding_ similar to a `blankNodePropertyList`. An `iriPropertyList` begins with `[ id _id_`, instead of a simple `[`. This sets _id_ as the **subject** to be used for the following `propertyList`. This provides a mechanisms similar to [JSON-LD Embedding](https://www.w3.org/TR/json-ld11/#embedding). @prefix dc: . @prefix : . :SummerReadingList a :OrderedListOfBooks ; :toRead ( - [hasId :mobyDick dc:title "Moby Dick"; :setting :WhaleIntestines ] + [id :mobyDick dc:title "Moby Dick"; :setting :WhaleIntestines ] [ - has_id :jaws + id :jaws dc:title "Jaws"; :setting :Beach ] diff --git a/etc/n3.ebnf b/etc/n3.ebnf index 86d94b2..6f3a2ad 100644 --- a/etc/n3.ebnf +++ b/etc/n3.ebnf @@ -93,7 +93,7 @@ | STRING_LITERAL_SINGLE_QUOTE /* Note, this must be matched before '[' */ - [33] IPLSTART ::= '[' WS* 'hasId' + [33] IPLSTART ::= '[' WS* 'id' /* borrowed from SPARQL spec, which excludes newlines and other nastiness */ [139s] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR | WS)* '>' diff --git a/etc/n3.sxp b/etc/n3.sxp index e270bb2..2731e96 100644 --- a/etc/n3.sxp +++ b/etc/n3.sxp @@ -44,7 +44,7 @@ (terminal STRING "32" (alt STRING_LITERAL_LONG_SINGLE_QUOTE STRING_LITERAL_LONG_QUOTE STRING_LITERAL_QUOTE STRING_LITERAL_SINGLE_QUOTE )) - (terminal IPLSTART "33" (seq "[" (star WS) "hasId")) + (terminal IPLSTART "33" (seq "[" (star WS) "id")) (terminal IRIREF "139s" (seq "<" (star (alt (diff (range "^<>\"{}|^`\\") (range "#x00-#x20")) UCHAR WS)) ">")) (terminal PNAME_NS "140s" (seq (opt PN_PREFIX) ":")) diff --git a/lib/rdf/n3/terminals.rb b/lib/rdf/n3/terminals.rb index 4413b32..21dd9ce 100644 --- a/lib/rdf/n3/terminals.rb +++ b/lib/rdf/n3/terminals.rb @@ -65,7 +65,7 @@ module Terminals STRING_LITERAL_LONG_QUOTE = /"""(?:(?:"|"")?(?:[^"\\]|#{ECHAR}|#{UCHAR}))*"""/um.freeze # 33 - IPLSTART = /\[\s*hasId/um.freeze + IPLSTART = /\[\s*id/um.freeze # 28t PREFIX = /@?prefix/ui.freeze diff --git a/spec/reader_spec.rb b/spec/reader_spec.rb index f3cb11a..cc225f0 100644 --- a/spec/reader_spec.rb +++ b/spec/reader_spec.rb @@ -986,16 +986,16 @@ describe "iriPropertyList" do { "not embedded": [ - %([hasId :s :p :o] .), + %([id :s :p :o] .), %(:s :p :o .) ], "with whitespace": [ - %([ hasId :s :p :o] .), + %([ id :s :p :o] .), %(:s :p :o .) ], "with linefeed": [ %([ - hasId :s + id :s :p :o ] .), %(:s :p :o .) @@ -1004,7 +1004,7 @@ %( @prefix a: . a:b a:oneRef [ - hasId a:node0 + id a:node0 a:pp "1" ; a:qq "2" ] . @@ -1020,9 +1020,9 @@ @prefix a: . a:a a:p [ - hasId a:node1 + id a:node1 a:p2 [ - hasId a:node0 + id a:node0 a:p3 "v1" , "v2" ; a:p4 "v3" ] ; a:p5 "v4" ] . @@ -1037,15 +1037,15 @@ ), ], "illegal semicolon": [ - %([ hasId :s ; :p :o]), + %([ id :s ; :p :o]), :error ], "illegal subject list": [ - %([ hasId :s1, :s2 :p :o]), + %([ id :s1, :s2 :p :o]), :error ], "illegal bnode subject": [ - %([ hasId _:bn :p :o]), + %([ id _:bn :p :o]), :error ], }.each do |title, (n3, res)| From 19c2ad9b044fa3c401f334bf66021ea83027c4ce Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 27 Nov 2022 14:24:28 -0800 Subject: [PATCH 06/11] Minor change to EBNF. --- etc/n3.ebnf | 12 +++++------- etc/n3.sxp | 12 ++++-------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/etc/n3.ebnf b/etc/n3.ebnf index 6f3a2ad..54f5f16 100644 --- a/etc/n3.ebnf +++ b/etc/n3.ebnf @@ -27,14 +27,14 @@ | 'a' | 'has' expression | 'is' expression 'of' - | '<-' expression # Synonym for is expression of + | '=' | '<=' | '=>' - | '=' [13] subject ::= expression - [14] predicate ::= expression + [14] predicate ::= (expression | '<-' expression) + /* allow inverting first predicate in a path */ [15] object ::= expression @@ -96,11 +96,11 @@ [33] IPLSTART ::= '[' WS* 'id' /* borrowed from SPARQL spec, which excludes newlines and other nastiness */ - [139s] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR | WS)* '>' + [139s] IRIREF ::= '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR)* '>' [140s] PNAME_NS ::= PN_PREFIX? ':' [141s] PNAME_LN ::= PNAME_NS PN_LOCAL [142s] BLANK_NODE_LABEL ::= '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)? - [145s] LANGTAG ::= "@" ([a-zA-Z]+ ( "-" [a-zA-Z0-9]+ )*) - ("is" | "has") + [145s] LANGTAG ::= "@" ([a-zA-Z]+ ( "-" [a-zA-Z0-9]+ )*) [146s] INTEGER ::= [0-9]+ [147s] DECIMAL ::= [0-9]* '.' [0-9]+ [148s] DOUBLE ::= [0-9]+ '.' [0-9]* EXPONENT @@ -137,5 +137,3 @@ # Ignore all whitespace and comments between non-terminals @pass ( WS | COMMENT )* - - diff --git a/etc/n3.sxp b/etc/n3.sxp index 2731e96..9d2cbbb 100644 --- a/etc/n3.sxp +++ b/etc/n3.sxp @@ -12,12 +12,9 @@ (seq verb objectList (star (seq ";" (opt (seq verb objectList)))))) (rule objectList "11" (seq object (star (seq "," object)))) (rule verb "12" - (alt predicate "a" - (seq "has" expression) - (seq "is" expression "of") - (seq "<-" expression) "<=" "=>" "=" )) + (alt predicate "a" (seq "has" expression) (seq "is" expression "of") "=" "<=" "=>")) (rule subject "13" (seq expression)) - (rule predicate "14" (seq expression)) + (rule predicate "14" (alt expression (seq "<-" expression))) (rule object "15" (seq expression)) (rule expression "16" (seq path)) (rule path "17" (seq pathItem (opt (alt (seq "!" path) (seq "^" path))))) @@ -46,14 +43,13 @@ STRING_LITERAL_QUOTE STRING_LITERAL_SINGLE_QUOTE )) (terminal IPLSTART "33" (seq "[" (star WS) "id")) (terminal IRIREF "139s" - (seq "<" (star (alt (diff (range "^<>\"{}|^`\\") (range "#x00-#x20")) UCHAR WS)) ">")) + (seq "<" (star (alt (diff (range "^<>\"{}|^`\\") (range "#x00-#x20")) UCHAR)) ">")) (terminal PNAME_NS "140s" (seq (opt PN_PREFIX) ":")) (terminal PNAME_LN "141s" (seq PNAME_NS PN_LOCAL)) (terminal BLANK_NODE_LABEL "142s" (seq "_:" (alt PN_CHARS_U (range "0-9")) (opt (seq (star (alt PN_CHARS ".")) PN_CHARS)))) (terminal LANGTAG "145s" - (seq "@" - (diff (seq (plus (range "a-zA-Z")) (star (seq "-" (plus (range "a-zA-Z0-9"))))) (alt "is" "has"))) ) + (seq "@" (seq (plus (range "a-zA-Z")) (star (seq "-" (plus (range "a-zA-Z0-9"))))))) (terminal INTEGER "146s" (plus (range "0-9"))) (terminal DECIMAL "147s" (seq (star (range "0-9")) "." (plus (range "0-9")))) (terminal DOUBLE "148s" From 2af20d654efcf5847a46a2608f8122a65f93ee82 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 4 Jan 2023 13:35:09 -0800 Subject: [PATCH 07/11] CI on 3.2. --- .github/workflows/ci.yml | 10 ++-------- .github/workflows/generate-docs.yml | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9991f94..0657543 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,16 +26,10 @@ jobs: strategy: fail-fast: false matrix: - ruby: - - 2.6 - - 2.7 - - "3.0" - - 3.1 - - ruby-head - - jruby + ruby: [2.6, 2.7, '3.0', 3.1, 3.2, ruby-head, jruby] steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml index b8d16ed..65aea93 100644 --- a/.github/workflows/generate-docs.yml +++ b/.github/workflows/generate-docs.yml @@ -10,7 +10,7 @@ jobs: name: Update gh-pages with docs steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From 82ad7d4d6d8cd352b0bc76ff842c398e13f47829 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 3 May 2023 14:47:54 -0700 Subject: [PATCH 08/11] Update badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98a30e1..6cc1a73 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # RDF::N3 reader/writer and reasoner Notation-3 reader/writer for [RDF.rb][RDF.rb] . -[![Gem Version](https://badge.fury.io/rb/rdf-n3.png)](https://badge.fury.io/rb/rdf-n3) +[![Gem Version](https://badge.fury.io/rb/rdf-n3.svg)](https://badge.fury.io/rb/rdf-n3) [![Build Status](https://github.com/ruby-rdf/rdf-n3/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf-n3/actions?query=workflow%3ACI) [![Coverage Status](https://coveralls.io/repos/github/ruby-rdf/rdf-n3/badge.svg?branch=develop)](https://coveralls.io/github/ruby-rdf/rdf-n3?branch=develop) [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf) From 991d834f04d297fba28c890ecbc81b93cbb092d8 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sat, 26 Aug 2023 12:40:18 -0700 Subject: [PATCH 09/11] Updates for version 3.3.0 with minimum Ruby version 3.0. --- .github/workflows/ci.yml | 6 +++--- README.md | 6 +++--- VERSION | 2 +- rdf-n3.gemspec | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0657543..d80d483 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.6, 2.7, '3.0', 3.1, 3.2, ruby-head, jruby] + ruby: ['3.0', 3.1, 3.2, ruby-head, jruby] steps: - name: Clone repository uses: actions/checkout@v3 @@ -39,7 +39,7 @@ jobs: - name: Run tests run: ruby --version; bundle exec rspec spec || $ALLOW_FAILURES - name: Coveralls GitHub Action - uses: coverallsapp/github-action@v1.1.2 - if: "matrix.ruby == '3.0'" + uses: coverallsapp/github-action@v2 + if: "matrix.ruby == '3.2'" with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 6cc1a73..fe58590 100644 --- a/README.md +++ b/README.md @@ -214,9 +214,9 @@ Formulae are typically used to query the knowledge-base, which is set from the b Blank nodes associated with rdf:List statements used as part of a built-in are made _non-distinguished_ existential variables, and patters containing these variables become optional. If they are not bound as part of the query, the implicitly are bound as the original blank nodes defined within the formula, which allows for both constant list arguments, list arguments that contain variables, or arguments which are variables expanding to lists. ## Dependencies -* [Ruby](https://ruby-lang.org/) (>= 2.6) -* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.2) -* [EBNF][EBNF gem] (~> 2.2) +* [Ruby](https://ruby-lang.org/) (>= 3.0) +* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.3) +* [EBNF][EBNF gem] (~> 2.4) * [SPARQL][SPARQL gem] (~> 3.1) * [SXP][SXP gem] (~> 1.2) diff --git a/VERSION b/VERSION index e4604e3..15a2799 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.1 +3.3.0 diff --git a/rdf-n3.gemspec b/rdf-n3.gemspec index 3a1034c..f3eb1a0 100755 --- a/rdf-n3.gemspec +++ b/rdf-n3.gemspec @@ -25,20 +25,20 @@ Gem::Specification.new do |gem| gem.files = %w(README.md VERSION UNLICENSE) + Dir.glob('lib/**/*.rb') gem.require_paths = %w(lib) - gem.required_ruby_version = '>= 2.6' + gem.required_ruby_version = '>= 3.0' gem.requirements = [] - gem.add_dependency 'ebnf', '~> 2.2' - gem.add_dependency 'rdf', '~> 3.2', '>= 3.2.5' + gem.add_dependency 'ebnf', '~> 2.4' + gem.add_dependency 'rdf', '~> 3.3' gem.add_dependency 'sparql', '~> 3.2' gem.add_runtime_dependency 'sxp', '~> 1.2' - gem.add_development_dependency 'json-ld', '~> 3.2' + gem.add_development_dependency 'json-ld', '~> 3.3' gem.add_development_dependency 'rdf-spec', '~> 3.2' - gem.add_development_dependency 'rdf-isomorphic', '~> 3.2' + gem.add_development_dependency 'rdf-isomorphic', '~> 3.3' gem.add_development_dependency 'rdf-trig', '~> 3.2' gem.add_development_dependency 'rdf-vocab', '~> 3.2' - gem.add_development_dependency 'rspec', '~> 3.10' + gem.add_development_dependency 'rspec', '~> 3.12' gem.add_development_dependency 'rspec-its', '~> 1.3' gem.add_development_dependency 'yard' , '~> 0.9' From 2b45a55b147efd4df45b624c84fd48a7a9e07df6 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Sun, 27 Aug 2023 13:34:32 -0700 Subject: [PATCH 10/11] Update dependencies. --- rdf-n3.gemspec | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rdf-n3.gemspec b/rdf-n3.gemspec index f3eb1a0..fc73156 100755 --- a/rdf-n3.gemspec +++ b/rdf-n3.gemspec @@ -30,14 +30,14 @@ Gem::Specification.new do |gem| gem.add_dependency 'ebnf', '~> 2.4' gem.add_dependency 'rdf', '~> 3.3' - gem.add_dependency 'sparql', '~> 3.2' - gem.add_runtime_dependency 'sxp', '~> 1.2' + gem.add_dependency 'sparql', '~> 3.3' + gem.add_runtime_dependency 'sxp', '~> 1.3' gem.add_development_dependency 'json-ld', '~> 3.3' - gem.add_development_dependency 'rdf-spec', '~> 3.2' + gem.add_development_dependency 'rdf-spec', '~> 3.3' gem.add_development_dependency 'rdf-isomorphic', '~> 3.3' - gem.add_development_dependency 'rdf-trig', '~> 3.2' - gem.add_development_dependency 'rdf-vocab', '~> 3.2' + gem.add_development_dependency 'rdf-trig', '~> 3.3' + gem.add_development_dependency 'rdf-vocab', '~> 3.3' gem.add_development_dependency 'rspec', '~> 3.12' gem.add_development_dependency 'rspec-its', '~> 1.3' gem.add_development_dependency 'yard' , '~> 0.9' From f22889738b010796266c98efbb79e440524d2f2f Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Fri, 1 Sep 2023 13:36:09 -0700 Subject: [PATCH 11/11] simplecov 0.22. --- Gemfile | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 5af72e4..ba0246c 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ group :development do end group :development, :test do - gem 'simplecov', '~> 0.21', platforms: :mri + gem 'simplecov', '~> 0.22', platforms: :mri gem 'simplecov-lcov', '~> 0.8', platforms: :mri end diff --git a/README.md b/README.md index fe58590..8efecd8 100644 --- a/README.md +++ b/README.md @@ -217,8 +217,8 @@ Blank nodes associated with rdf:List statements used as part of a built-in are m * [Ruby](https://ruby-lang.org/) (>= 3.0) * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.3) * [EBNF][EBNF gem] (~> 2.4) -* [SPARQL][SPARQL gem] (~> 3.1) -* [SXP][SXP gem] (~> 1.2) +* [SPARQL][SPARQL gem] (~> 3.3) +* [SXP][SXP gem] (~> 1.3) ## Documentation Full documentation available on [RubyDoc.info](https://ruby-rdf.github.io/rdf-n3)