Skip to content

Commit

Permalink
Properly unescaep PN_LOCAL_ESC.
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Jan 5, 2024
1 parent 76bc642 commit 16e5bc2
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 14 deletions.
8 changes: 8 additions & 0 deletions lib/rdf/turtle/freebase_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ def read_pname(**options)
end
pfx_iri = prefix(ns)
raise RDF::ReaderError.new("ERROR [line #{lineno}] prefix #{ns.inspect} is not defined", lineno: lineno) unless pfx_iri

# Unescape PN_LOCAL_ESC
suffix = suffix.gsub(PN_LOCAL_ESC) {|esc| esc[1]} if
suffix.match?(PN_LOCAL_ESC)

# Remove any redundant leading hash from suffix
suffix = suffix.sub(/^\#/, "") if pfx_iri.to_s.index("#")

uri = RDF::URI(pfx_iri + suffix)
uri.validate! if validate?
uri
Expand Down
9 changes: 8 additions & 1 deletion lib/rdf/turtle/reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,14 @@ def pname(prefix, suffix)
error("undefined prefix", production: :pname, token: prefix)
''
end
suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")

# Unescape PN_LOCAL_ESC
suffix = suffix.gsub(PN_LOCAL_ESC) {|esc| esc[1]} if
suffix.match?(PN_LOCAL_ESC)

# Remove any redundant leading hash from suffix
suffix = suffix.sub(/^\#/, "") if base.index("#")

debug("pname", depth: options[:depth]) {"base: '#{base}', suffix: '#{suffix}'"}
process_iri(base + suffix.to_s)
end
Expand Down
36 changes: 36 additions & 0 deletions spec/freebase_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,42 @@
g = RDF::Graph.new << subject
expect(g).to be_equivalent_graph("@prefix foo: <http://example/bar#> ." + input, logger: @logger)
end

context "PN_LOCAL" do
{
"p:_a": "<http://a.example/_a>", # PN_CHARS_U
"p::": "<http://a.example/:>", # PN_LOCAL
"p:0": "<http://a.example/0>", # PN_LOCAL
"p:%B7": "<http://a.example/%B7>", # PN_LOCAL
"p:a.b": "<http://a.example/a.b>", # PN_LOCAL

"p:\\_underscore": "<http://a.example/_underscore>", # PN_LOCAL_ESC
"p:\\~tilda": "<http://a.example/~tilda>", # PN_LOCAL_ESC
"p:\\.dot": "<http://a.example/.dot>", # PN_LOCAL_ESC
"p:\\-dash": "<http://a.example/-dash>", # PN_LOCAL_ESC
"p:\\!exclamation": "<http://a.example/!exclamation>", # PN_LOCAL_ESC
"p:\\$dollar": "<http://a.example/$dollar>", # PN_LOCAL_ESC
"p:\\&amper": "<http://a.example/&amper>", # PN_LOCAL_ESC
"p:\\'squote": "<http://a.example/'squote>", # PN_LOCAL_ESC
"p:\\(paren\\)": "<http://a.example/(paren)>", # PN_LOCAL_ESC
"p:\\*star": "<http://a.example/*star>", # PN_LOCAL_ESC
"p:\\+plus": "<http://a.example/+plus>", # PN_LOCAL_ESC
"p:\\,comma": "<http://a.example/,comma>", # PN_LOCAL_ESC
"p:\\;semi": "<http://a.example/;semi>", # PN_LOCAL_ESC
"p:\\=equal": "<http://a.example/=equal>", # PN_LOCAL_ESC
"p:\\/slash": "<http://a.example//slash>", # PN_LOCAL_ESC
"p:\\?question": "<http://a.example/?question>", # PN_LOCAL_ESC
"p:\\#numbersign": "<http://a.example/#numbersign>", # PN_LOCAL_ESC
"p:\\@ampersand": "<http://a.example/@ampersand>", # PN_LOCAL_ESC
"p:\\%percent": "<http://a.example/%percent>", # PN_LOCAL_ESC
}.each do |pn, iri|
it pn do
ttl = %(@prefix p: <http://a.example/> .\n p:s p:p #{pn} .)
nt = %(<http://a.example/s> <http://a.example/p> #{iri} .)
expect(parse(ttl, validate: false)).to be_equivalent_graph(nt, logger: @logger)
end
end
end
end

describe "with simple sample data" do
Expand Down
36 changes: 36 additions & 0 deletions spec/reader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,42 @@
nil => "http://test/"})
end

context "PN_LOCAL" do
{
"p:_a": "<http://a.example/_a>", # PN_CHARS_U
"p::": "<http://a.example/:>", # PN_LOCAL
"p:0": "<http://a.example/0>", # PN_LOCAL
"p:%B7": "<http://a.example/%B7>", # PN_LOCAL
"p:a.b": "<http://a.example/a.b>", # PN_LOCAL

"p:\\_underscore": "<http://a.example/_underscore>", # PN_LOCAL_ESC
"p:\\~tilda": "<http://a.example/~tilda>", # PN_LOCAL_ESC
"p:\\.dot": "<http://a.example/.dot>", # PN_LOCAL_ESC
"p:\\-dash": "<http://a.example/-dash>", # PN_LOCAL_ESC
"p:\\!exclamation": "<http://a.example/!exclamation>", # PN_LOCAL_ESC
"p:\\$dollar": "<http://a.example/$dollar>", # PN_LOCAL_ESC
"p:\\&amper": "<http://a.example/&amper>", # PN_LOCAL_ESC
"p:\\'squote": "<http://a.example/'squote>", # PN_LOCAL_ESC
"p:\\(paren\\)": "<http://a.example/(paren)>", # PN_LOCAL_ESC
"p:\\*star": "<http://a.example/*star>", # PN_LOCAL_ESC
"p:\\+plus": "<http://a.example/+plus>", # PN_LOCAL_ESC
"p:\\,comma": "<http://a.example/,comma>", # PN_LOCAL_ESC
"p:\\;semi": "<http://a.example/;semi>", # PN_LOCAL_ESC
"p:\\=equal": "<http://a.example/=equal>", # PN_LOCAL_ESC
"p:\\/slash": "<http://a.example//slash>", # PN_LOCAL_ESC
"p:\\?question": "<http://a.example/?question>", # PN_LOCAL_ESC
"p:\\#numbersign": "<http://a.example/#numbersign>", # PN_LOCAL_ESC
"p:\\@ampersand": "<http://a.example/@ampersand>", # PN_LOCAL_ESC
"p:\\%percent": "<http://a.example/%percent>", # PN_LOCAL_ESC
}.each do |pn, iri|
it pn do
ttl = %(PREFIX p: <http://a.example/>\n p:s p:p #{pn} .)
nt = %(<http://a.example/s> <http://a.example/p> #{iri} .)
expect(parse(ttl, validate: false)).to be_equivalent_graph(nt, logger: @logger)
end
end
end

{
"@prefix foo: <http://foo/bar#> ." => [true, true],
"@PrEfIx foo: <http://foo/bar#> ." => [false, true],
Expand Down
21 changes: 8 additions & 13 deletions spec/terminals_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,16 @@
! # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : / < = ? @
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
_ a b c d e f g h i j k l m n o p q r s t u v w x y z ~
ab\\u00E9xy ab\xC3\xA9xy>
\\u03B1:a \xCE\xB1:a
a\\u003Ab a\x3Ab
\\U00010000 \xF0\x90\x80\x80
\\U000EFFFF \xF3\xAF\xBF\xBF
ab\\u00E9xy
\\u03B1:a
a\\u003Ab
\\U00010000
\\U000EFFFF
).each do |string|
it "matches <scheme:#{string.inspect}>" do
begin
string = "<scheme:#{string}>"
string.force_encoding(Encoding::UTF_8)
expect(string).to match(RDF::Turtle::Terminals::IRIREF)
rescue RSpec::Expectations::ExpectationNotMetError
pending "Escapes in IRIs"
fail
end
string = "<scheme:#{string}>"
string.force_encoding(Encoding::UTF_8)
expect(string).to match(RDF::Turtle::Terminals::IRIREF)
end
end
end
Expand Down

0 comments on commit 16e5bc2

Please sign in to comment.