language-ruby 0.6.0 → 0.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdf5e247df3ee0c287a560265c60107d161eb4b7cb71610f6f50c15c81c2e3aa
4
- data.tar.gz: acfe4eea02eb399831fd378adb0bd69100efbdecaeead3c99a2faaec11e552cb
3
+ metadata.gz: f4baad3490a61d7414a3010ae28d7ebe15678cf7155d6fa733d6db38e69a6f15
4
+ data.tar.gz: 498e238afd5c1fdee3eb7d43d6416deda5c4af0a7ea3e7be7b16b3c52f35fc08
5
5
  SHA512:
6
- metadata.gz: 318d1dd9888a5aee6aec7fef5410b9092f169e6e12e1d4a0608c6a2e36b2ae4b3bfc6412052a8e331a9b1260bf4387ccfa6340e1ea74f7511da049ff222d4050
7
- data.tar.gz: 5c0c443194c047a08c461f9b713fcf131ebd12ce479b81d344415202694106a7db00e19547c37319c6d69d4a0bc78a768b0a8aaf1d29e1b9a7ae1369d87c520e
6
+ metadata.gz: b51659b87522dbe212304842b3d8af561e6caf86ce78cef0ed0bfd732123736961736750fe603073398e50150b03d4be328c858754a7d4d2e6bd3926377878da
7
+ data.tar.gz: 740130b9f8e3a5c5e6ac8e09b8adbb5c0bd75074fbc0c94b1bac6a58276bed37b818a82d98e4cfe6953bb3e6f318a222790ddfe6089ffe6c01aae97f4ea605d1
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.0
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.3.0
data/Gemfile CHANGED
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  gemspec
4
6
 
7
+ ruby "3.3.0"
8
+
5
9
  gem "rspec"
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ language-ruby (0.6.2)
5
+ zeitwerk (~> 2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.5.0)
11
+ rspec (3.12.0)
12
+ rspec-core (~> 3.12.0)
13
+ rspec-expectations (~> 3.12.0)
14
+ rspec-mocks (~> 3.12.0)
15
+ rspec-core (3.12.2)
16
+ rspec-support (~> 3.12.0)
17
+ rspec-expectations (3.12.3)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.12.0)
20
+ rspec-mocks (3.12.6)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.12.0)
23
+ rspec-support (3.12.1)
24
+ zeitwerk (2.6.12)
25
+
26
+ PLATFORMS
27
+ arm64-darwin-22
28
+ arm64-darwin-23
29
+
30
+ DEPENDENCIES
31
+ language-ruby!
32
+ rspec
33
+
34
+ RUBY VERSION
35
+ ruby 3.3.0p0
36
+
37
+ BUNDLED WITH
38
+ 2.5.6
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # language-ruby
2
+
3
+ A Parsing Expression Grammar (PEG) for making parsers
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
1
4
  require_relative "lib/language/version"
2
5
 
3
6
  Gem::Specification.new do |s|
@@ -7,10 +10,9 @@ Gem::Specification.new do |s|
7
10
  s.description = s.summary
8
11
  s.authors = ["Dorian Marié"]
9
12
  s.email = "dorian@dorianmarie.fr"
10
- s.files = `git ls-files`.split($/)
11
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
13
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
12
14
  s.require_paths = ["lib"]
13
- s.homepage = "https://github.com/dorianmariefr/language-ruby"
15
+ s.homepage = "https://github.com/dorianmariecom/language-ruby"
14
16
  s.license = "MIT"
15
17
 
