spdx 2.0.11 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +71 -5
- data/exceptions.json +2 -2
- data/lib/spdx.rb +69 -189
- data/lib/spdx/version.rb +1 -1
- data/lib/spdx_grammar.rb +54 -9
- data/lib/spdx_parser.rb +36 -8
- data/lib/spdx_parser.treetop +34 -17
- data/licenses.json +703 -433
- data/spdx.gemspec +1 -2
- data/spec/spdx_spec.rb +93 -198
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57eb1d8fa593ee4d8502733dd5257f050a5a421e8e272036517f146a362f1eea
|
4
|
+
data.tar.gz: e6d33c4be673643a9e052df93fcac4d41a3c8c809fca6293482979f0ffb62fb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29d8dd9dd27711bc077d2a6828cfa58a8f378a5bcd2e6a0b3915fc070e2561b03b412f7683027985d50624a013310d6e4bdd4f053e3646c4fb659d4675553fd6
|
7
|
+
data.tar.gz: 03ea3f99549c654a817c53077f584feaacd4a85200f008e987a7aebac684435974269ab6edac88a22d253d78f4dd9171ab12f6713c9241a5cf153966ae8b7863
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
# [Spdx](http://libraries.io/rubygems/spdx) - A SPDX license
|
2
|
-
|
3
|
-
This gem allows you to find the closest match using [FuzzyMatch](https://github.com/seamusabshere/fuzzy_match) in the [spdx-licenses](https://github.com/domcleal/spdx-licenses) list for similar (not necessarily exact) license names.
|
1
|
+
# [Spdx](http://libraries.io/rubygems/spdx) - A SPDX license parser
|
4
2
|
|
3
|
+
This gem allows you validate and parse spdx expressions. It also contains (relatively) up to date license and license exception lists from https://github.com/spdx/license-list-data/tree/master/json
|
5
4
|
## Installation
|
6
5
|
|
7
6
|
Add this line to your application's Gemfile:
|
@@ -21,14 +20,81 @@ Or install it yourself as:
|
|
21
20
|
## Usage
|
22
21
|
|
23
22
|
```ruby
|
24
|
-
Spdx.
|
23
|
+
Spdx.valid?("(MIT OR AGPL-3.0+)")
|
24
|
+
=> true
|
25
|
+
```
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Spdx.parse("MIT OR AGPL-3.0+")
|
29
|
+
=> LogicalOr+OrExpression4 offset=0, "MIT OR AGPL-3.0+":
|
30
|
+
License+LicenseId0 offset=0, "MIT" (idstring)
|
31
|
+
LicensePlus+SimpleExpression0 offset=7, "AGPL-3.0+" (license_id):
|
32
|
+
License+LicenseId0 offset=7, "AGPL-3.0" (idstring)
|
33
|
+
```
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
Spdx.normalize("Mit OR agpl-3.0+ AND APACHE-2.0")
|
37
|
+
=> "MIT OR (AGPL-3.0+ AND Apache-2.0)"
|
38
|
+
|
39
|
+
Spdx.normalize("Mit OR agpl-3.0+ AND APACHE-2.0", top_level_parens: true)
|
40
|
+
=> "(MIT OR (AGPL-3.0+ AND Apache-2.0))"
|
41
|
+
```
|
42
|
+
|
43
|
+
### Nodes
|
44
|
+
|
45
|
+
Parsed SPDX license expressions can be a number of various nodes. Each of these nodes share a few methods, most notably `text_value` which contains the text that spans that node, and `licenses` which contains an array of individual licenses used in that portion of the expression. Below are the nodes in more detail, and their additional methods.
|
46
|
+
|
47
|
+
#### `License`
|
48
|
+
|
49
|
+
This node represents a single license, and is the result of the most simple form of expression, e.g. `Spdx.parse("MIT")`. It can also be found as a child node of other nodes.
|
50
|
+
|
51
|
+
#### `LicensePlus`
|
52
|
+
|
53
|
+
This node represents the current version of a license or any later version, e.g. `Spdx.parse("CDDL-1.0+")`. The inner license node can be found via the `child` method.
|
54
|
+
|
55
|
+
#### `LicenseRef`
|
56
|
+
|
57
|
+
This node represents a reference to a license not defined in the SPDX license list, e.g. `Spdx.parse("LicenseRef-23")`.
|
58
|
+
|
59
|
+
#### `DocumentRef`
|
60
|
+
|
61
|
+
Similar to `LicenseRef`, this node also represents a reference to a license not defined in the SPDX license list, e.g. `Spdx.parse("DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2")`.
|
62
|
+
|
63
|
+
#### `LicenseException`
|
64
|
+
|
65
|
+
This node represents an exception to a license. See `With`.
|
66
|
+
|
67
|
+
#### `With`
|
68
|
+
|
69
|
+
This node represents a license with an SPDX-defined license exception, e.g. `Spdx.parse("GPL-2.0-or-later WITH Bison-exception-2.2")`. This node has two extra methods, `license` and `exception`, which return the nodes for the license portion of the expression and the exception portion of the expression, respectively.
|
70
|
+
|
71
|
+
#### `LogicalAnd`
|
72
|
+
|
73
|
+
This node represents an "AND" expression, e.g. `Spdx.parse("LGPL-2.1-only AND MIT")`. This node has two extra methods, `left` and `right`, which return the node for the left side of the expression and the node for the right side of the expression, respectively. Any node can be the child of `LogicalAnd`, including `LogicalAnd`/`LogicalOr`.
|
74
|
+
|
75
|
+
`Spdx.parse("(MIT AND GPL-1.0) OR MPL-2.0 AND Apache-2.0")` would result in the following tree:
|
76
|
+
|
77
|
+
```txt
|
78
|
+
LogicalOr
|
79
|
+
├── LogicalAnd
|
80
|
+
│ ├── License (MIT)
|
81
|
+
│ └── License (GPL-1.0)
|
82
|
+
└── LogicalAnd
|
83
|
+
├── License (MPL-2.0)
|
84
|
+
└── License Apache-2.0
|
25
85
|
```
|
26
86
|
|
87
|
+
#### `LogicalOr`
|
88
|
+
|
89
|
+
The same as `LogicalAnd`, but for "OR" expressions.
|
90
|
+
|
27
91
|
## Testing
|
28
92
|
|
29
93
|
Run the tests with:
|
30
94
|
|
31
|
-
|
95
|
+
```sh
|
96
|
+
bundle exec rspec
|
97
|
+
```
|
32
98
|
|
33
99
|
## Contributing
|
34
100
|
|
data/exceptions.json
CHANGED
data/lib/spdx.rb
CHANGED
@@ -1,187 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "spdx/version"
|
4
|
-
require "fuzzy_match"
|
5
4
|
require "spdx_parser"
|
6
5
|
require "json"
|
7
6
|
require_relative "exception"
|
8
7
|
require_relative "license"
|
9
8
|
|
10
|
-
# Fuzzy matcher for licenses to SPDX standard licenses
|
11
9
|
module Spdx
|
12
|
-
def self.find(name)
|
13
|
-
name = name.strip
|
14
|
-
return nil if commercial?(name)
|
15
|
-
return nil if non_spdx?(name)
|
16
|
-
|
17
|
-
search(name)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.search(name)
|
21
|
-
lookup(name) ||
|
22
|
-
find_by_special_case(name) ||
|
23
|
-
closest(name)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.commercial?(name)
|
27
|
-
name.casecmp("commercial").zero?
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.non_spdx?(name)
|
31
|
-
["standard pil license"].include? name.downcase
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.lookup(name)
|
35
|
-
return false if name.nil?
|
36
|
-
return lookup_license(name) if license_exists?(name)
|
37
|
-
|
38
|
-
lowercase = licenses.keys.sort.find { |k| k.casecmp(name).zero? }
|
39
|
-
lookup_license(lowercase) if lowercase
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.closest(name)
|
43
|
-
name.gsub!(/#{stop_words.join('|')}/i, "")
|
44
|
-
name.gsub!(/(\d)/, ' \1 ')
|
45
|
-
best_match = fuzzy_match(name)
|
46
|
-
return nil unless best_match
|
47
|
-
|
48
|
-
lookup(best_match) || find_by_name(best_match)
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.matches(name, max_distance = 40)
|
52
|
-
names.map { |key| [key, Text::Levenshtein.distance(name, key)] }
|
53
|
-
.select { |arr| arr[1] <= max_distance }
|
54
|
-
.sort_by { |arr| arr[1] }
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.fuzzy_match(name)
|
58
|
-
FuzzyMatch.new(names).find(name, must_match_at_least_one_word: true)
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.stop_words
|
62
|
-
%w[version software the or right all]
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.find_by_name(name)
|
66
|
-
match = licenses.find { |_k, v| v["name"] == name }
|
67
|
-
lookup(match[0]) if match
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.find_by_special_case(name)
|
71
|
-
gpl = gpl_match(name)
|
72
|
-
return gpl if gpl
|
73
|
-
|
74
|
-
lookup(special_cases[name.downcase.strip])
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.gpl_match(name)
|
78
|
-
match = name.match(/^(l|a)?gpl-?\s?_?v?(1|2|3)\.?(\d)?(\+)?$/i)
|
79
|
-
return unless match
|
80
|
-
|
81
|
-
lookup "#{match[1]}GPL-#{match[2]}.#{match[3] || 0}#{match[4]}"
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.special_cases
|
85
|
-
{
|
86
|
-
"perl_5" => "Artistic-1.0-Perl",
|
87
|
-
"bsd3" => "BSD-3-Clause",
|
88
|
-
"bsd" => "BSD-3-Clause",
|
89
|
-
"bsd license" => "BSD-3-Clause",
|
90
|
-
"new bsd license" => "BSD-3-Clause",
|
91
|
-
"gnu gpl v2" => "GPL-2.0-only",
|
92
|
-
"gpl" => "GPL-2.0+",
|
93
|
-
"gpl-2 | gpl-3 [expanded from: gpl (≥ 2.0)]" => "GPL-2.0+",
|
94
|
-
"gpl-2 | gpl-3 [expanded from: gpl]" => "GPL-2.0+",
|
95
|
-
"gpl-2 | gpl-3 [expanded from: gpl (≥ 2)]" => "GPL-2.0+",
|
96
|
-
"gpl-2 | gpl-3" => "GPL-2.0+",
|
97
|
-
"gplv2 or later" => "GPL-2.0+",
|
98
|
-
"the gpl v3" => "GPL-3.0",
|
99
|
-
"gpl (≥ 3)" => "GPL-3.0+",
|
100
|
-
"mpl2.0" => "mpl-2.0",
|
101
|
-
"mpl1" => "mpl-1.0",
|
102
|
-
"mpl1.0" => "mpl-1.0",
|
103
|
-
"mpl1.1" => "mpl-1.1",
|
104
|
-
"mpl2" => "mpl-2.0",
|
105
|
-
"gnu lesser general public license" => "LGPL-2.1+",
|
106
|
-
"lgplv2 or later" => "LGPL-2.1+",
|
107
|
-
"gpl2 w/ cpe" => "GPL-2.0-with-classpath-exception",
|
108
|
-
"new bsd license (gpl-compatible)" => "BSD-3-Clause",
|
109
|
-
"public domain" => "Unlicense",
|
110
|
-
"cc0" => "CC0-1.0",
|
111
|
-
"artistic_2" => "Artistic-2.0",
|
112
|
-
"artistic_1" => "Artistic-1.0",
|
113
|
-
"alv2" => "Apache-2.0",
|
114
|
-
"asl" => "Apache-2.0",
|
115
|
-
"asl 2.0" => "Apache-2.0",
|
116
|
-
"mpl 2.0" => "MPL-2.0",
|
117
|
-
"publicdomain" => "Unlicense",
|
118
|
-
"unlicensed" => "Unlicense",
|
119
|
-
"psfl" => "Python-2.0",
|
120
|
-
"psf" => "Python-2.0",
|
121
|
-
"psf 2" => "Python-2.0",
|
122
|
-
"psf 2.0" => "Python-2.0",
|
123
|
-
"asl2" => "Apache-2.0",
|
124
|
-
"al2" => "Apache-2.0",
|
125
|
-
"aslv2" => "Apache-2.0",
|
126
|
-
"apache_2_0" => "Apache-2.0",
|
127
|
-
"apache_v2" => "Apache-2.0",
|
128
|
-
"zpl 1.1" => "ZPL-1.1",
|
129
|
-
"zpl 2.0" => "ZPL-2.0",
|
130
|
-
"zpl 2.1" => "ZPL-2.1",
|
131
|
-
"lgpl_2_1" => "LGPL-2.1",
|
132
|
-
"lgpl_v2_1" => "LGPL-2.1",
|
133
|
-
"lgpl version 3" => "LGPL-3.0",
|
134
|
-
"gnu lgpl v3+" => "LGPL-3.0",
|
135
|
-
"gnu lgpl" => "LGPL-2.1+",
|
136
|
-
"cc by-sa 4.0" => "CC-BY-SA-4.0",
|
137
|
-
"cc by-nc-sa 3.0" => "CC-BY-NC-SA-3.0",
|
138
|
-
"cc by-sa 3.0" => "CC-BY-SA-3.0",
|
139
|
-
"mpl v2.0" => "MPL-2.0",
|
140
|
-
"mplv2.0" => "MPL-2.0",
|
141
|
-
"mplv2" => "MPL-2.0",
|
142
|
-
"cpal v1.0" => "CPAL-1.0",
|
143
|
-
"cddl 1.0" => "CDDL-1.0",
|
144
|
-
"cddl 1.1" => "CDDL-1.1",
|
145
|
-
"epl" => "EPL-1.0",
|
146
|
-
"mit-license" => "MIT",
|
147
|
-
"(mit or x11)" => "MIT",
|
148
|
-
"iscl" => "ISC",
|
149
|
-
"wtf" => "WTFPL",
|
150
|
-
"2-clause bsdl" => "BSD-2-clause",
|
151
|
-
"3-clause bsdl" => "BSD-3-clause",
|
152
|
-
"2-clause bsd" => "BSD-2-clause",
|
153
|
-
"3-clause bsd" => "BSD-3-clause",
|
154
|
-
"bsd 3-clause" => "BSD-3-clause",
|
155
|
-
"bsd 2-clause" => "BSD-2-clause",
|
156
|
-
"two-clause bsd-style license" => "BSD-2-clause",
|
157
|
-
"bsd style" => "BSD-3-clause",
|
158
|
-
"cc0 1.0 universal (cc0 1.0) public domain dedication" => "CC0-1.0",
|
159
|
-
"common development and distribution license 1.0 (cddl-1.0)" => "CDDL-1.0",
|
160
|
-
"european union public licence 1.0 (eupl 1.0)" => "EUPL-1.0",
|
161
|
-
"european union public licence 1.1 (eupl 1.1)" => "EUPL-1.1",
|
162
|
-
"european union public licence 1.2 (eupl 1.2)" => "EUPL-1.2",
|
163
|
-
"vovida software license 1.0" => "VSL-1.0",
|
164
|
-
"w3c license" => "W3C",
|
165
|
-
"zlib/libpng license" => "zlib-acknowledgement",
|
166
|
-
"gnu general public license (gpl)" => "GPL-2.0+",
|
167
|
-
"gnu general public license v2 (gplv2)" => "GPL-2.0",
|
168
|
-
"gnu general public license v2 or later (gplv2+)" => "GPL-2.0+",
|
169
|
-
"gnu general public license v3 (gplv3)" => "GPL-3.0",
|
170
|
-
"gnu general public license v3 or later (gplv3+)" => "GPL-3.0+",
|
171
|
-
"gnu lesser general public license v2 (lgplv2)" => "LGPL-2.0",
|
172
|
-
"gnu lesser general public license v2 or later (lgplv2+)" => "LGPL-2.0+",
|
173
|
-
"gnu lesser general public license v3 (lgplv3)" => "LGPL-3.0",
|
174
|
-
"gnu lesser general public license v3 or later (lgplv3+)" => "LGPL-3.0+",
|
175
|
-
"gnu library or lesser general public license (lgpl)" => "LGPL-2.0+",
|
176
|
-
"netscape public License (npl)" => "NPL-1.1",
|
177
|
-
"apache software license" => "Apache-2.0",
|
178
|
-
"academic free license (afl)" => "AFL-3.0",
|
179
|
-
"gnu free documentation license (fdl)" => "GFDL-1.3",
|
180
|
-
"sun industry standards source license (sissl)" => "SISSL-1.2",
|
181
|
-
"zope public license" => "ZPL-2.1",
|
182
|
-
}
|
183
|
-
end
|
184
|
-
|
185
10
|
def self.names
|
186
11
|
(licenses.keys + licenses.map { |_k, v| v["name"] }).sort
|
187
12
|
end
|
@@ -190,6 +15,7 @@ module Spdx
|
|
190
15
|
unless defined?(@exceptions)
|
191
16
|
data = JSON.parse(File.read(File.expand_path("../exceptions.json", __dir__)))
|
192
17
|
@exceptions = {}
|
18
|
+
|
193
19
|
data["exceptions"].each do |details|
|
194
20
|
id = details.delete("licenseExceptionId")
|
195
21
|
@exceptions[id] = details
|
@@ -199,27 +25,18 @@ module Spdx
|
|
199
25
|
end
|
200
26
|
|
201
27
|
def self.license_exists?(id)
|
202
|
-
licenses.key?(id.to_s)
|
203
|
-
end
|
204
|
-
|
205
|
-
def self.lookup_license(id)
|
206
|
-
json = licenses[id.to_s]
|
207
|
-
Spdx::License.new(id.to_s, json["name"], json["isOsiApproved"]) if json
|
208
|
-
end
|
209
|
-
|
210
|
-
def self.lookup_exception(id)
|
211
|
-
json = exceptions[id.to_s]
|
212
|
-
Spdx::Exception.new(id.to_s, json["name"], json["isDeprecatedLicenseId"]) if json
|
28
|
+
licenses.key?(id.to_s) || licenses_downcase.key?(id.to_s.downcase)
|
213
29
|
end
|
214
30
|
|
215
31
|
def self.exception_exists?(id)
|
216
|
-
exceptions.key?(id.to_s)
|
32
|
+
exceptions.key?(id.to_s) || exceptions_downcase.key?(id.to_s.downcase)
|
217
33
|
end
|
218
34
|
|
219
35
|
def self.licenses
|
220
36
|
unless defined?(@licenses)
|
221
37
|
data = JSON.parse(File.read(File.expand_path("../licenses.json", __dir__)))
|
222
38
|
@licenses = {}
|
39
|
+
|
223
40
|
data["licenses"].each do |details|
|
224
41
|
id = details.delete("licenseId")
|
225
42
|
@licenses[id] = details
|
@@ -228,7 +45,70 @@ module Spdx
|
|
228
45
|
@licenses
|
229
46
|
end
|
230
47
|
|
231
|
-
def self.
|
48
|
+
def self.licenses_downcase
|
49
|
+
unless defined?(@licenses_downcase)
|
50
|
+
@licenses_downcase = {}
|
51
|
+
licenses.keys.each { |key| @licenses_downcase[key.downcase] = key }
|
52
|
+
end
|
53
|
+
@licenses_downcase
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.exceptions_downcase
|
57
|
+
unless defined?(@exceptions_downcase)
|
58
|
+
@exceptions_downcase = {}
|
59
|
+
exceptions.keys.each { |key| @exceptions_downcase[key.downcase] = key }
|
60
|
+
end
|
61
|
+
@exceptions_downcase
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.normalize(spdx_string, top_level_parens: false)
|
65
|
+
normalize_tree(SpdxParser.parse(spdx_string), parens: top_level_parens)
|
66
|
+
end
|
67
|
+
|
68
|
+
private_class_method def self.normalize_tree(node, parens: true)
|
69
|
+
case node
|
70
|
+
when SpdxGrammar::LogicalAnd
|
71
|
+
left = normalize_tree(node.left)
|
72
|
+
right = normalize_tree(node.right)
|
73
|
+
if parens
|
74
|
+
"(#{left} AND #{right})"
|
75
|
+
else
|
76
|
+
"#{left} AND #{right}"
|
77
|
+
end
|
78
|
+
when SpdxGrammar::LogicalOr
|
79
|
+
left = normalize_tree(node.left)
|
80
|
+
right = normalize_tree(node.right)
|
81
|
+
if parens
|
82
|
+
"(#{left} OR #{right})"
|
83
|
+
else
|
84
|
+
"#{left} OR #{right}"
|
85
|
+
end
|
86
|
+
when SpdxGrammar::With
|
87
|
+
license = normalize_tree(node.license)
|
88
|
+
exception = normalize_tree(node.exception)
|
89
|
+
if parens
|
90
|
+
"(#{license} WITH #{exception})"
|
91
|
+
else
|
92
|
+
"#{license} WITH #{exception}"
|
93
|
+
end
|
94
|
+
when SpdxGrammar::None
|
95
|
+
"NONE"
|
96
|
+
when SpdxGrammar::NoAssertion
|
97
|
+
"NOASSERTION"
|
98
|
+
when SpdxGrammar::License
|
99
|
+
licenses_downcase[node.text_value.downcase]
|
100
|
+
when SpdxGrammar::LicensePlus
|
101
|
+
"#{normalize_tree(node.child)}+"
|
102
|
+
when SpdxGrammar::LicenseRef
|
103
|
+
node.text_value
|
104
|
+
when SpdxGrammar::DocumentRef
|
105
|
+
node.text_value
|
106
|
+
when SpdxGrammar::LicenseException
|
107
|
+
exceptions_downcase[node.text_value.downcase]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.valid?(spdx_string)
|
232
112
|
return false unless spdx_string.is_a?(String)
|
233
113
|
|
234
114
|
SpdxParser.parse(spdx_string)
|
@@ -237,7 +117,7 @@ module Spdx
|
|
237
117
|
false
|
238
118
|
end
|
239
119
|
|
240
|
-
def self.
|
120
|
+
def self.parse(spdx_string)
|
241
121
|
SpdxParser.parse(spdx_string)
|
242
122
|
end
|
243
123
|
end
|
data/lib/spdx/version.rb
CHANGED
data/lib/spdx_grammar.rb
CHANGED
@@ -1,19 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module SpdxGrammar
|
4
|
-
class
|
4
|
+
class LogicalBinary < Treetop::Runtime::SyntaxNode
|
5
|
+
# Used internally
|
6
|
+
|
5
7
|
def licenses
|
6
|
-
|
8
|
+
(left.licenses + right.licenses).uniq
|
9
|
+
end
|
10
|
+
|
11
|
+
def left
|
12
|
+
elements[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def right
|
16
|
+
elements[1]
|
7
17
|
end
|
8
18
|
end
|
9
19
|
|
10
|
-
class
|
20
|
+
class LogicalAnd < LogicalBinary
|
11
21
|
end
|
12
22
|
|
13
|
-
class
|
23
|
+
class LogicalOr < LogicalBinary
|
14
24
|
end
|
15
25
|
|
16
26
|
class With < Treetop::Runtime::SyntaxNode
|
27
|
+
def licenses
|
28
|
+
license.licenses
|
29
|
+
end
|
30
|
+
|
31
|
+
def license
|
32
|
+
elements[0]
|
33
|
+
end
|
34
|
+
|
35
|
+
def exception
|
36
|
+
elements[1]
|
37
|
+
end
|
17
38
|
end
|
18
39
|
|
19
40
|
class None < Treetop::Runtime::SyntaxNode
|
@@ -30,20 +51,44 @@ module SpdxGrammar
|
|
30
51
|
|
31
52
|
class License < Treetop::Runtime::SyntaxNode
|
32
53
|
def licenses
|
33
|
-
text_value
|
54
|
+
[text_value]
|
34
55
|
end
|
35
56
|
end
|
36
57
|
|
37
|
-
class
|
38
|
-
|
58
|
+
class LicensePlus < Treetop::Runtime::SyntaxNode
|
59
|
+
def licenses
|
60
|
+
child.licenses
|
61
|
+
end
|
62
|
+
|
63
|
+
def child
|
64
|
+
elements[0]
|
65
|
+
end
|
39
66
|
end
|
40
67
|
|
41
|
-
class
|
68
|
+
class LicenseRef < Treetop::Runtime::SyntaxNode
|
42
69
|
def licenses
|
43
|
-
|
70
|
+
[text_value]
|
44
71
|
end
|
45
72
|
end
|
46
73
|
|
74
|
+
class DocumentRef < Treetop::Runtime::SyntaxNode
|
75
|
+
def licenses
|
76
|
+
[text_value]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class LicenseException < Treetop::Runtime::SyntaxNode
|
81
|
+
# TODO: actually do license exceptions
|
82
|
+
end
|
83
|
+
|
84
|
+
class GroupedExpression < Treetop::Runtime::SyntaxNode
|
85
|
+
# Used internally
|
86
|
+
end
|
87
|
+
|
88
|
+
class Operand < Treetop::Runtime::SyntaxNode
|
89
|
+
# Used internally
|
90
|
+
end
|
91
|
+
|
47
92
|
class SpdxParseError < StandardError
|
48
93
|
end
|
49
94
|
end
|