yarspg 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +152 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/yarspg.rb +25 -0
- data/lib/yarspg/format.rb +42 -0
- data/lib/yarspg/meta.rb +176 -0
- data/lib/yarspg/reader.rb +413 -0
- data/lib/yarspg/terminals.rb +31 -0
- data/lib/yarspg/version.rb +0 -0
- data/lib/yarspg/writer.rb +10 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b2b77d4c266d555c6bd1174dee2f8b8d789126ab66cde6a5f6abcdb92e6ae676
|
4
|
+
data.tar.gz: 5b1db8e4c1b65605d5aaeb285281dd1b070d90934c7dce9da0a8d2e067f57c80
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b561d143b1d75f9d8eed956546d77bd50a2dcaa2f37503fa0522ebfc3919c25d5d5c268493f31e3117157f14726e9d9b8f5fb601c6bd8d6c30893498bd0f2807
|
7
|
+
data.tar.gz: 775e173535e0bb258ef233db97f63cf4aafa8988869bfb1264136e93314256532b2f306dd980b4859f3b9244f111a3b6e606ea920cda2ec06632fdf6a0302658
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# YARS-PG Property Graph to RDF* Processor.
|
2
|
+
|
3
|
+
[YARS-PG][] reader for [RDF.rb][]. Reads [Property Graph][] descriptions and generates [RDF*][] datasets.
|
4
|
+
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/yarspg.png)](https://badge.fury.io/rb/yarspg)
|
6
|
+
[![Build Status](https://secure.travis-ci.org/gkellogg/yarspg.png?branch=master)](https://travis-ci.org/gkellogg/yarspg)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/gkellogg/yarspg/badge.svg)](https://coveralls.io/r/gkellogg/yarspg)
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
YARSPG parses CSV or other Tabular Data into [RDF*][].
|
12
|
+
|
13
|
+
* Nodes, properties, and string annotations are treated as document-relative fragments.
|
14
|
+
* Edges are emitted only to the default graph, with properties and annotations emitted either to the default graph, or the specifically named graph(s).
|
15
|
+
* Node labels are treated as as document-relative `rdf:type` values.
|
16
|
+
* List complex values are emitted as `rdf:Lists`.
|
17
|
+
* Set and Struct complex values are emitted as `rdf:JSON` literals.
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
Install with `gem install yarspg`.
|
21
|
+
|
22
|
+
## Description
|
23
|
+
|
24
|
+
YARSPG parses [YARS-PG][] formatted documents into [RDF*][] datasets, where edges are RDF triples in the default graph, which form the subject of the properties and annotations on that edge.
|
25
|
+
|
26
|
+
There is currently no extra support for [Node Schemas](https://lszeremeta.github.io/yarspg/index.html#dfn-node-schema-declaration) or [Edge Schemas](https://lszeremeta.github.io/yarspg/index.html#dfn-edge-schema-declaration).
|
27
|
+
|
28
|
+
## Example
|
29
|
+
|
30
|
+
An example YARS-PG document follows:
|
31
|
+
|
32
|
+
# Prefix declaration
|
33
|
+
:foaf: <http://xmlns.com/foaf/0.1/>
|
34
|
+
|
35
|
+
%METADATA
|
36
|
+
-foaf:maker: "Łukasz Szeremeta and Dominik Tomaszuk"
|
37
|
+
|
38
|
+
%NODES
|
39
|
+
<"Author01">{"Author"}["fname": "John", "lname": "Smith"] #Author01
|
40
|
+
<"Author02">{"Author"}["fname": "Alice", "lname": "Brown"]
|
41
|
+
<"EI01">{"Entry", "InProceedings"}["title": "Serialization for...", "numpages": 10, "keyword": "Graph database"]
|
42
|
+
<"EA01">{"Entry", "Article"}["title": "Property Graph...", "numpages": 10, "keyword": ["Query", "Graph"]]
|
43
|
+
<"Proc01">{"Proceedings"}["title": "BDAS", "year": 2018, "month": "May"]
|
44
|
+
<"Jour01">{"Journal"}["title": "J. DB", "year": 2020, "vol": 30]
|
45
|
+
|
46
|
+
%EDGES
|
47
|
+
("EI01")-{"has_author"}["order": 1]->("Author01")
|
48
|
+
("EI01")-{"has_author"}["order": 2]->("Author02")
|
49
|
+
("EA01")-{"has_author"}["order": 1]->("Author02")
|
50
|
+
("EA01")-{"cites"}->("EI01")
|
51
|
+
("EI01")-{"booktitle"}["pages": "111-121"]->("Proc01")
|
52
|
+
("EA01")-{"published_in"}["pages": "222-232"]->("Jour01")
|
53
|
+
|
54
|
+
This results in the following TriG*:
|
55
|
+
|
56
|
+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
57
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
58
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
59
|
+
|
60
|
+
<> foaf:maker "Łukasz Szeremeta and Dominik Tomaszuk" .
|
61
|
+
|
62
|
+
<#Author01> a <#Author>; <#fname> "John"; <#lname> "Smith" .
|
63
|
+
<#Author02> a <#Author>; <#fname> "Alice"; <#lname> "Brown" .
|
64
|
+
|
65
|
+
<#EI01> a <#Entry>, <#InProceedings>;
|
66
|
+
<#title> "Serialization for...";
|
67
|
+
<#numpages> 10;
|
68
|
+
<#keyword> "Graph database";
|
69
|
+
<#booktitle> <#Proc01>;
|
70
|
+
<#has_author> <#Author02>, <#Author01> .
|
71
|
+
|
72
|
+
<#EA01> a <#Entry>, <#Article>;
|
73
|
+
<#title> "Property Graph...";
|
74
|
+
<#numpages> 10;
|
75
|
+
<#keyword> ("Query" "Graph");
|
76
|
+
<#cites> <#EI01>;
|
77
|
+
<#has_author> <#Author02>;
|
78
|
+
<#published_in> <#Jour01> .
|
79
|
+
|
80
|
+
<#Proc01> a <#Proceedings>;
|
81
|
+
<#month> "May";
|
82
|
+
<#title> "BDAS";
|
83
|
+
<#year> 2018 .
|
84
|
+
|
85
|
+
<#Jour01> a <#Journal>;
|
86
|
+
<#title> "J. DB";
|
87
|
+
<#vol> 30;
|
88
|
+
<#year> 2020 .
|
89
|
+
|
90
|
+
<<<#EI01> <#has_author> <#Author01>>> <#order> 1 .
|
91
|
+
<<<#EI01> <#has_author> <#Author02>>> <#order> 2 .
|
92
|
+
<<<#EA01> <#has_author> <#Author02>>> <#order> 1 .
|
93
|
+
<<<#EI01> <#booktitle> <#Proc01>>> <#pages> "111-121" .
|
94
|
+
<<<#EA01> <#published_in> <#Jour01>>> <#pages> "222-232" .
|
95
|
+
|
96
|
+
## RDF Reader
|
97
|
+
YARS acts as a normal RDF reader, using the standard RDF.rb Reader interface:
|
98
|
+
|
99
|
+
graph = RDF::Graph.load("etc/doap.yarspg")
|
100
|
+
|
101
|
+
alternatively
|
102
|
+
|
103
|
+
graph = RDF::Graph.new {|g| YARSPG::Reader.open("etc/doap.yarspg") {|r| g << r}}
|
104
|
+
|
105
|
+
### Principal Classes
|
106
|
+
* {YARSPG}
|
107
|
+
* {YARSPG::Format}
|
108
|
+
* {YARSPG::Metadata}
|
109
|
+
* {YARSPG::Reader}
|
110
|
+
* {YARSPG::Terminals}
|
111
|
+
|
112
|
+
## Dependencies
|
113
|
+
* [Ruby](https://ruby-lang.org/) (>= 2.4)
|
114
|
+
* [RDF.rb][] (~> 3.1)
|
115
|
+
* [EBNF][] (~> 2.0)
|
116
|
+
|
117
|
+
## Installation
|
118
|
+
The recommended installation method is via [RubyGems](https://rubygems.org/).
|
119
|
+
To install the latest official release of the `RDF::Tabular` gem, do:
|
120
|
+
|
121
|
+
% [sudo] gem install yarspg
|
122
|
+
|
123
|
+
## Mailing List
|
124
|
+
* <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
|
125
|
+
|
126
|
+
## Author
|
127
|
+
* [Gregg Kellogg](https://github.com/gkellogg) - <https://greggkellogg.net/>
|
128
|
+
|
129
|
+
## Contributing
|
130
|
+
* Do your best to adhere to the existing coding conventions and idioms.
|
131
|
+
* Don't use hard tabs, and don't leave trailing whitespace on any line.
|
132
|
+
* Do document every method you add using [YARD][] annotations. Read the
|
133
|
+
[tutorial][YARD-GS] or just look at the existing code for examples.
|
134
|
+
* Don't touch the `rdf-tabular.gemspec`, `VERSION` or `AUTHORS` files. If you need to change them, do so on your private branch only.
|
135
|
+
* Do feel free to add yourself to the `CREDITS` file and the corresponding list in the the `README`. Alphabetical order applies.
|
136
|
+
* Do note that in order for us to merge any non-trivial changes (as a rule of thumb, additions larger than about 15 lines of code), we need an explicit [public domain dedication][PDD] on record from you.
|
137
|
+
|
138
|
+
##License
|
139
|
+
|
140
|
+
This is free and unencumbered public domain software. For more information,
|
141
|
+
see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
142
|
+
|
143
|
+
[Ruby]: https://ruby-lang.org/
|
144
|
+
[RDF]: https://www.w3.org/RDF/
|
145
|
+
[YARD]: https://yardoc.org/
|
146
|
+
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
147
|
+
[PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
|
148
|
+
[EBNF]: https://rubygems.org/gems/ebnf
|
149
|
+
[RDF.rb]: https://rubygems.org/gems/rdf
|
150
|
+
[RDF*]: https://lists.w3.org/Archives/Public/public-rdf-star/
|
151
|
+
[YARS-PG]: https://lszeremeta.github.io/yarspg/index.html
|
152
|
+
[Property Graph]: http://graphdatamodeling.com/Graph%20Data%20Modeling/GraphDataModeling/page/PropertyGraphs.html
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <https://unlicense.org/>
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/yarspg.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
|
3
|
+
##
|
4
|
+
# **`YARSPG`** is an YARS-PG extension for RDF.rb.
|
5
|
+
#
|
6
|
+
# @example Requiring the `YARSPG` module
|
7
|
+
# require 'yarspg'
|
8
|
+
#
|
9
|
+
# @example Parsing statements from a YARS-PG file into a graph using RDF*.
|
10
|
+
# YARSPG::Reader.open("etc/foaf.yarspg") do |reader|
|
11
|
+
# reader.each_statement do |statement|
|
12
|
+
# puts statement.inspect
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @see https://rubydoc.info/github/ruby-rdf/rdf/
|
17
|
+
# @see https://lszeremeta.github.io/yarspg/index.html
|
18
|
+
#
|
19
|
+
# @author [Gregg Kellogg](https://greggkellogg.net/)
|
20
|
+
module YARSPG
|
21
|
+
require 'yarspg/format'
|
22
|
+
autoload :Reader, 'yarspg/reader'
|
23
|
+
autoload :VERSION, 'yarspg/version'
|
24
|
+
autoload :Writer, 'yarspg/writer'
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module YARSPG
|
2
|
+
##
|
3
|
+
# YARS-PG format specification.
|
4
|
+
#
|
5
|
+
# @example Obtaining an ## format class
|
6
|
+
# RDF::Format.for("etc/foaf.yarspg")
|
7
|
+
# RDF::Format.for(file_name: "etc/foaf.yarspg")
|
8
|
+
# RDF::Format.for(file_extension: "yarspg")
|
9
|
+
# RDF::Format.for(content_type: "text/yarspg")
|
10
|
+
#
|
11
|
+
# @example Obtaining serialization format MIME types
|
12
|
+
# RDF::Format.content_types #=> {"text/yarspg" => [YARSPG::Format]}
|
13
|
+
#
|
14
|
+
# @example Obtaining serialization format file extension mappings
|
15
|
+
# RDF::Format.file_extensions #=> {yarspg: "text/yarspg"}
|
16
|
+
#
|
17
|
+
# @see https://www.w3.org/TR/rdf-testcases/#ntriples
|
18
|
+
class Format < RDF::Format
|
19
|
+
content_type 'text/yarspg',
|
20
|
+
extension: :yarspg
|
21
|
+
content_encoding 'utf-8'
|
22
|
+
|
23
|
+
reader { YARSPG::Reader }
|
24
|
+
writer { YARSPG::Writer }
|
25
|
+
|
26
|
+
##
|
27
|
+
# Sample detection to see if it matches YARS-PG
|
28
|
+
#
|
29
|
+
# Use a text sample to detect the format of an input file. Sub-classes implement a matcher sufficient to detect probably format matches, including disambiguating between other similar formats.
|
30
|
+
#
|
31
|
+
# @param [String] sample Beginning several bytes (~ 1K) of input.
|
32
|
+
# @return [Boolean]
|
33
|
+
def self.detect(sample)
|
34
|
+
!!sample.match(%r(
|
35
|
+
(?:%(METADATA|NODE SCHEMAS|EDGE SCHEMAS|NODES|EDGES)) | # Section Names
|
36
|
+
(?:[S\{.*\}]-) | # Node Schema
|
37
|
+
(?:[S\(.*\)]-) | # Edge Schema
|
38
|
+
(?:\(.*\)-) # Edge
|
39
|
+
)mx)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/yarspg/meta.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# This file is automatically generated by ebnf version 2.0.0
|
2
|
+
# Derived from etc/yars-pg.ebnf
|
3
|
+
module YARSPG::Meta
|
4
|
+
RULES = [
|
5
|
+
EBNF::Rule.new(:yarspg, "1", [:star, :statement]).extend(EBNF::PEG::Rule),
|
6
|
+
EBNF::Rule.new(:statement, "2", [:alt, :node, :edge, :prefix_directive, :metadata, :node_schema, :edge_schema, :section]).extend(EBNF::PEG::Rule),
|
7
|
+
EBNF::Rule.new(:prefix_directive, "3", [:seq, :_prefix_directive_1, :IRI]).extend(EBNF::PEG::Rule),
|
8
|
+
EBNF::Rule.new(:_prefix_directive_1, "3.1", [:alt, "::", :pname]).extend(EBNF::PEG::Rule),
|
9
|
+
EBNF::Rule.new(:pname, "4", [:seq, ":", :ALNUM_PLUS, ":"]).extend(EBNF::PEG::Rule),
|
10
|
+
EBNF::Rule.new(:pn_local, "5", [:seq, :ALNUM_PLUS]).extend(EBNF::PEG::Rule),
|
11
|
+
EBNF::Rule.new(:metadata, "6", [:seq, "-", :_metadata_1, :_metadata_2]).extend(EBNF::PEG::Rule),
|
12
|
+
EBNF::Rule.new(:_metadata_1, "6.1", [:alt, :_metadata_3, :_metadata_4]).extend(EBNF::PEG::Rule),
|
13
|
+
EBNF::Rule.new(:_metadata_3, "6.3", [:seq, :pn_local, :pname]).extend(EBNF::PEG::Rule),
|
14
|
+
EBNF::Rule.new(:_metadata_4, "6.4", [:seq, :IRI, ":"]).extend(EBNF::PEG::Rule),
|
15
|
+
EBNF::Rule.new(:_metadata_2, "6.2", [:alt, :STRING, :IRI]).extend(EBNF::PEG::Rule),
|
16
|
+
EBNF::Rule.new(:graph_name, "6a", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
17
|
+
EBNF::Rule.new(:annotation, "7", [:alt, :string_annotation, :rdf_annotation]).extend(EBNF::PEG::Rule),
|
18
|
+
EBNF::Rule.new(:string_annotation, "8", [:seq, :STRING, ":", :STRING]).extend(EBNF::PEG::Rule),
|
19
|
+
EBNF::Rule.new(:rdf_annotation, "9", [:seq, :_rdf_annotation_1, :_rdf_annotation_2]).extend(EBNF::PEG::Rule),
|
20
|
+
EBNF::Rule.new(:_rdf_annotation_1, "9.1", [:alt, :_rdf_annotation_3, :_rdf_annotation_4]).extend(EBNF::PEG::Rule),
|
21
|
+
EBNF::Rule.new(:_rdf_annotation_3, "9.3", [:seq, :pn_local, :pname]).extend(EBNF::PEG::Rule),
|
22
|
+
EBNF::Rule.new(:_rdf_annotation_4, "9.4", [:seq, :IRI, ":"]).extend(EBNF::PEG::Rule),
|
23
|
+
EBNF::Rule.new(:_rdf_annotation_2, "9.2", [:alt, :STRING, :IRI]).extend(EBNF::PEG::Rule),
|
24
|
+
EBNF::Rule.new(:annotations_list, "10", [:seq, "+", :annotation, :_annotations_list_1]).extend(EBNF::PEG::Rule),
|
25
|
+
EBNF::Rule.new(:_annotations_list_1, "10.1", [:star, :_annotations_list_2]).extend(EBNF::PEG::Rule),
|
26
|
+
EBNF::Rule.new(:_annotations_list_2, "10.2", [:seq, ",", :annotation]).extend(EBNF::PEG::Rule),
|
27
|
+
EBNF::Rule.new(:props_list, "11", [:seq, "[", :prop, :_props_list_1, "]"]).extend(EBNF::PEG::Rule),
|
28
|
+
EBNF::Rule.new(:_props_list_1, "11.1", [:star, :_props_list_2]).extend(EBNF::PEG::Rule),
|
29
|
+
EBNF::Rule.new(:_props_list_2, "11.2", [:seq, ",", :prop]).extend(EBNF::PEG::Rule),
|
30
|
+
EBNF::Rule.new(:graphs_list, "12", [:seq, "/", :graph_name, :_graphs_list_1, "/"]).extend(EBNF::PEG::Rule),
|
31
|
+
EBNF::Rule.new(:_graphs_list_1, "12.1", [:star, :_graphs_list_2]).extend(EBNF::PEG::Rule),
|
32
|
+
EBNF::Rule.new(:_graphs_list_2, "12.2", [:seq, ",", :graph_name]).extend(EBNF::PEG::Rule),
|
33
|
+
EBNF::Rule.new(:node, "13", [:seq, "<", :node_id, ">", :_node_1, :_node_2, :_node_3, :_node_4]).extend(EBNF::PEG::Rule),
|
34
|
+
EBNF::Rule.new(:_node_1, "13.1", [:opt, :_node_5]).extend(EBNF::PEG::Rule),
|
35
|
+
EBNF::Rule.new(:_node_5, "13.5", [:seq, "{", :node_label, :_node_6, "}"]).extend(EBNF::PEG::Rule),
|
36
|
+
EBNF::Rule.new(:_node_6, "13.6", [:star, :_node_7]).extend(EBNF::PEG::Rule),
|
37
|
+
EBNF::Rule.new(:_node_7, "13.7", [:seq, ",", :node_label]).extend(EBNF::PEG::Rule),
|
38
|
+
EBNF::Rule.new(:_node_2, "13.2", [:opt, :props_list]).extend(EBNF::PEG::Rule),
|
39
|
+
EBNF::Rule.new(:_node_3, "13.3", [:opt, :graphs_list]).extend(EBNF::PEG::Rule),
|
40
|
+
EBNF::Rule.new(:_node_4, "13.4", [:opt, :annotations_list]).extend(EBNF::PEG::Rule),
|
41
|
+
EBNF::Rule.new(:edge, "14", [:alt, :directed, :undirected]).extend(EBNF::PEG::Rule),
|
42
|
+
EBNF::Rule.new(:section, "15", [:seq, "%", :SECTION_NAME]).extend(EBNF::PEG::Rule),
|
43
|
+
EBNF::Rule.new(:directed, "16", [:seq, "(", :node_id, ")", "-", :_directed_1, "{", :edge_label, "}", :_directed_2, "->", "(", :node_id, ")", :_directed_3, :_directed_4]).extend(EBNF::PEG::Rule),
|
44
|
+
EBNF::Rule.new(:_directed_1, "16.1", [:opt, :_directed_5]).extend(EBNF::PEG::Rule),
|
45
|
+
EBNF::Rule.new(:_directed_5, "16.5", [:seq, "<", :edge_id, ">"]).extend(EBNF::PEG::Rule),
|
46
|
+
EBNF::Rule.new(:_directed_2, "16.2", [:opt, :props_list]).extend(EBNF::PEG::Rule),
|
47
|
+
EBNF::Rule.new(:_directed_3, "16.3", [:opt, :graphs_list]).extend(EBNF::PEG::Rule),
|
48
|
+
EBNF::Rule.new(:_directed_4, "16.4", [:opt, :annotations_list]).extend(EBNF::PEG::Rule),
|
49
|
+
EBNF::Rule.new(:undirected, "17", [:seq, "(", :node_id, ")", "-", :_undirected_1, "{", :edge_label, "}", :_undirected_2, "-", "(", :node_id, ")", :_undirected_3, :_undirected_4]).extend(EBNF::PEG::Rule),
|
50
|
+
EBNF::Rule.new(:_undirected_1, "17.1", [:opt, :_undirected_5]).extend(EBNF::PEG::Rule),
|
51
|
+
EBNF::Rule.new(:_undirected_5, "17.5", [:seq, "<", :edge_id, ">"]).extend(EBNF::PEG::Rule),
|
52
|
+
EBNF::Rule.new(:_undirected_2, "17.2", [:opt, :props_list]).extend(EBNF::PEG::Rule),
|
53
|
+
EBNF::Rule.new(:_undirected_3, "17.3", [:opt, :graphs_list]).extend(EBNF::PEG::Rule),
|
54
|
+
EBNF::Rule.new(:_undirected_4, "17.4", [:opt, :annotations_list]).extend(EBNF::PEG::Rule),
|
55
|
+
EBNF::Rule.new(:node_id, "18", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
56
|
+
EBNF::Rule.new(:node_label, "19", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
57
|
+
EBNF::Rule.new(:prop, "20", [:seq, :key, ":", :value]).extend(EBNF::PEG::Rule),
|
58
|
+
EBNF::Rule.new(:edge_id, "21", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
59
|
+
EBNF::Rule.new(:edge_label, "22", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
60
|
+
EBNF::Rule.new(:key, "23", [:seq, :STRING]).extend(EBNF::PEG::Rule),
|
61
|
+
EBNF::Rule.new(:value, "24", [:alt, :primitive_value, :complex_value]).extend(EBNF::PEG::Rule),
|
62
|
+
EBNF::Rule.new(:primitive_value, "25", [:alt, :STRING, :DATETYPE, :NUMBER, :BOOL, "null"]).extend(EBNF::PEG::Rule),
|
63
|
+
EBNF::Rule.new(:complex_value, "26", [:alt, :set, :list, :struct]).extend(EBNF::PEG::Rule),
|
64
|
+
EBNF::Rule.new(:set, "27", [:seq, "{", :_set_1, :_set_2, "}"]).extend(EBNF::PEG::Rule),
|
65
|
+
EBNF::Rule.new(:_set_1, "27.1", [:alt, :primitive_value, :set]).extend(EBNF::PEG::Rule),
|
66
|
+
EBNF::Rule.new(:_set_2, "27.2", [:star, :_set_3]).extend(EBNF::PEG::Rule),
|
67
|
+
EBNF::Rule.new(:_set_3, "27.3", [:seq, ",", :_set_4]).extend(EBNF::PEG::Rule),
|
68
|
+
EBNF::Rule.new(:_set_4, "27.4", [:alt, :primitive_value, :set]).extend(EBNF::PEG::Rule),
|
69
|
+
EBNF::Rule.new(:list, "28", [:seq, "[", :_list_1, :_list_2, "]"]).extend(EBNF::PEG::Rule),
|
70
|
+
EBNF::Rule.new(:_list_1, "28.1", [:alt, :primitive_value, :list]).extend(EBNF::PEG::Rule),
|
71
|
+
EBNF::Rule.new(:_list_2, "28.2", [:star, :_list_3]).extend(EBNF::PEG::Rule),
|
72
|
+
EBNF::Rule.new(:_list_3, "28.3", [:seq, ",", :_list_4]).extend(EBNF::PEG::Rule),
|
73
|
+
EBNF::Rule.new(:_list_4, "28.4", [:alt, :primitive_value, :list]).extend(EBNF::PEG::Rule),
|
74
|
+
EBNF::Rule.new(:struct, "29", [:seq, "{", :key, ":", :_struct_1, :_struct_2, "}"]).extend(EBNF::PEG::Rule),
|
75
|
+
EBNF::Rule.new(:_struct_1, "29.1", [:alt, :primitive_value, :struct]).extend(EBNF::PEG::Rule),
|
76
|
+
EBNF::Rule.new(:_struct_2, "29.2", [:star, :_struct_3]).extend(EBNF::PEG::Rule),
|
77
|
+
EBNF::Rule.new(:_struct_3, "29.3", [:seq, ",", :key, ":", :_struct_4]).extend(EBNF::PEG::Rule),
|
78
|
+
EBNF::Rule.new(:_struct_4, "29.4", [:alt, :primitive_value, :struct]).extend(EBNF::PEG::Rule),
|
79
|
+
EBNF::Rule.new(:node_schema, "30", [:seq, "S", :_node_schema_1, :_node_schema_2, :_node_schema_3, :_node_schema_4]).extend(EBNF::PEG::Rule),
|
80
|
+
EBNF::Rule.new(:_node_schema_1, "30.1", [:seq, "{", :node_label, :_node_schema_5, "}"]).extend(EBNF::PEG::Rule),
|
81
|
+
EBNF::Rule.new(:_node_schema_5, "30.5", [:star, :_node_schema_6]).extend(EBNF::PEG::Rule),
|
82
|
+
EBNF::Rule.new(:_node_schema_6, "30.6", [:seq, ",", :node_label]).extend(EBNF::PEG::Rule),
|
83
|
+
EBNF::Rule.new(:_node_schema_2, "30.2", [:opt, :props_list_schema]).extend(EBNF::PEG::Rule),
|
84
|
+
EBNF::Rule.new(:_node_schema_3, "30.3", [:opt, :graphs_list]).extend(EBNF::PEG::Rule),
|
85
|
+
EBNF::Rule.new(:_node_schema_4, "30.4", [:opt, :annotations_list]).extend(EBNF::PEG::Rule),
|
86
|
+
EBNF::Rule.new(:props_list_schema, "31", [:seq, "[", :prop_schema, :_props_list_schema_1, "]"]).extend(EBNF::PEG::Rule),
|
87
|
+
EBNF::Rule.new(:_props_list_schema_1, "31.1", [:star, :_props_list_schema_2]).extend(EBNF::PEG::Rule),
|
88
|
+
EBNF::Rule.new(:_props_list_schema_2, "31.2", [:seq, ",", :prop_schema]).extend(EBNF::PEG::Rule),
|
89
|
+
EBNF::Rule.new(:prop_schema, "32", [:seq, :key, ":", :value_schema]).extend(EBNF::PEG::Rule),
|
90
|
+
EBNF::Rule.new(:value_schema, "33", [:alt, :primitive_value_schema, :complex_value_schema]).extend(EBNF::PEG::Rule),
|
91
|
+
EBNF::Rule.new(:primitive_value_schema, "34", [:alt, "Decimal", "SmallInt", "Integer", "BigInt", "Float", "Real", "Double", "Bool", "Null", "String", "Date", "Timestamp", "Time"]).extend(EBNF::PEG::Rule),
|
92
|
+
EBNF::Rule.new(:complex_value_schema, "35", [:alt, :set_schema, :list_schema, :struct_schema]).extend(EBNF::PEG::Rule),
|
93
|
+
EBNF::Rule.new(:set_schema, "36", [:seq, "Set", "(", :_set_schema_1, ")"]).extend(EBNF::PEG::Rule),
|
94
|
+
EBNF::Rule.new(:_set_schema_1, "36.1", [:alt, :primitive_value_schema, :set_schema]).extend(EBNF::PEG::Rule),
|
95
|
+
EBNF::Rule.new(:list_schema, "37", [:seq, "List", "(", :_list_schema_1, ")"]).extend(EBNF::PEG::Rule),
|
96
|
+
EBNF::Rule.new(:_list_schema_1, "37.1", [:alt, :primitive_value_schema, :list_schema]).extend(EBNF::PEG::Rule),
|
97
|
+
EBNF::Rule.new(:struct_schema, "38", [:seq, "Struct", "(", :_struct_schema_1, ")"]).extend(EBNF::PEG::Rule),
|
98
|
+
EBNF::Rule.new(:_struct_schema_1, "38.1", [:alt, :primitive_value_schema, :struct_schema]).extend(EBNF::PEG::Rule),
|
99
|
+
EBNF::Rule.new(:edge_schema, "39", [:alt, :directed_schema, :undirected_schema]).extend(EBNF::PEG::Rule),
|
100
|
+
EBNF::Rule.new(:directed_schema, "40", [:seq, "S", :_directed_schema_1, "-", "{", :edge_label, "}", :_directed_schema_2, "->", :_directed_schema_3]).extend(EBNF::PEG::Rule),
|
101
|
+
EBNF::Rule.new(:_directed_schema_1, "40.1", [:opt, :_directed_schema_4]).extend(EBNF::PEG::Rule),
|
102
|
+
EBNF::Rule.new(:_directed_schema_4, "40.4", [:seq, "(", :node_label, ")"]).extend(EBNF::PEG::Rule),
|
103
|
+
EBNF::Rule.new(:_directed_schema_2, "40.2", [:opt, :props_list_schema]).extend(EBNF::PEG::Rule),
|
104
|
+
EBNF::Rule.new(:_directed_schema_3, "40.3", [:opt, :_directed_schema_5]).extend(EBNF::PEG::Rule),
|
105
|
+
EBNF::Rule.new(:_directed_schema_5, "40.5", [:seq, "(", :node_label, ")"]).extend(EBNF::PEG::Rule),
|
106
|
+
EBNF::Rule.new(:undirected_schema, "41", [:seq, "S", :_undirected_schema_1, "-", "{", :edge_label, "}", :_undirected_schema_2, "-", :_undirected_schema_3]).extend(EBNF::PEG::Rule),
|
107
|
+
EBNF::Rule.new(:_undirected_schema_1, "41.1", [:opt, :_undirected_schema_4]).extend(EBNF::PEG::Rule),
|
108
|
+
EBNF::Rule.new(:_undirected_schema_4, "41.4", [:seq, "(", :node_label, ")"]).extend(EBNF::PEG::Rule),
|
109
|
+
EBNF::Rule.new(:_undirected_schema_2, "41.2", [:opt, :props_list_schema]).extend(EBNF::PEG::Rule),
|
110
|
+
EBNF::Rule.new(:_undirected_schema_3, "41.3", [:opt, :_undirected_schema_5]).extend(EBNF::PEG::Rule),
|
111
|
+
EBNF::Rule.new(:_undirected_schema_5, "41.5", [:seq, "(", :node_label, ")"]).extend(EBNF::PEG::Rule),
|
112
|
+
EBNF::Rule.new(:SECTION_NAME, "42", [:alt, "METADATA", "NODE SCHEMAS", "EDGE SCHEMAS", "NODES", "EDGES"], kind: :terminal).extend(EBNF::PEG::Rule),
|
113
|
+
EBNF::Rule.new(:COMMENT, "43", [:seq, "#", :_COMMENT_1], kind: :terminal).extend(EBNF::PEG::Rule),
|
114
|
+
EBNF::Rule.new(:_COMMENT_1, "43.1", [:star, :_COMMENT_2], kind: :terminal).extend(EBNF::PEG::Rule),
|
115
|
+
EBNF::Rule.new(:_COMMENT_2, "43.2", [:range, "^#xd#xa#xc"], kind: :terminal).extend(EBNF::PEG::Rule),
|
116
|
+
EBNF::Rule.new(:STRING, "44", [:seq, :STRING_LITERAL_QUOTE], kind: :terminal).extend(EBNF::PEG::Rule),
|
117
|
+
EBNF::Rule.new(:NUMBER, "45", [:seq, :_NUMBER_1, :_NUMBER_2, :_NUMBER_3, :_NUMBER_4], kind: :terminal).extend(EBNF::PEG::Rule),
|
118
|
+
EBNF::Rule.new(:_NUMBER_1, "45.1", [:opt, :SIGN], kind: :terminal).extend(EBNF::PEG::Rule),
|
119
|
+
EBNF::Rule.new(:_NUMBER_2, "45.2", [:plus, :_NUMBER_5], kind: :terminal).extend(EBNF::PEG::Rule),
|
120
|
+
EBNF::Rule.new(:_NUMBER_5, "45.5", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
121
|
+
EBNF::Rule.new(:_NUMBER_3, "45.3", [:opt, "."], kind: :terminal).extend(EBNF::PEG::Rule),
|
122
|
+
EBNF::Rule.new(:_NUMBER_4, "45.4", [:star, :_NUMBER_6], kind: :terminal).extend(EBNF::PEG::Rule),
|
123
|
+
EBNF::Rule.new(:_NUMBER_6, "45.6", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
124
|
+
EBNF::Rule.new(:BOOL, "46", [:alt, "true", "false"], kind: :terminal).extend(EBNF::PEG::Rule),
|
125
|
+
EBNF::Rule.new(:STRING_LITERAL_QUOTE, "47", [:seq, "\"", :_STRING_LITERAL_QUOTE_1, "\""], kind: :terminal).extend(EBNF::PEG::Rule),
|
126
|
+
EBNF::Rule.new(:_STRING_LITERAL_QUOTE_1, "47.1", [:star, :_STRING_LITERAL_QUOTE_2], kind: :terminal).extend(EBNF::PEG::Rule),
|
127
|
+
EBNF::Rule.new(:_STRING_LITERAL_QUOTE_2, "47.2", [:alt, :_STRING_LITERAL_QUOTE_3, "'", "\""], kind: :terminal).extend(EBNF::PEG::Rule),
|
128
|
+
EBNF::Rule.new(:_STRING_LITERAL_QUOTE_3, "47.3", [:range, "^\"#xd#xa"], kind: :terminal).extend(EBNF::PEG::Rule),
|
129
|
+
EBNF::Rule.new(:ALNUM_PLUS, "48", [:seq, :PN_CHARS_BASE, :_ALNUM_PLUS_1], kind: :terminal).extend(EBNF::PEG::Rule),
|
130
|
+
EBNF::Rule.new(:_ALNUM_PLUS_1, "48.1", [:opt, :_ALNUM_PLUS_2], kind: :terminal).extend(EBNF::PEG::Rule),
|
131
|
+
EBNF::Rule.new(:_ALNUM_PLUS_2, "48.2", [:seq, :_ALNUM_PLUS_3, :PN_CHARS], kind: :terminal).extend(EBNF::PEG::Rule),
|
132
|
+
EBNF::Rule.new(:_ALNUM_PLUS_3, "48.3", [:star, :_ALNUM_PLUS_4], kind: :terminal).extend(EBNF::PEG::Rule),
|
133
|
+
EBNF::Rule.new(:_ALNUM_PLUS_4, "48.4", [:alt, :PN_CHARS, "."], kind: :terminal).extend(EBNF::PEG::Rule),
|
134
|
+
EBNF::Rule.new(:IRI, "49", [:seq, "<", :_IRI_1, ">"], kind: :terminal).extend(EBNF::PEG::Rule),
|
135
|
+
EBNF::Rule.new(:_IRI_1, "49.1", [:star, :_IRI_2], kind: :terminal).extend(EBNF::PEG::Rule),
|
136
|
+
EBNF::Rule.new(:_IRI_2, "49.2", [:alt, :PN_CHARS, ".", ":", "/", "\\", "#", "@", "%", "&", :UCHAR], kind: :terminal).extend(EBNF::PEG::Rule),
|
137
|
+
EBNF::Rule.new(:PN_CHARS, "50", [:alt, :PN_CHARS_U, :_PN_CHARS_1], kind: :terminal).extend(EBNF::PEG::Rule),
|
138
|
+
EBNF::Rule.new(:_PN_CHARS_1, "50.1", [:range, "-0-9#xB7#x0300-#x036F#x203F-#x2040"], kind: :terminal).extend(EBNF::PEG::Rule),
|
139
|
+
EBNF::Rule.new(:PN_CHARS_U, "51", [:alt, :PN_CHARS_BASE, "_"], kind: :terminal).extend(EBNF::PEG::Rule),
|
140
|
+
EBNF::Rule.new(:DATETYPE, "52", [:alt, :TIMESTAMP, :DATE, :TIME], kind: :terminal).extend(EBNF::PEG::Rule),
|
141
|
+
EBNF::Rule.new(:DATE, "53", [:seq, :_DATE_1, :_DATE_2, :_DATE_3, :_DATE_4, "-", :_DATE_5, :_DATE_6, "-", :_DATE_7, :_DATE_8], kind: :terminal).extend(EBNF::PEG::Rule),
|
142
|
+
EBNF::Rule.new(:_DATE_1, "53.1", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
143
|
+
EBNF::Rule.new(:_DATE_2, "53.2", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
144
|
+
EBNF::Rule.new(:_DATE_3, "53.3", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
145
|
+
EBNF::Rule.new(:_DATE_4, "53.4", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
146
|
+
EBNF::Rule.new(:_DATE_5, "53.5", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
147
|
+
EBNF::Rule.new(:_DATE_6, "53.6", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
148
|
+
EBNF::Rule.new(:_DATE_7, "53.7", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
149
|
+
EBNF::Rule.new(:_DATE_8, "53.8", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
150
|
+
EBNF::Rule.new(:TIME, "54", [:seq, :_TIME_1, :_TIME_2, ":", :_TIME_3, :_TIME_4, ":", :_TIME_5, :_TIME_6, :_TIME_7], kind: :terminal).extend(EBNF::PEG::Rule),
|
151
|
+
EBNF::Rule.new(:_TIME_1, "54.1", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
152
|
+
EBNF::Rule.new(:_TIME_2, "54.2", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
153
|
+
EBNF::Rule.new(:_TIME_3, "54.3", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
154
|
+
EBNF::Rule.new(:_TIME_4, "54.4", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
155
|
+
EBNF::Rule.new(:_TIME_5, "54.5", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
156
|
+
EBNF::Rule.new(:_TIME_6, "54.6", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
157
|
+
EBNF::Rule.new(:_TIME_7, "54.7", [:opt, :TIMEZONE], kind: :terminal).extend(EBNF::PEG::Rule),
|
158
|
+
EBNF::Rule.new(:TIMEZONE, "55", [:seq, :_TIMEZONE_1, :_TIMEZONE_2, :_TIMEZONE_3, ":", :_TIMEZONE_4, :_TIMEZONE_5], kind: :terminal).extend(EBNF::PEG::Rule),
|
159
|
+
EBNF::Rule.new(:_TIMEZONE_1, "55.1", [:opt, :SIGN], kind: :terminal).extend(EBNF::PEG::Rule),
|
160
|
+
EBNF::Rule.new(:_TIMEZONE_2, "55.2", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
161
|
+
EBNF::Rule.new(:_TIMEZONE_3, "55.3", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
162
|
+
EBNF::Rule.new(:_TIMEZONE_4, "55.4", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
163
|
+
EBNF::Rule.new(:_TIMEZONE_5, "55.5", [:range, "0-9"], kind: :terminal).extend(EBNF::PEG::Rule),
|
164
|
+
EBNF::Rule.new(:TIMESTAMP, "56", [:seq, :DATE, "T", :TIME], kind: :terminal).extend(EBNF::PEG::Rule),
|
165
|
+
EBNF::Rule.new(:SIGN, "57", [:alt, "+", "-"], kind: :terminal).extend(EBNF::PEG::Rule),
|
166
|
+
EBNF::Rule.new(:UCHAR, "58", [:seq, :_UCHAR_1, :HEX, :HEX, :HEX, :HEX], kind: :terminal).extend(EBNF::PEG::Rule),
|
167
|
+
EBNF::Rule.new(:_UCHAR_1, "58.1", [:alt, "u", :_UCHAR_2], kind: :terminal).extend(EBNF::PEG::Rule),
|
168
|
+
EBNF::Rule.new(:_UCHAR_2, "58.2", [:seq, "U", :HEX, :HEX, :HEX, :HEX], kind: :terminal).extend(EBNF::PEG::Rule),
|
169
|
+
EBNF::Rule.new(:PN_CHARS_BASE, "59", [:range, "A-Za-z0-9#xC0-#xD6#xD8-#xF6#xF8-#x2FF#x370-#x37D#x37F-#x1FFF#x200C-#x200D#x2070-#x218F#x2C00-#x2FEF#x3001-#xD7FF#xF900-#xFDCF#xFDF0-#xFFFD"], kind: :terminal).extend(EBNF::PEG::Rule),
|
170
|
+
EBNF::Rule.new(:HEX, "60", [:range, "0-9A-Fa-f"], kind: :terminal).extend(EBNF::PEG::Rule),
|
171
|
+
EBNF::Rule.new(:WS, "61", [:plus, :_WS_1], kind: :terminal).extend(EBNF::PEG::Rule),
|
172
|
+
EBNF::Rule.new(:_WS_1, "61.1", [:alt, :_WS_2, :COMMENT], kind: :terminal).extend(EBNF::PEG::Rule),
|
173
|
+
EBNF::Rule.new(:_WS_2, "61.2", [:range, "#x20#x9#xa"], kind: :terminal).extend(EBNF::PEG::Rule),
|
174
|
+
]
|
175
|
+
end
|
176
|
+
|
@@ -0,0 +1,413 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'ebnf'
|
3
|
+
require 'yarspg/meta'
|
4
|
+
require 'yarspg/terminals'
|
5
|
+
require 'json/canonicalization'
|
6
|
+
|
7
|
+
module YARSPG
|
8
|
+
##
|
9
|
+
# A parser for YARS-PG.
|
10
|
+
#
|
11
|
+
# Parses into RDF*, taking liberties with the meaning of a Property Graph.
|
12
|
+
#
|
13
|
+
# Issues:
|
14
|
+
# * Is it an error to parse data outside of a declared section? (warning?)
|
15
|
+
# * Node lables are treated like types
|
16
|
+
# * Node properties are treated like statements on that node
|
17
|
+
# * Node string annotations are treated like statements with the predicate created as a document fragment.
|
18
|
+
# * Edge labels and Edge ids are ignored.
|
19
|
+
# * The `graph_name` of each edge is used only for properties and annotations, the edges themselves are in the default graph (per RDF* semantics).
|
20
|
+
# * Node and Edge schemas are ignored.
|
21
|
+
|
22
|
+
class Reader < RDF::Reader
|
23
|
+
format Format
|
24
|
+
include EBNF::PEG::Parser
|
25
|
+
include YARSPG::Meta
|
26
|
+
include YARSPG::Terminals
|
27
|
+
include RDF::Util::Logger
|
28
|
+
|
29
|
+
SECTION_ORDERS = {
|
30
|
+
METADATA: 0,
|
31
|
+
"NODE SCHEMAS": 1,
|
32
|
+
"EDGE SCHEMAS": 2,
|
33
|
+
NODES: 3,
|
34
|
+
EDGES: 4
|
35
|
+
}
|
36
|
+
|
37
|
+
PartialStatement = Struct.new(:predicate, :object)
|
38
|
+
|
39
|
+
# Terminial definitions
|
40
|
+
|
41
|
+
# Always return a literal, to distinguish between actual string terminals.
|
42
|
+
terminal(:STRING, STRING) {|value| RDF::Literal(value[1..-2])}
|
43
|
+
terminal(:NUMBER, NUMBER) do |value|
|
44
|
+
value.include?('.') ?
|
45
|
+
RDF::Literal::Decimal.new(value) :
|
46
|
+
RDF::Literal::Integer.new(value)
|
47
|
+
end
|
48
|
+
|
49
|
+
terminal(:BOOL, BOOL) {|value| RDF::Literal::Boolean.new(value)}
|
50
|
+
terminal(:ALNUM_PLUS, ALNUM_PLUS)
|
51
|
+
terminal(:IRI, IRI) { |value| base_uri.join(value[1..-2])}
|
52
|
+
terminal(:DATE, DATE) {|value| RDF::Literal::Date.new(value)}
|
53
|
+
terminal(:TIME, TIME) {|value| RDF::Literal::Time.new(value)}
|
54
|
+
terminal(:TIMESTAMP, TIMESTAMP) {|value| RDF::Literal::DateTime.new(value)}
|
55
|
+
|
56
|
+
# `[3] prefix_directive ::= ('::' | pname) IRI`
|
57
|
+
production(:prefix_directive) do |value, data, callback|
|
58
|
+
if value.first[:_prefix_directive_1] == '::'
|
59
|
+
callback.call(:base_uri, value.last[:IRI])
|
60
|
+
else
|
61
|
+
pfx = value.first[:_prefix_directive_1].to_sym
|
62
|
+
prefixes[pfx] = value.last[:IRI]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# `[4] pname ::= ":" ALNUM_PLUS ":"`
|
67
|
+
production(:pname) {|value| value[1][:ALNUM_PLUS]}
|
68
|
+
|
69
|
+
# `[5] pn_local ::= ALNUM_PLUS`
|
70
|
+
#
|
71
|
+
# This must be a prefix
|
72
|
+
production(:pn_local) do |value|
|
73
|
+
pfx = value.first[:ALNUM_PLUS].to_sym
|
74
|
+
error("pn_local", "no prefix defined for #{pfx}") unless prefixes[pfx]
|
75
|
+
prefixes[pfx]
|
76
|
+
end
|
77
|
+
|
78
|
+
# `[6] metadata ::= "-" ((pn_local pname) | (IRI ":")) (STRING | IRI)`
|
79
|
+
production(:metadata) do |value, data, callback|
|
80
|
+
pred = value[1][:_metadata_1]
|
81
|
+
obj = value[2][:_metadata_2]
|
82
|
+
callback.call(:statement, :metadata, base_uri, pred, obj)
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
# `(seq pn_local pname)`
|
86
|
+
production(:_metadata_3) {|value| value.first[:pn_local].join(value.last[:pname])}
|
87
|
+
# `(seq IRI ":")`
|
88
|
+
production(:_metadata_4) {|value| value.first[:IRI]}
|
89
|
+
|
90
|
+
# `[6a] graph_name ::= STRING`
|
91
|
+
production(:graph_name) {|value| base_uri.join("##{value.first[:STRING]}")}
|
92
|
+
|
93
|
+
production(:annotation) {|value| value}
|
94
|
+
|
95
|
+
# `[8] string_annotation ::= STRING ":" STRING`
|
96
|
+
#
|
97
|
+
# Treated as an RDF annotation where the string is interpreted as a predicate based on the base_uri.
|
98
|
+
production(:string_annotation) do |value|
|
99
|
+
pred = base_uri.join("##{value.first[:STRING]}")
|
100
|
+
obj = value.last[:STRING]
|
101
|
+
PartialStatement.new(pred, obj)
|
102
|
+
end
|
103
|
+
|
104
|
+
# `[9] rdf_annotation ::= ((pn_local pname) | (IRI ":")) (STRING | IRI)`
|
105
|
+
#
|
106
|
+
# Returns a statement without subject
|
107
|
+
production(:rdf_annotation) do |value|
|
108
|
+
pred = value.first[:_rdf_annotation_1]
|
109
|
+
obj = value.last[:_rdf_annotation_2]
|
110
|
+
PartialStatement.new(pred, obj)
|
111
|
+
end
|
112
|
+
# `(seq pn_local pname)`
|
113
|
+
production(:_rdf_annotation_3) {|value| value.first[:pn_local].join(value.last[:pname])}
|
114
|
+
# `(seq IRI ":")`
|
115
|
+
production(:_rdf_annotation_4) {|value| value.first[:IRI]}
|
116
|
+
|
117
|
+
# `[10] annotations_list ::= "+" annotation ("," annotation)*`
|
118
|
+
production(:annotations_list) do |value|
|
119
|
+
value.last[:_annotations_list_1].unshift(value[1][:annotation])
|
120
|
+
end
|
121
|
+
# `(star _annotations_list_2)`
|
122
|
+
production(:_annotations_list_1) {|value| value.map {|al| al[1][:annotation]}}
|
123
|
+
|
124
|
+
# `[11] props_list ::= "[" prop ("," prop)* "]"`
|
125
|
+
production(:props_list) do |value|
|
126
|
+
value[2][:_props_list_1].unshift(value[1][:prop])
|
127
|
+
end
|
128
|
+
# `(star _props_list_2)`
|
129
|
+
production(:_props_list_1) {|value| value.map {|prop| prop[1][:prop]}}
|
130
|
+
|
131
|
+
# `[12] graphs_list ::= "/" graph_name ("," graph_name)* "/"`
|
132
|
+
production(:graphs_list) do |value|
|
133
|
+
value[2][:_graphs_list_1].unshift(value[1][:graph_name])
|
134
|
+
end
|
135
|
+
# `seq "," graph_name)`
|
136
|
+
production(:_graphs_list_2) {|value| value.last[:graph_name]}
|
137
|
+
|
138
|
+
# `[13] node ::= "<" node_id ">" ("{" node_label ("," node_label)* "}")? props_list? graphs_list? annotations_list?
|
139
|
+
production(:node) do |value, data, callback|
|
140
|
+
subject = value[1][:node_id]
|
141
|
+
types = Array(value[3][:_node_1])
|
142
|
+
props = Array(value[4][:_node_2])
|
143
|
+
graphs = Array(value[5][:_node_3])
|
144
|
+
annotations = Array(value[6][:_node_4])
|
145
|
+
|
146
|
+
# Generate statements in named graphs, if present, otherwise, the default graph
|
147
|
+
graphs = [false] if graphs.empty?
|
148
|
+
graphs.each do |graph_name|
|
149
|
+
# Yield statements
|
150
|
+
types.each do |type|
|
151
|
+
callback.call(:statement, :node, subject, RDF.type, type, graph_name)
|
152
|
+
end
|
153
|
+
emit_statements(subject, props, graph_name) {|s, p, o, g| callback.call(:statement, :node, s, p, o, g)}
|
154
|
+
emit_statements(subject, annotations, graph_name) {|s, p, o, g| callback.call(:statement, :node, s, p, o, g)}
|
155
|
+
end
|
156
|
+
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
# `(seq "{" node_label _node_6 "}")`
|
160
|
+
production(:_node_5) do |value|
|
161
|
+
value[2][:_node_6].unshift(value[1][:node_label])
|
162
|
+
end
|
163
|
+
# `(seq "," node_label)`
|
164
|
+
production(:_node_7) {|value| value.last[:node_label]}
|
165
|
+
|
166
|
+
# `[14] edge ::= directed | undirected`
|
167
|
+
#
|
168
|
+
# Ignores `edge_id` and `edge_label`. Treats `node_id` as a document-relative fragment.
|
169
|
+
production(:edge) do |value, data, callback|
|
170
|
+
value[:graphs].each do |graph_name|
|
171
|
+
# Statements in graphs, with inverse statement if :undirected
|
172
|
+
edges = [RDF::Statement(value[:subject], value[:predicate], value[:object])]
|
173
|
+
edges << RDF::Statement(value[:object], value[:predicate], value[:subject]) if value[:undirected]
|
174
|
+
|
175
|
+
edges.each do |edge|
|
176
|
+
# Emit each edge (per RDF*, edges don't have graph names)
|
177
|
+
callback.call(:statement, :edge, edge.subject, edge.predicate, edge.object)
|
178
|
+
emit_statements(edge, value[:props], graph_name) {|s, p, o, g| callback.call(:statement, :edge, s, p, o, g)}
|
179
|
+
emit_statements(edge, value[:annotations], graph_name) {|s, p, o, g| callback.call(:statement, :edge, s, p, o, g)}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# `[15] section ::= "%" SECTION_NAME`
|
185
|
+
production(:section) do |value|
|
186
|
+
# Note the section we're parsing; this can generate a warning if parsing something outside the section (other than the next section), or if seeing past the last section
|
187
|
+
section = value.last[:SECTION_NAME].to_sym
|
188
|
+
if !@in_section.nil? && @in_section > SECTION_ORDERS[section.to_sym]
|
189
|
+
warn("section", "parsing section #{section} out of order.")
|
190
|
+
end
|
191
|
+
@in_section = SECTION_ORDERS[section.to_sym]
|
192
|
+
{section: section.to_sym}
|
193
|
+
end
|
194
|
+
|
195
|
+
# `[16] directed ::= "(" node_id ")" "-" ("<" edge_id ">")? "{" edge_label "}" props_list? "->" "(" node_id ")" graphs_list? annotations_list?`
|
196
|
+
production(:directed) do |value|
|
197
|
+
{
|
198
|
+
subject: value[1][:node_id],
|
199
|
+
predicate: value[6][:edge_label],
|
200
|
+
object: value[11][:node_id],
|
201
|
+
props: Array(value[8][:_directed_2]),
|
202
|
+
graphs: Array(value[13][:_directed_3] || false),
|
203
|
+
annotations: Array(value[14][ :_directed_4])
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
# `[17] undirected ::= "(" node_id ")" "-" ("<" edge_id ">")? "{" edge_label "}" props_list? "-" "(" node_id ")" graphs_list?` annotations_list?
|
208
|
+
production(:undirected) do |value|
|
209
|
+
{
|
210
|
+
subject: value[1][:node_id],
|
211
|
+
predicate: value[6][:edge_label],
|
212
|
+
object: value[11][:node_id],
|
213
|
+
props: Array(value[8][:_undirected_2]),
|
214
|
+
graphs: Array(value[13][:_undirected_3] || false),
|
215
|
+
annotations: Array(value[14][ :_undirected_4]),
|
216
|
+
undirected: true
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
# `[18] node_id ::= STRING`
|
221
|
+
production(:node_id) {|value| base_uri.join("##{value.first[:STRING]}")}
|
222
|
+
|
223
|
+
# `[19] node_label ::= STRING`
|
224
|
+
production(:node_label) {|value| base_uri.join("##{value.first[:STRING]}")}
|
225
|
+
|
226
|
+
# `[20] prop ::= key ":" value
|
227
|
+
#
|
228
|
+
# Treated as an String annotation.
|
229
|
+
production(:prop) do |value|
|
230
|
+
pred = base_uri.join("##{value.first[:key]}")
|
231
|
+
obj = value.last[:value]
|
232
|
+
PartialStatement.new(pred, obj)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Ignored
|
236
|
+
#production(:edge_id) {|value| value}
|
237
|
+
production(:edge_label) {|value| base_uri.join("##{value.first[:STRING]}")}
|
238
|
+
production(:key) {|value| value.first[:STRING].to_s}
|
239
|
+
#production(:value) {|value| value}
|
240
|
+
|
241
|
+
# `[25] primitive_value ::= STRING | DATETYPE | NUMBER | BOOL | "null"`
|
242
|
+
production(:primitive_value) {|value| value == "null" ? RDF.nil : value}
|
243
|
+
|
244
|
+
# `[26] complex_value ::= set | list | struct`
|
245
|
+
#
|
246
|
+
# At the start, record that we're from a complex value, so proper RDF values are created only after recursive calls are complete.
|
247
|
+
start_production(:complex_value) {|data| data[:from_complex_value] = true}
|
248
|
+
production(:complex_value) {|value| value}
|
249
|
+
|
250
|
+
# 27] set ::= "{" (primitive_value | set) ("," (primitive_value | set))* "}"
|
251
|
+
#
|
252
|
+
# Because this is recursive, we'll only return a JSON literal if called from complex_value
|
253
|
+
production(:set) do |value|
|
254
|
+
set = value[2][:_set_2].unshift(value[1][:_set_1])
|
255
|
+
if prod_data[:from_complex_value]
|
256
|
+
# Wrap value in a literal
|
257
|
+
RDF::Literal(set.to_json_c14n, datatype: RDF.JSON)
|
258
|
+
else
|
259
|
+
set
|
260
|
+
end
|
261
|
+
end
|
262
|
+
# `(alt primitive_value struct)`
|
263
|
+
production(:_set_1) {|value| value.is_a?(RDF::Literal) ? value.to_s : value}
|
264
|
+
# `(seq "," _set_4)`
|
265
|
+
production(:_set_3) {|value| value.last[:_set_4]}
|
266
|
+
# `(alt primitive_value struct)`
|
267
|
+
production(:_set_4) {|value| value.is_a?(RDF::Literal) ? value.to_s : value}
|
268
|
+
|
269
|
+
# `[28] list ::= "[" (primitive_value | list) ("," (primitive_value | list))* "]"`
|
270
|
+
production(:list) do |value|
|
271
|
+
RDF::List(value[2][:_list_2].unshift(value[1][:_list_1]))
|
272
|
+
end
|
273
|
+
# (star _list_3)
|
274
|
+
production(:_list_2) do |value|
|
275
|
+
value.map {|li| li.last[:_list_4]}
|
276
|
+
end
|
277
|
+
|
278
|
+
# `[29] struct ::= "{" key ":" (primitive_value | struct) ("," key ":" (primitive_value | struct))* "}"`
|
279
|
+
#
|
280
|
+
# Because this is recursive, we'll only return a JSON literal if called from complex_value
|
281
|
+
production(:struct) do |value|
|
282
|
+
struct = {value[1][:key] => value[3][:_struct_1]}.merge(value[4][:_struct_2])
|
283
|
+
if prod_data[:from_complex_value]
|
284
|
+
# Wrap value in a literal
|
285
|
+
RDF::Literal(struct.to_json_c14n, datatype: RDF.JSON)
|
286
|
+
else
|
287
|
+
struct
|
288
|
+
end
|
289
|
+
end
|
290
|
+
# `(alt primitive_value struct)`
|
291
|
+
production(:_struct_1) {|value| value.is_a?(RDF::Literal) ? value.to_s : value}
|
292
|
+
# `(star _struct_3)`
|
293
|
+
production(:_struct_2) do |value|
|
294
|
+
value.inject({}) {|memo, struct| memo.merge(struct)}
|
295
|
+
end
|
296
|
+
# `(seq "," key ":" _struct_4)`
|
297
|
+
production(:_struct_3) {|value| {value[1][:key] => value[3][:_struct_4]}}
|
298
|
+
# `(alt primitive_value struct)`
|
299
|
+
production(:_struct_4) {|value| value.is_a?(RDF::Literal) ? value.to_s : value}
|
300
|
+
|
301
|
+
production(:node_schema) {|value| value}
|
302
|
+
production(:props_list_schema) {|value| value}
|
303
|
+
production(:prop_schema) {|value| value}
|
304
|
+
production(:value_schema) {|value| value}
|
305
|
+
production(:primitive_value_schema) {|value| value}
|
306
|
+
production(:complex_value_schema) {|value| value}
|
307
|
+
production(:set_schema) {|value| value}
|
308
|
+
production(:list_schema) {|value| value}
|
309
|
+
production(:struct_schema) {|value| value}
|
310
|
+
production(:edge_schema) {|value| value}
|
311
|
+
production(:directed_schema) {|value| value}
|
312
|
+
production(:undirected_schema) {|value| value}
|
313
|
+
|
314
|
+
##
|
315
|
+
# Initializes a new reader instance.
|
316
|
+
#
|
317
|
+
# This assumes that strings are interpreted as document-relative fragments.
|
318
|
+
#
|
319
|
+
# @param [String, #to_s] input
|
320
|
+
# @param [Hash{Symbol => Object}] options
|
321
|
+
# @option options [Hash] :prefixes (Hash.new)
|
322
|
+
# the prefix mappings to use (for acessing intermediate parser productions)
|
323
|
+
# @option options [#to_s] :base_uri (nil)
|
324
|
+
# the base URI to use when resolving relative URIs (for acessing intermediate parser productions)
|
325
|
+
# @option options [Boolean] :validate (false)
|
326
|
+
# whether to validate the parsed statements and values. If not validating,
|
327
|
+
# the parser will attempt to recover from errors.
|
328
|
+
# @option options [Logger, #write, #<<] :logger
|
329
|
+
# Record error/info/debug output
|
330
|
+
# @return [YARSPG::Reader]
|
331
|
+
def initialize(input = nil, **options, &block)
|
332
|
+
super do
|
333
|
+
@options[:base_uri] = RDF::URI(base_uri || "")
|
334
|
+
@options[:logger] = false unless @options.has_key?(:logger)
|
335
|
+
log_debug("base IRI") {base_uri.inspect}
|
336
|
+
|
337
|
+
if block_given?
|
338
|
+
case block.arity
|
339
|
+
when 0 then instance_eval(&block)
|
340
|
+
else block.call(self)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def inspect
|
347
|
+
sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, base_uri.to_s)
|
348
|
+
end
|
349
|
+
|
350
|
+
##
|
351
|
+
# Iterates the given block for each RDF statement in the input.
|
352
|
+
#
|
353
|
+
# @yield [statement]
|
354
|
+
# @yieldparam [RDF::Statement] statement
|
355
|
+
# @return [void]
|
356
|
+
def each_statement(&block)
|
357
|
+
if block_given?
|
358
|
+
log_recover
|
359
|
+
@callback = block
|
360
|
+
|
361
|
+
begin
|
362
|
+
parse(@input, :yarspg, YARSPG::Meta::RULES, **@options) do |context, *data|
|
363
|
+
case context
|
364
|
+
when :base_uri
|
365
|
+
@options[:base_uri] = data.first
|
366
|
+
when :statement
|
367
|
+
loc = data.shift
|
368
|
+
@callback.call(RDF::Statement.from(data))
|
369
|
+
end
|
370
|
+
end
|
371
|
+
rescue EBNF::PEG::Parser::Error
|
372
|
+
# Terminate loop if Errors found while parsing
|
373
|
+
end
|
374
|
+
|
375
|
+
if validate? && log_statistics[:error]
|
376
|
+
raise RDF::ReaderError, "Errors found during processing"
|
377
|
+
end
|
378
|
+
end
|
379
|
+
enum_for(:each_statement)
|
380
|
+
end
|
381
|
+
|
382
|
+
##
|
383
|
+
# Iterates the given block for each RDF triple in the input.
|
384
|
+
#
|
385
|
+
# @yield [subject, predicate, object]
|
386
|
+
# @yieldparam [RDF::Resource] subject
|
387
|
+
# @yieldparam [RDF::URI] predicate
|
388
|
+
# @yieldparam [RDF::Value] object
|
389
|
+
# @return [void]
|
390
|
+
def each_triple(&block)
|
391
|
+
if block_given?
|
392
|
+
each_statement do |statement|
|
393
|
+
block.call(*statement.to_triple)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
enum_for(:each_triple)
|
397
|
+
end
|
398
|
+
|
399
|
+
# Emit statements, accounting for lists
|
400
|
+
def emit_statements(subject, partials, graph_name)
|
401
|
+
partials.each do |partial|
|
402
|
+
if partial.object.list?
|
403
|
+
yield(subject, partial.predicate, partial.object.subject, graph_name)
|
404
|
+
partial.object.each_statement do |st|
|
405
|
+
yield(st.subject, st.predicate, st.object, graph_name)
|
406
|
+
end
|
407
|
+
else
|
408
|
+
yield(subject, partial.predicate, partial.object, graph_name)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Terminal definitions for EBNF Parser
|
3
|
+
module YARSPG::Terminals
|
4
|
+
U_CHARS1 = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
|
5
|
+
[\\u00C0-\\u00D6]|[\\u00D8-\\u00F6]|[\\u00F8-\\u02FF]|
|
6
|
+
[\\u0370-\\u037D]|[\\u037F-\\u1FFF]|[\\u200C-\\u200D]|
|
7
|
+
[\\u2070-\\u218F]|[\\u2C00-\\u2FEF]|[\\u3001-\\uD7FF]|
|
8
|
+
[\\uF900-\\uFDCF]|[\\uFDF0-\\uFFFD]|[\\u{10000}-\\u{EFFFF}]
|
9
|
+
EOS
|
10
|
+
U_CHARS2 = Regexp.compile("\\u00B7|[\\u0300-\\u036F]|[\\u203F-\\u2040]", Regexp::FIXEDENCODING).freeze
|
11
|
+
IRI_RANGE = Regexp.compile("[[^<>\"{}|^`\\\\]&&[^\\x00-\\x20]]", Regexp::FIXEDENCODING).freeze
|
12
|
+
UCHAR = EBNF::LL1::Lexer::UCHAR
|
13
|
+
|
14
|
+
STRING_LITERAL_QUOTE = /"([^\"\\\n\r]|#{UCHAR})*"/.freeze
|
15
|
+
SIGN = %r([\+\-])u.freeze
|
16
|
+
PN_CHARS_BASE = %r([A-Z]|[a-z]|[0-9]|#{U_CHARS1})u.freeze
|
17
|
+
PN_CHARS_U = %r(_|(?:#{PN_CHARS_BASE}))u.freeze
|
18
|
+
PN_CHARS = %r(-|[0-9]|(?:#{PN_CHARS_U})|#{U_CHARS2})u.freeze
|
19
|
+
STRING = %r(#{STRING_LITERAL_QUOTE})u.freeze
|
20
|
+
NUMBER = %r((?:#{SIGN})?\d+(\.\d*)?)u.freeze
|
21
|
+
BOOL = %r(true|false)u.freeze
|
22
|
+
ALNUM_PLUS = %r((?:#{PN_CHARS_BASE})(?:(?:(?:#{PN_CHARS})|\.)*(?:#{PN_CHARS}))?)u.freeze
|
23
|
+
IRI = /<(?:(?:#{IRI_RANGE})|(?:#{UCHAR}))*>/u.freeze # prob with grammar
|
24
|
+
DATE = %r(\d\d\d\d-\d\d-\d\d)u.freeze
|
25
|
+
TIMEZONE = %r((?:#{SIGN})?\d\d:\d\d)u.freeze
|
26
|
+
TIME = %r(\d\d:\d\d:\d\d(?:#{TIMEZONE})?)u.freeze
|
27
|
+
TIMESTAMP = %r((?:#{DATE})T(?:#{TIME}))u.freeze
|
28
|
+
HEX = %r(\#x[0-9a-fA-F]+)u.freeze
|
29
|
+
COMMENT = /(?:#[^\n\r\r]*)/u.freeze
|
30
|
+
WS = /(?:\s|(?:#{COMMENT}))+/m.freeze
|
31
|
+
end
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yarspg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gregg Kellogg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-06-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rdf
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ebnf
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json-canonicalization
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sxp
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rdf-xsd
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdf-spec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.9'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec-its
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yard
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.9.20
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.9.20
|
139
|
+
description: YARSPG is an YARS-PG reader/writer for the RDF.rb library suite.
|
140
|
+
email: gregg@greggkellogg.net
|
141
|
+
executables: []
|
142
|
+
extensions: []
|
143
|
+
extra_rdoc_files: []
|
144
|
+
files:
|
145
|
+
- README.md
|
146
|
+
- UNLICENSE
|
147
|
+
- VERSION
|
148
|
+
- lib/yarspg.rb
|
149
|
+
- lib/yarspg/format.rb
|
150
|
+
- lib/yarspg/meta.rb
|
151
|
+
- lib/yarspg/reader.rb
|
152
|
+
- lib/yarspg/terminals.rb
|
153
|
+
- lib/yarspg/version.rb
|
154
|
+
- lib/yarspg/writer.rb
|
155
|
+
homepage: https://github.com/gkellogg/yarspg
|
156
|
+
licenses:
|
157
|
+
- Unlicense
|
158
|
+
metadata: {}
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '2.4'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubygems_version: 3.1.3
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: YARS-PG reader/writer for RDF.rb.
|
178
|
+
test_files: []
|