16
18
  s.add_dependency "zeitwerk", "~> 2"
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Absent < Atom
6
+ def initialize(parent: nil)
7
+ @parent = parent
8
+ end
9
+
10
+ def parse(parser)
11
+ clone =
12
+ Parser.new(
13
+ root: self,
14
+ input: parser.input,
15
+ cursor: parser.cursor,
16
+ buffer: parser.buffer
17
+ )
18
+ @parent&.parse(clone)
19
+ rescue Parser::Interuption
20
+ else
21
+ raise Parser::Interuption.new(parser, self)
22
+ end
23
+
24
+ def to_s
25
+ @parent ? "(#{@parent}).absent" : "absent"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Aka < Atom
6
+ def initialize(name:, parent:)
7
+ @name = name
8
+ @parent = parent
9
+ end
10
+
11
+ def parse(parser)
12
+ clone =
13
+ Parser.new(root: self, input: parser.input, cursor: parser.cursor)
14
+
15
+ @parent.parse(clone)
16
+
17
+ if clone.output?
18
+ parser.output = Output.new(@name => clone.output)
19
+ else
20
+ parser.output[@name] = Output.new(clone.buffer)
21
+ parser.buffer = ""
22
+ end
23
+
24
+ parser.cursor = clone.cursor
25
+ end
26
+
27
+ def to_s
28
+ @parent ? "#{@parent}.aka(#{@name.inspect})" : "aka(#{@name.inspect})"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class And < Atom
6
+ def initialize(left:, right:)
7
+ @left = left
8
+ @right = right
9
+ end
10
+
11
+ def parse(parser)
12
+ @left.parse(parser)
13
+ right_clone =
14
+ Parser.new(
15
+ root: self,
16
+ input: parser.input,
17
+ cursor: parser.cursor,
18
+ buffer: parser.buffer
19
+ )
20
+ @right.parse(right_clone)
21
+ parser.cursor = right_clone.cursor
22
+ parser.buffer = right_clone.buffer
23
+
24
+ parser.output.merge(right_clone.output)
25
+ end
26
+
27
+ def to_s
28
+ "#{@left} >> #{@right}".to_s
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,6 +3,13 @@
3
3
  class Language
4
4
  class Atom
5
5
  class Any < Atom
6
+ def parse(parser)
7
+ parser.consume(1)
8
+ end
9
+
10
+ def to_s
11
+ "any"
12
+ end
6
13
  end
7
14
  end
8
15
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Ignore < Atom
6
+ def initialize(parent:)
7
+ @parent = parent
8
+ end
9
+
10
+ def parse(parser)
11
+ clone =
12
+ Parser.new(
13
+ root: self,
14
+ input: parser.input,
15
+ cursor: parser.cursor,
16
+ buffer: parser.buffer
17
+ )
18
+ @parent.parse(clone)
19
+ parser.cursor = clone.cursor
20
+ end
21
+
22
+ def to_s
23
+ "#{@parent}.ignore"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Maybe < Atom
6
+ def initialize(parent:)
7
+ @parent = parent
8
+ end
9
+
10
+ def parse(parser)
11
+ clone =
12
+ Parser.new(
13
+ root: self,
14
+ input: parser.input,
15
+ cursor: parser.cursor,
16
+ buffer: parser.buffer
17
+ )
18
+
19
+ @parent.parse(clone)
20
+ rescue Parser::Interuption
21
+ else
22
+ parser.buffer = clone.buffer
23
+ parser.cursor = clone.cursor
24
+ parser.output = clone.output
25
+ end
26
+
27
+ def to_s
28
+ @parent ? "#{@parent}.maybe" : "maybe"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Or < Atom
6
+ def initialize(left:, right:)
7
+ @left = left
8
+ @right = right
9
+ end
10
+
11
+ def parse(parser)
12
+ left_clone =
13
+ Parser.new(
14
+ root: self,
15
+ input: parser.input,
16
+ cursor: parser.cursor,
17
+ buffer: parser.buffer
18
+ )
19
+
20
+ right_clone =
21
+ Parser.new(
22
+ root: self,
23
+ input: parser.input,
24
+ cursor: parser.cursor,
25
+ buffer: parser.buffer
26
+ )
27
+
28
+ begin
29
+ @left.parse(left_clone)
30
+ parser.cursor = left_clone.cursor
31
+ parser.buffer = left_clone.buffer
32
+ parser.output.merge(left_clone.output)
33
+ rescue Parser::Interuption
34
+ @right.parse(right_clone)
35
+ parser.cursor = right_clone.cursor
36
+ parser.buffer = right_clone.buffer
37
+ parser.output.merge(right_clone.output)
38
+ end
39
+ end
40
+
41
+ def to_s
42
+ "((#{@left}) | (#{@right}))"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -3,13 +3,55 @@
3
3
  class Language
4
4
  class Atom
5
5
  class Repeat < Atom
6
- def initialize(parent:)
6
+ def initialize(parent: nil, minimum: 0, maximum: nil)
7
7
  @parent = parent
8
+ @minimum = minimum
9
+ @maximum = maximum
10
+ end
11
+
12
+ def parse(parser)
13
+ return unless @parent
14
+
15
+ @minimum.times { match(parser) }
16
+ if @maximum.nil?
17
+ begin
18
+ loop { match(parser) }
19
+ rescue Parser::Interuption
20
+ end
21
+ else
22
+ begin
23
+ (@maximum - @minimum).times { match(parser) }
24
+ rescue Parser::Interuption
25
+ end
26
+ end
27
+ end
28
+
29
+ def to_s
30
+ minimum = @minimum.zero? ? "" : @minimum.to_s
31
+ maximum = @maximum.nil? ? "" : ", #{@maximum}"
32
+ parenthesis =
33
+ (minimum.empty? && maximum.empty?) ? "" : "(#{minimum}#{maximum})"
34
+
35
+ @parent ? "(#{@parent}).repeat#{parenthesis}" : "repeat#{parenthesis}"
8
36
  end
9
37
 
10
38
  private
11
39
 
12
- attr_reader :parent
40
+ def match(parser)
41
+ clone =
42
+ Parser.new(
43
+ root: self,
44
+ input: parser.input,
45
+ cursor: parser.cursor,
46
+ buffer: parser.buffer
47
+ )
48
+
49
+ @parent.parse(clone)
50
+
51
+ parser.cursor = clone.cursor
52
+ parser.buffer = clone.buffer
53
+ parser.output << clone.output
54
+ end
13
55
  end
14
56
  end
15
57
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Str < Atom
6
+ def initialize(string:)
7
+ @string = string
8
+ end
9
+
10
+ def parse(parser)
11
+ unless parser.next?(@string)
12
+ raise Parser::Str::NotFound.new(parser, @string)
13
+ end
14
+
15
+ parser.consume(@string.size)
16
+ end
17
+
18
+ def to_s
19
+ "str(#{@string.inspect})"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Language
4
+ class Atom
5
+ class Then < Atom
6
+ def initialize(parent:, block:)
7
+ @parent = parent
8
+ @block = block
9
+ end
10
+
11
+ def parse(parser)
12
+ @parent.parse(parser)
13
+ parser.output = Output.from_raw(@block.call(parser.output.to_raw))
14
+ end
15
+
16
+ def to_s
17
+ "(#{@parent}).then {}"
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/language/atom.rb CHANGED
@@ -2,270 +2,6 @@
2
2
 
3
3
  class Language
4
4
  class Atom
5
- class Any < Atom
6
- def parse(parser)
7
- parser.consume(1)
8
- end
9
-
10
- def to_s
11
- "any"
12
- end
13
- end
14
-
15
- class Then < Atom
16
- def initialize(parent:, block:)
17
- @parent = parent
18
- @block = block
19
- end
20
-
21
- def parse(parser)
22
- @parent.parse(parser)
23
- parser.output = Output.from_raw(@block.call(parser.output.to_raw))
24
- end
25
-
26
- def to_s
27
- "(#{@parent}).then {}"
28
- end
29
- end
30
-
31
- class Repeat < Atom
32
- def initialize(parent: nil, minimum: 0, maximum: nil)
33
- @parent = parent
34
- @minimum = minimum
35
- @maximum = maximum
36
- end
37
-
38
- def parse(parser)
39
- return unless @parent
40
-
41
- @minimum.times { match(parser) }
42
- if @maximum.nil?
43
- begin
44
- loop { match(parser) }
45
- rescue Parser::Interuption
46
- end
47
- else
48
- begin
49
- (@maximum - @minimum).times { match(parser) }
50
- rescue Parser::Interuption
51
- end
52
- end
53
- end
54
-
55
- def to_s
56
- minimum = @minimum.zero? ? "" : @minimum.to_s
57
- maximum = @maximum.nil? ? "" : ", #{@maximum}"
58
- parenthesis =
59
- minimum.empty? && maximum.empty? ? "" : "(#{minimum}#{maximum})"
60
-
61
- @parent ? "(#{@parent}).repeat#{parenthesis}" : "repeat#{parenthesis}"
62
- end
63
-
64
- private
65
-
66
- def match(parser)
67
- clone =
68
- Parser.new(
69
- root: self,
70
- input: parser.input,
71
- cursor: parser.cursor,
72
- buffer: parser.buffer
73
- )
74
-
75
- @parent.parse(clone)
76
-
77
- parser.cursor = clone.cursor
78
- parser.buffer = clone.buffer
79
- parser.output << clone.output
80
- end
81
- end
82
-
83
- class Str < Atom
84
- def initialize(string:)
85
- @string = string
86
- end
87
-
88
- def parse(parser)
89
- unless parser.next?(@string)
90
- raise Parser::Str::NotFound.new(parser, @string)
91
- end
92
-
93
- parser.consume(@string.size)
94
- end
95
-
96
- def to_s
97
- "str(#{@string.inspect})"
98
- end
99
- end
100
-
101
- class Absent < Atom
102
- def initialize(parent: nil)
103
- @parent = parent
104
- end
105
-
106
- def parse(parser)
107
- clone =
108
- Parser.new(
109
- root: self,
110
- input: parser.input,
111
- cursor: parser.cursor,
112
- buffer: parser.buffer
113
- )
114
- @parent&.parse(clone)
115
- rescue Parser::Interuption
116
- else
117
- raise Parser::Interuption.new(parser, self)
118
- end
119
-
120
- def to_s
121
- @parent ? "(#{@parent}).absent" : "absent"
122
- end
123
- end
124
-
125
- class Ignore < Atom
126
- def initialize(parent: nil)
127
- @parent = parent
128
- end
129
-
130
- def parse(parser)
131
- clone =
132
- Parser.new(
133
- root: self,
134
- input: parser.input,
135
- cursor: parser.cursor,
136
- buffer: parser.buffer
137
- )
138
- @parent&.parse(clone)
139
- parser.cursor = clone.cursor
140
- end
141
-
142
- def to_s
143
- @parent ? "#{@parent}.ignore" : "ignore"
144
- end
145
- end
146
-
147
- class Maybe < Atom
148
- def initialize(parent:)
149
- @parent = parent
150
- end
151
-
152
- def parse(parser)
153
- clone =
154
- Parser.new(
155
- root: self,
156
- input: parser.input,
157
- cursor: parser.cursor,
158
- buffer: parser.buffer
159
- )
160
-
161
- @parent.parse(clone)
162
- rescue Parser::Interuption
163
- else
164
- parser.buffer = clone.buffer
165
- parser.cursor = clone.cursor
166
- parser.output = clone.output
167
- end
168
-
169
- def to_s
170
- @parent ? "#{@parent}.maybe" : "maybe"
171
- end
172
- end
173
-
174
- class Aka < Atom
175
- def initialize(name:, parent:)
176
- @name = name
177
- @parent = parent
178
- end
179
-
180
- def parse(parser)
181
- clone =
182
- Parser.new(root: self, input: parser.input, cursor: parser.cursor)
183
-
184
- @parent.parse(clone)
185
-
186
- if clone.output?
187
- parser.output = Output.new(@name => clone.output)
188
- else
189
- parser.output[@name] = Output.new(clone.buffer)
190
- parser.buffer = ""
191
- end
192
-
193
- parser.cursor = clone.cursor
194
- end
195
-
196
- def to_s
197
- @parent ? "#{@parent}.aka(#{@name.inspect})" : "aka(#{@name.inspect})"
198
- end
199
- end
200
-
201
- class Or < Atom
202
- def initialize(left:, right:)
203
- @left = left
204
- @right = right
205
- end
206
-
207
- def parse(parser)
208
- left_clone =
209
- Parser.new(
210
- root: self,
211
- input: parser.input,
212
- cursor: parser.cursor,
213
- buffer: parser.buffer
214
- )
215
-
216
- right_clone =
217
- Parser.new(
218
- root: self,
219
- input: parser.input,
220
- cursor: parser.cursor,
221
- buffer: parser.buffer
222
- )
223
-
224
- begin
225
- @left.parse(left_clone)
226
- parser.cursor = left_clone.cursor
227
- parser.buffer = left_clone.buffer
228
- parser.output.merge(left_clone.output)
229
- rescue Parser::Interuption
230
- @right.parse(right_clone)
231
- parser.cursor = right_clone.cursor
232
- parser.buffer = right_clone.buffer
233
- parser.output.merge(right_clone.output)
234
- end
235
- end
236
-
237
- def to_s
238
- "((#{@left}) | (#{@right}))"
239
- end
240
- end
241
-
242
- class And < Atom
243
- def initialize(left:, right:)
244
- @left = left
245
- @right = right
246
- end
247
-
248
- def parse(parser)
249
- @left.parse(parser)
250
- right_clone =
251
- Parser.new(
252
- root: self,
253
- input: parser.input,
254
- cursor: parser.cursor,
255
- buffer: parser.buffer
256
- )
257
- @right.parse(right_clone)
258
- parser.cursor = right_clone.cursor
259
- parser.buffer = right_clone.buffer
260
-
261
- parser.output.merge(right_clone.output)
262
- end
263
-
264
- def to_s
265
- "#{@left} >> #{@right}".to_s
266
- end
267
- end
268
-
269
5
  def any
270
6
  Any.new
271
7
  end
@@ -315,7 +51,7 @@ class Language
315
51
  end
316
52
 
317
53
  def to_s
318
- ""
54
+ raise NotImplementedError, "#{self.class}#parse"
319
55
  end
320
56
 
321
57
  def inspect
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../language"
2
4
 
3
- Language::Version = Gem::Version.new("0.6.0")
5
+ Language::Version = Gem::Version.new("0.6.2")
data/lib/language-ruby.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "zeitwerk"
2
4
 
3
5
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ class Parser
5
+ class Nothing < Language
6
+ def nothing_keyword
7
+ str("nothing")
8
+ end
9
+
10
+ def root
11
+ nothing_keyword.aka(:nothing)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ RSpec.describe Language do
18
+ it "works" do
19
+ expect(Code::Parser::Nothing.parse("nothing")).to eq({ nothing: "nothing" })
20
+ end
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../lib/language-ruby"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: language-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-10 00:00:00.000000000 Z
11
+ date: 2024-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -30,13 +30,27 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
+ - ".gitignore"
34
+ - ".rspec"
35
+ - ".ruby-version"
36
+ - ".tool-versions"
33
37
  - Gemfile
38
+ - Gemfile.lock
39
+ - README.md
34
40
  - language-ruby.gemspec
35
41
  - lib/language-ruby.rb
36
42
  - lib/language.rb
37
43
  - lib/language/atom.rb
44
+ - lib/language/atom/absent.rb
45
+ - lib/language/atom/aka.rb
46
+ - lib/language/atom/and.rb
38
47
  - lib/language/atom/any.rb
48
+ - lib/language/atom/ignore.rb
49
+ - lib/language/atom/maybe.rb
50
+ - lib/language/atom/or.rb
39
51
  - lib/language/atom/repeat.rb
52
+ - lib/language/atom/str.rb
53
+ - lib/language/atom/then.rb
40
54
  - lib/language/output.rb
41
55
  - lib/language/parser.rb
42
56
  - lib/language/parser/absent.rb
@@ -47,8 +61,9 @@ files:
47
61
  - lib/language/parser/str.rb
48
62
  - lib/language/parser/str/not_found.rb
49
63
  - lib/language/version.rb
64
+ - spec/language_spec.rb
50
65
  - spec/spec_helper.rb
51
- homepage: https://github.com/dorianmariefr/language-ruby
66
+ homepage: https://github.com/dorianmariecom/language-ruby
52
67
  licenses:
53
68
  - MIT
54
69
  metadata: {}
@@ -67,9 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
82
  - !ruby/object:Gem::Version
68
83
  version: '0'
69
84
  requirements: []
70
- rubygems_version: 3.4.14
85
+ rubygems_version: 3.5.3
71
86
  signing_key:
72
87
  specification_version: 4
73
88
  summary: A Parsing Expression Grammar (PEG) for making parsers
74
- test_files:
75
- - spec/spec_helper.rb
89
+ test_files: []