tcepsni 0.2.0 → 0.3.1

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: 3695b6a1a12979fa76824819d4f839ce4e3b9a2af040f97eca9e474609c5c1f2
4
- data.tar.gz: 373da53b2e230d3510f2043f25b8ae7cf017fae689fdfbaa92a388be4155ebcd
3
+ metadata.gz: 40d96c10a7e7729b0c37648bedd7b693dff04602d9bc3ef9794e695d48986864
4
+ data.tar.gz: f6316e6ceba71e2a7cee7d99140357a08e52c598e31324016159d301ffb791e5
5
5
  SHA512:
6
- metadata.gz: f646aecf1094e4e171581b52ca0e48dccddc4464bf158f4c30b93e8df7ef7b8989b240e9c61abf25a7cb65c2c9a29ec6978529f627a1c360f0fede299624d297
7
- data.tar.gz: 573e5e82c5c7a0b476ee93255fe6b6fc7992febcee911e54ee1b852c9acacca29950bc67183ec01cbed7c3cf3cfcce3edd21137f1c04400bff42959d6f1d72c8
6
+ metadata.gz: e3235426ddaeed30dd132dfc2f904259abe5da867aa4e17aa683d43d42112d8ded52575e4cb3e218c39fcc0f4f1a84175594279f5e07e221da08a5d03afe79f7
7
+ data.tar.gz: 3e79b0c3e3f29d5044cdc7051e980db49d1a49fd54a7fa8299386056f38864887fe04238319177d5fa9f0bbe4bd07c773a9c4fe279b2875b80fdf7e9f5bcbac8
data/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.1 - 2024-07-21
6
+
7
+ Update gemspec fields etc.
8
+ There should be no API changes.
9
+
10
+ ## 0.3.0 - 2023-11-18
11
+
12
+ ### Changed
13
+
14
+ - Introduced plugin system.
15
+ For example, if the source contains `Pathname` objects, use the `vendors` option like `Tcepsni.parse(str, vendors: [::Tcepsni::Vendor::Pathname])`.
16
+
17
+ ### Removed
18
+
19
+ - `Tcepsni::Class#string_scanner?`, `Tcepsni::Class#pathname?`, `Tcepsni::Class#ipaddr?`, `Tcepsni::Class#active_support_ordered_options?`, and `Tcepsni::Class#rails_paths_root?`.
20
+
5
21
  ## 0.2.0 - 2023-10-20
6
22
 
7
23
  ### Added
data/README.md CHANGED
@@ -15,7 +15,7 @@ Tcepsni has a parsing method `Tcepsni.parse(str)`, which returns a parsed Ruby o
15
15
  ## Development
16
16
 
17
17
  After checking out the repo, run `bin/setup` to install dependencies.
18
- Then, run `rake test-unit` to run the tests.
18
+ Then, run `rake test` to run the tests.
19
19
  You can also run `bin/console` for an interactive prompt that will allow you to experiment.
20
20
 
21
21
  To install this gem onto your local machine, run `bundle exec rake install`.
@@ -27,7 +27,7 @@ Bug reports and pull requests are welcome.
27
27
 
28
28
  ## License
29
29
 
30
- Copyright 2023 gemmaro.
30
+ Copyright 2023, 2024 gemmaro.
31
31
 
32
32
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
33
33
  You may obtain a copy of the License at [Apache Software Foundation - Apache License, Version 2.0][asl].
@@ -0,0 +1,165 @@
1
+ require 'strscan'
2
+ require 'forwardable'
3
+
4
+ module Tcepsni
5
+ class Parser
6
+ def initialize(source, vendors:)
7
+ @scanner = ::StringScanner.new(source)
8
+ @vendors = vendors.flat_map { |vendor| [*vendor.dependencies, vendor] }.uniq
9
+ end
10
+
11
+ # If it returned nil when failed, it collides with normal nil value.
12
+ def parse_expression
13
+ if @scanner.skip(/nil\b/)
14
+ nil
15
+ elsif @scanner.skip(/true\b/)
16
+ true
17
+ elsif @scanner.skip(/false\b/)
18
+ false
19
+ elsif @scanner.skip(':')
20
+ parse_identifier
21
+ elsif @scanner.skip('"')
22
+ parse_string
23
+ elsif @scanner.skip('[')
24
+ parse_array
25
+ elsif @scanner.skip('{')
26
+ parse_hash
27
+ elsif @scanner.skip('#<')
28
+ pos = @scanner.pos
29
+ @vendors.select { |vendor| vendor.object? }.each do |vendor|
30
+ @scanner.pos = pos
31
+ return vendor.parse(self)
32
+ rescue Error
33
+ next
34
+ end
35
+ @scanner.pos = pos
36
+ parse_object
37
+ elsif (digits = @scanner.scan(/\d+/))
38
+ int = Integer(digits)
39
+ if @scanner.skip('.')
40
+ int2 = parse_integer
41
+ Float("#{int}.#{int2}")
42
+ elsif digits.size == 4 && @scanner.skip(/-(?<month>[01]\d)-(?<day>\d\d) (?<hour>[012]\d):(?<minute>[0-5]\d):(?<second>[0-5]\d) (?<zone>[+-]\d\d\d\d)/)
43
+ Time.new(Integer(int), @scanner[:month], @scanner[:day],
44
+ @scanner[:hour], @scanner[:minute], @scanner[:second],
45
+ @scanner[:zone])
46
+ else
47
+ int
48
+ end
49
+ else
50
+ parse_class
51
+ end
52
+ end
53
+
54
+ alias parse parse_expression
55
+
56
+ def parse_integer
57
+ int = @scanner.scan(/\d+/) or raise Error, 'no digits'
58
+ Integer(int)
59
+ end
60
+
61
+ def parse_identifier
62
+ id = @scanner.scan(/[A-Za-z_][A-Za-z0-9_]*/) or raise Error, 'no identifier'
63
+ id.intern
64
+ end
65
+
66
+ def parse_string
67
+ result = ''
68
+ until @scanner.eos?
69
+ if @scanner.skip('"')
70
+ return result
71
+ elsif @scanner.skip('\\"')
72
+ result << '"'
73
+ else
74
+ result << @scanner.getch
75
+ end
76
+ end
77
+ result
78
+ end
79
+
80
+ def parse_array
81
+ result = []
82
+ until @scanner.eos?
83
+ begin
84
+ result << parse_expression
85
+ rescue StandardError
86
+ break
87
+ end
88
+ @scanner.skip(', ') or break
89
+ end
90
+ @scanner.skip(']') or raise Error, "no array closer: #{@scanner.inspect}"
91
+ result
92
+ end
93
+
94
+ def parse_hash
95
+ result = {}
96
+ until @scanner.eos?
97
+ key = begin
98
+ parse_expression
99
+ rescue StandardError
100
+ break
101
+ end
102
+ @scanner.skip('=>') or raise Error, 'no hash arrow'
103
+ value = parse_expression
104
+ result[key] = value
105
+ @scanner.skip(', ') or break
106
+ end
107
+ @scanner.skip('}') or raise Error, 'no hash closer'
108
+ result
109
+ end
110
+
111
+ def parse_class
112
+ namespaces = [parse_capitalized_identifier]
113
+ until @scanner.eos?
114
+ @scanner.skip('::') or break
115
+ @scanner.eos? and raise Error, 'incomplete class'
116
+ namespaces << parse_capitalized_identifier
117
+ end
118
+ *namespaces, name = namespaces
119
+ Tcepsni::Class.new(name:, namespaces:)
120
+ end
121
+
122
+ def parse_capitalized_identifier
123
+ id = @scanner.scan(/[A-Z][A-Za-z0-9_]*/) or raise Error, "no capitalized identifier: #{@scanner.inspect}"
124
+ id.intern
125
+ end
126
+
127
+ def parse_object
128
+ klass = parse_class
129
+ if klass.encoding?
130
+ @scanner.skip(':') or raise Error, 'no colon separator in encoding object'
131
+ @scanner.skip(/(?<name>[^>]+)>/) or raise Error, 'invalid encoding name'
132
+ Encoding.find(@scanner[:name])
133
+ else
134
+ memory_reference = parse_memory_reference
135
+ attributes = parse_attributes
136
+ Tcepsni::Object.new(klass:, memory_reference:, attributes:)
137
+ end
138
+ end
139
+
140
+ def parse_attributes
141
+ attributes = {}
142
+ unless @scanner.skip('>')
143
+ until @scanner.eos?
144
+ @scanner.skip(' @') or break
145
+ key = parse_identifier
146
+ @scanner.skip('=') or raise Error, 'no attribute keyval equal char'
147
+ attributes[key.intern] = parse_expression
148
+ unless @scanner.skip(',')
149
+ @scanner.skip('>') or raise Error, "no object closer: #{@scanner.inspect}"
150
+ break
151
+ end
152
+ end
153
+ end
154
+ attributes
155
+ end
156
+
157
+ def parse_memory_reference
158
+ @scanner.skip(/:(?<memory_reference>0x[0-9a-f]{16})/) or raise Error, "no memory reference: #{@scanner.inspect}"
159
+ Integer(@scanner[:memory_reference])
160
+ end
161
+
162
+ extend Forwardable
163
+ def_delegators :@scanner, :skip, :[]
164
+ end
165
+ end
@@ -0,0 +1,28 @@
1
+ require 'active_support/ordered_options'
2
+
3
+ module Tcepsni
4
+ module Vendor
5
+ module ActiveSupport
6
+ class OrderedOptions
7
+ def self.parse(parser)
8
+ parser.skip('ActiveSupport::OrderedOptions {') or raise Error, 'no space between ActiveSupport::OrderedOptions class name and hash opener'
9
+ hash = parser.parse_hash
10
+ parser.skip('>') or raise Error, "no ActiveSupport ordered options closer: #{parser.scanner.inspect}"
11
+ options = ::ActiveSupport::OrderedOptions.new
12
+ hash.each do |key, val|
13
+ options[key] = val
14
+ end
15
+ options
16
+ end
17
+
18
+ def self.dependencies
19
+ []
20
+ end
21
+
22
+ def self.object?
23
+ true
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ require 'ipaddr'
2
+
3
+ module Tcepsni
4
+ module Vendor
5
+ class IPAddr
6
+ def self.parse(parser)
7
+ parser.skip(/IPAddr: IPv[46]:(?<addr>[^>]+)>/) or raise Error, 'invalid IP address format error'
8
+ ::IPAddr.new(parser[:addr])
9
+ end
10
+
11
+ def self.object?
12
+ true
13
+ end
14
+
15
+ def self.dependencies
16
+ []
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ require 'pathname'
2
+
3
+ module Tcepsni
4
+ module Vendor
5
+ class Pathname
6
+ def self.parse(parser)
7
+ parser.skip('Pathname:') or raise Error, 'no colon between Pathname class name and path string'
8
+ parser.skip(/(?<path>[^>]+)>/) or raise Error, 'invalid path string and closer'
9
+ ::Pathname.new(parser[:path])
10
+ end
11
+
12
+ def self.object?
13
+ true
14
+ end
15
+
16
+ def self.dependencies
17
+ []
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ require 'rails/paths'
2
+
3
+ module Tcepsni
4
+ module Vendor
5
+ module Rails
6
+ module Paths
7
+ class Root
8
+ attr_reader :memory_reference, :attributes
9
+
10
+ def initialize(memory_reference, attributes)
11
+ @memory_reference = memory_reference
12
+ @attributes = attributes
13
+ end
14
+
15
+ def self.parse(parser)
16
+ parser.skip('Rails::Paths::Root') or raise Error, 'this is not Rails::Paths::Root'
17
+ memory_reference = parser.parse_memory_reference
18
+ attributes = if parser.skip(' ...>')
19
+ {}
20
+ else
21
+ parser.parse_attributes
22
+ end
23
+ Tcepsni::Vendor::Rails::Paths::Root.new(memory_reference, attributes)
24
+ end
25
+
26
+ def self.object?
27
+ true
28
+ end
29
+
30
+ def self.dependencies
31
+ [::Tcepsni::Vendor::Pathname]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ module Tcepsni
2
+ module Vendor
3
+ class StringScanner
4
+ attr_reader :pos, :total, :scanned, :rest
5
+
6
+ def initialize(pos:, total:, scanned:, rest:)
7
+ @pos = pos
8
+ @total = total
9
+ @scanned = scanned
10
+ @rest = rest
11
+ end
12
+
13
+ def self.parse(parser)
14
+ parser.skip('StringScanner ') or raise Error, 'no space after string scanner class name'
15
+ pos = parser.parse_integer
16
+ parser.skip('/') or raise Error, 'no string scanner progress delimiter slash'
17
+ total = parser.parse_integer
18
+ parser.skip(' "') or raise Error, 'no space after string scanner progress'
19
+ scanned = parser.parse_string
20
+ parser.skip(' @ "') or raise Error, "no string scanner mark in string: #{parser.scanner.inspect}"
21
+ rest = parser.parse_string
22
+ parser.skip('>') or raise Error, 'no string scanner closer'
23
+ Tcepsni::Vendor::StringScanner.new(pos:, total:, scanned:, rest:)
24
+ end
25
+
26
+ def self.dependencies
27
+ []
28
+ end
29
+
30
+ def self.object?
31
+ true
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module Tcepsni
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.1'
3
3
  end
data/lib/tcepsni.rb CHANGED
@@ -1,190 +1,11 @@
1
- require 'strscan'
2
- require 'pathname'
3
- require 'ipaddr'
4
- require 'active_support/ordered_options'
5
- require 'rails/paths'
6
1
  require_relative 'tcepsni/version'
2
+ require_relative 'tcepsni/parser'
7
3
 
8
4
  module Tcepsni
9
- class Error < StandardError; end
5
+ Error = Class.new(StandardError)
10
6
 
11
- def self.parse(str)
12
- scanner = ::StringScanner.new(str)
13
- parse_expression(scanner)
14
- end
15
-
16
- class << self
17
- private
18
-
19
- # If it returned nil when failed, it collides with normal nil value.
20
- def parse_expression(scanner)
21
- if scanner.skip(/nil\b/)
22
- nil
23
- elsif scanner.skip(/true\b/)
24
- true
25
- elsif scanner.skip(/false\b/)
26
- false
27
- elsif scanner.skip(':')
28
- parse_identifier(scanner)
29
- elsif scanner.skip('"')
30
- parse_string(scanner)
31
- elsif scanner.skip('[')
32
- parse_array(scanner)
33
- elsif scanner.skip('{')
34
- parse_hash(scanner)
35
- elsif scanner.skip('#<')
36
- parse_object(scanner)
37
- else
38
- if (digits = scanner.scan(/\d+/))
39
- int = Integer(digits)
40
- if scanner.skip('.')
41
- int2 = parse_integer(scanner)
42
- Float("#{int}.#{int2}")
43
- elsif digits.size == 4 && scanner.skip(/-(?<month>[01]\d)-(?<day>\d\d) (?<hour>[012]\d):(?<minute>[0-5]\d):(?<second>[0-5]\d) (?<zone>[+-]\d\d\d\d)/)
44
- Time.new(Integer(int), scanner[:month], scanner[:day],
45
- scanner[:hour], scanner[:minute], scanner[:second],
46
- scanner[:zone])
47
- else
48
- int
49
- end
50
- else
51
- parse_class(scanner)
52
- end
53
- end
54
- end
55
-
56
- def parse_integer(scanner)
57
- int = scanner.scan(/\d+/) or raise Error, 'no digits'
58
- Integer(int)
59
- end
60
-
61
- def parse_identifier(scanner)
62
- id = scanner.scan(/[A-Za-z_][A-Za-z0-9_]*/) or raise Error, 'no identifier'
63
- id.intern
64
- end
65
-
66
- def parse_string(scanner)
67
- result = ''
68
- until scanner.eos?
69
- if scanner.skip('"')
70
- return result
71
- elsif scanner.skip('\\"')
72
- result << '"'
73
- else
74
- result << scanner.getch
75
- end
76
- end
77
- result
78
- end
79
-
80
- def parse_array(scanner)
81
- result = []
82
- until scanner.eos?
83
- result << parse_expression(scanner) rescue break
84
- scanner.skip(', ') or break
85
- end
86
- scanner.skip(']') or raise Error, "no array closer: #{scanner.inspect}"
87
- result
88
- end
89
-
90
- def parse_hash(scanner)
91
- result = {}
92
- until scanner.eos?
93
- key = parse_expression(scanner) rescue break
94
- scanner.skip('=>') or raise Error, 'no hash arrow'
95
- value = parse_expression(scanner)
96
- result[key] = value
97
- scanner.skip(', ') or break
98
- end
99
- scanner.skip('}') or raise Error, 'no hash closer'
100
- result
101
- end
102
-
103
- def parse_class(scanner)
104
- namespaces = [parse_capitalized_identifier(scanner)]
105
- until scanner.eos?
106
- scanner.skip('::') or break
107
- scanner.eos? and raise Error, 'incomplete class'
108
- namespaces << parse_capitalized_identifier(scanner)
109
- end
110
- *namespaces, name = namespaces
111
- Tcepsni::Class.new(name: name, namespaces: namespaces)
112
- end
113
-
114
- def parse_capitalized_identifier(scanner)
115
- id = scanner.scan(/[A-Z][A-Za-z0-9_]*/) or raise Error, "no capitalized identifier: #{scanner.inspect}"
116
- id.intern
117
- end
118
-
119
- def parse_object(scanner)
120
- klass = parse_class(scanner)
121
- if klass.string_scanner?
122
- scanner.skip(' ') or raise Error, 'no space after string scanner class name'
123
- pos = parse_integer(scanner)
124
- scanner.skip('/') or raise Error, 'no string scanner progress delimiter slash'
125
- total = parse_integer(scanner)
126
- scanner.skip(' "') or raise Error, 'no space after string scanner progress'
127
- scanned = parse_string(scanner)
128
- scanner.skip(' @ "') or raise Error, "no string scanner mark in string: #{scanner.inspect}"
129
- rest = parse_string(scanner)
130
- scanner.skip('>') or raise Error, 'no string scanner closer'
131
- Tcepsni::Vendor::StringScanner.new(pos: pos, total: total, scanned: scanned, rest: rest)
132
- elsif klass.pathname?
133
- scanner.skip(':') or raise Error, 'no colon between Pathname class name and path string'
134
- scanner.skip(/(?<path>[^>]+)>/) or raise Error, 'invalid path string and closer'
135
- Pathname(scanner[:path])
136
- elsif klass.encoding?
137
- scanner.skip(':') or raise Error, 'no colon separator in encoding object'
138
- scanner.skip(/(?<name>[^>]+)>/) or raise Error, 'invalid encoding name'
139
- Encoding.find(scanner[:name])
140
- elsif klass.ipaddr?
141
- scanner.skip(/: IPv[46]:(?<addr>[^>]+)>/) or raise Error, 'invalid IP address format error'
142
- IPAddr.new(scanner[:addr])
143
- elsif klass.active_support_ordered_options?
144
- scanner.skip(' {') or raise Error, 'no space between ActiveSupport::OrderedOptions class name and hash opener'
145
- hash = parse_hash(scanner)
146
- scanner.skip('>') or raise Error, "no ActiveSupport ordered options closer: #{scanner.inspect}"
147
- options = ActiveSupport::OrderedOptions.new
148
- hash.each do |key, val|
149
- options[key] = val
150
- end
151
- options
152
- elsif klass.rails_paths_root?
153
- memory_reference = parse_memory_reference(scanner)
154
- if scanner.skip(' ...>')
155
- attributes = {}
156
- else
157
- attributes = parse_attributes(scanner)
158
- end
159
- Tcepsni::Vendor::Rails::Paths::Root.new(memory_reference, attributes)
160
- else
161
- memory_reference = parse_memory_reference(scanner)
162
- attributes = parse_attributes(scanner)
163
- Tcepsni::Object.new(klass: klass, memory_reference: memory_reference, attributes: attributes)
164
- end
165
- end
166
-
167
- def parse_attributes(scanner)
168
- attributes = {}
169
- unless scanner.skip('>')
170
- until scanner.eos?
171
- scanner.skip(' @') or break
172
- key = parse_identifier(scanner)
173
- scanner.skip('=') or raise Error, 'no attribute keyval equal char'
174
- attributes[key.intern] = parse_expression(scanner)
175
- unless scanner.skip(',')
176
- scanner.skip('>') or raise Error, "no object closer: #{scanner.inspect}"
177
- break
178
- end
179
- end
180
- end
181
- attributes
182
- end
183
-
184
- def parse_memory_reference(scanner)
185
- scanner.skip(/:(?<memory_reference>0x[0-9a-f]{16})/) or raise Error, "no memory reference: #{scanner.inspect}"
186
- Integer(scanner[:memory_reference])
187
- end
7
+ def self.parse(str, vendors: [])
8
+ Parser.new(str, vendors:).parse
188
9
  end
189
10
 
190
11
  class Class
@@ -195,29 +16,9 @@ module Tcepsni
195
16
  @namespaces = namespaces
196
17
  end
197
18
 
198
- def string_scanner?
199
- @name == :StringScanner && @namespaces.empty?
200
- end
201
-
202
- def pathname?
203
- @name == :Pathname
204
- end
205
-
206
19
  def encoding?
207
20
  @name == :Encoding && @namespaces.empty?
208
21
  end
209
-
210
- def ipaddr?
211
- @name == :IPAddr && @namespaces.empty?
212
- end
213
-
214
- def active_support_ordered_options?
215
- @name == :OrderedOptions && @namespaces == [:ActiveSupport]
216
- end
217
-
218
- def rails_paths_root?
219
- @name == :Root && @namespaces == [:Rails, :Paths]
220
- end
221
22
  end
222
23
 
223
24
  class Object
@@ -229,30 +30,4 @@ module Tcepsni
229
30
  @memory_reference = memory_reference
230
31
  end
231
32
  end
232
-
233
- module Vendor
234
- class StringScanner
235
- attr_reader :pos, :total, :scanned, :rest
236
-
237
- def initialize(pos:, total:, scanned:, rest:)
238
- @pos = pos
239
- @total = total
240
- @scanned = scanned
241
- @rest = rest
242
- end
243
- end
244
-
245
- module Rails
246
- module Paths
247
- class Root
248
- attr_reader :memory_reference, :attributes
249
-
250
- def initialize(memory_reference, attributes)
251
- @memory_reference = memory_reference
252
- @attributes = attributes
253
- end
254
- end
255
- end
256
- end
257
- end
258
33
  end
data/sig/tcepsni.gen.rbs CHANGED
@@ -4,18 +4,27 @@
4
4
  module Tcepsni
5
5
  VERSION: String
6
6
 
7
- # def self.parse: (String str) -> parsed
8
- def self.parse_expression: (untyped scanner) -> ((Array[(Array[(Class | Float | Integer | Object | String | Time | bool)?] | Hash[Object?, Object?] | Object)?] | Hash[Object?, (Array[Object?] | Hash[Object?, Object?] | Object)?] | Object)?)
9
- def self.parse_integer: (untyped scanner) -> Integer
10
- def self.parse_identifier: (untyped scanner) -> untyped
11
- def self.parse_string: (untyped scanner) -> String
12
- def self.parse_array: (untyped scanner) -> (Array[(Array[(Array[untyped] | Class | Float | Hash[(Class | Float | Integer | Object | String | Time | bool)?, untyped] | Integer | Object | String | Time | bool)?] | Hash[Object?, (Array[untyped] | Hash[Object?, untyped] | Object)?] | Object)?])
13
- def self.parse_hash: (untyped scanner) -> (Hash[Object?, (Array[(Array[untyped] | Hash[Object?, untyped] | Object)?] | Hash[Object?, (Array[untyped] | Hash[Object?, untyped] | Object)?] | Object)?])
14
- def self.parse_class: (untyped scanner) -> Class
15
- def self.parse_capitalized_identifier: (untyped scanner) -> untyped
16
- def self.parse_object: (untyped scanner) -> (Encoding | IPAddr | Object | Pathname | Vendor::Rails::Paths::Root | Vendor::StringScanner)
17
- def self.parse_attributes: (untyped scanner) -> (Hash[untyped, (Array[(Array[untyped] | Hash[Object?, untyped] | Object)?] | Hash[Object?, (Array[untyped] | Hash[Object?, untyped] | Object)?] | Object)?])
18
- def self.parse_memory_reference: (untyped scanner) -> Integer
7
+ # def self.parse: (String str) -> untyped
8
+
9
+ class Parser
10
+ extend Forwardable
11
+ @scanner: StringScanner
12
+ @vendors: Array[Array[untyped]]
13
+
14
+ # def initialize: (String source, vendors: Array[untyped]?) -> void
15
+ # def parse_expression: -> untyped
16
+ alias parse parse_expression
17
+ # def parse_integer: -> Integer
18
+ # def parse_identifier: -> Symbol
19
+ # def parse_string: -> String
20
+ # def parse_array: -> Array[untyped]
21
+ # def parse_hash: -> Hash[untyped, untyped]
22
+ # def parse_class: -> Class
23
+ # def parse_capitalized_identifier: -> Symbol
24
+ # def parse_object: -> Object
25
+ # def parse_attributes: -> Hash[Symbol, untyped]
26
+ # def parse_memory_reference: -> Integer
27
+ end
19
28
 
20
29
  class Class
21
30
  # def initialize: (name: Symbol?, namespaces: Array[Symbol]) -> void
@@ -31,29 +40,55 @@ module Tcepsni
31
40
  end
32
41
 
33
42
  class Object
34
- # def initialize: (klass: Class, attributes: Hash[Symbol, parsed], memory_reference: Integer) -> void
43
+ # def initialize: (klass: Class, attributes: Hash[Symbol, untyped], memory_reference: Integer) -> void
35
44
  # attr_reader klass: Class
36
- # attr_reader attributes: Hash[Symbol, (Array[untyped] | Array[untyped] | Class | Hash[untyped, untyped] | Hash[untyped, untyped] | Integer | Object | String | StringScanner | Symbol | bool)?]
45
+ # attr_reader attributes: Hash[Symbol, untyped]
37
46
  # attr_reader memory_reference: Integer
38
47
  end
39
48
 
40
49
  module Vendor
41
50
  class StringScanner
42
- # def initialize: (pos: Integer, total: Integer, scanned: String, rest: String) -> void
43
- # attr_reader pos: Integer
44
- # attr_reader total: Integer
45
- # attr_reader scanned: String
46
- # attr_reader rest: String
51
+ attr_reader pos: untyped
52
+ attr_reader total: untyped
53
+ attr_reader scanned: untyped
54
+ attr_reader rest: untyped
55
+ def initialize: (pos: untyped, total: untyped, scanned: untyped, rest: untyped) -> void
56
+ def self.parse: (untyped parser) -> StringScanner
57
+ def self.dependencies: -> Array[untyped]
58
+ def self.object?: -> true
47
59
  end
48
60
 
49
61
  module Rails
50
62
  module Paths
51
63
  class Root
52
- # def initialize: (Integer memory_reference, Hash[Symbol, parsed?] attributes) -> void
53
- # attr_reader memory_reference: Integer
54
- # attr_reader attributes: Hash[Symbol, (Array[untyped] | Array[untyped] | Class | Hash[untyped, untyped] | Hash[untyped, untyped] | Integer | Object | String | StringScanner | Symbol | bool)?]
64
+ attr_reader memory_reference: untyped
65
+ attr_reader attributes: Hash[untyped, untyped]
66
+ def initialize: (untyped memory_reference, Hash[untyped, untyped] attributes) -> void
67
+ def self.parse: (untyped parser) -> Root
68
+ def self.object?: -> true
69
+ def self.dependencies: -> [singleton(Pathname)]
55
70
  end
56
71
  end
57
72
  end
73
+
74
+ module ActiveSupport
75
+ class OrderedOptions
76
+ def self.parse: (untyped parser) -> untyped
77
+ def self.dependencies: -> Array[untyped]
78
+ def self.object?: -> true
79
+ end
80
+ end
81
+
82
+ class IPAddr
83
+ def self.parse: (untyped parser) -> IPAddr
84
+ def self.object?: -> true
85
+ def self.dependencies: -> Array[untyped]
86
+ end
87
+
88
+ class Pathname
89
+ def self.parse: (untyped parser) -> Pathname
90
+ def self.object?: -> true
91
+ def self.dependencies: -> Array[untyped]
92
+ end
58
93
  end
59
94
  end
data/sig/tcepsni.rbs CHANGED
@@ -4,11 +4,23 @@ module Tcepsni
4
4
  class Error < StandardError
5
5
  end
6
6
 
7
- type parsed = nil | Symbol | FalseClass | TrueClass | Integer | String |
8
- Array[parsed] | Hash[parsed, parsed] |
9
- Class | Object | StringScanner
7
+ def self.parse: (String str) -> untyped
10
8
 
11
- def self.parse: (String str) -> parsed
9
+ class Parser
10
+ def initialize: (String source, vendors: Array[untyped]?) -> void
11
+ def parse_expression: -> untyped
12
+ alias parse parse_expression
13
+ def parse_integer: -> Integer
14
+ def parse_identifier: -> Symbol
15
+ def parse_string: -> String
16
+ def parse_array: -> Array[untyped]
17
+ def parse_hash: -> Hash[untyped, untyped]
18
+ def parse_class: -> Class
19
+ def parse_capitalized_identifier: -> Symbol
20
+ def parse_object: -> Object
21
+ def parse_attributes: -> Hash[Symbol, untyped]
22
+ def parse_memory_reference: -> Integer
23
+ end
12
24
 
13
25
  class Class
14
26
  attr_reader name: Symbol
@@ -25,28 +37,31 @@ module Tcepsni
25
37
 
26
38
  class Object
27
39
  attr_reader klass: ::Class
28
- attr_reader attributes: Hash[Symbol, parsed]
40
+ attr_reader attributes: Hash[Symbol, untyped]
29
41
  attr_reader memory_reference: Integer
30
- def initialize: (klass: Class, attributes: Hash[Symbol, parsed], memory_reference: Integer) -> void
42
+ def initialize: (klass: Class, attributes: Hash[Symbol, untyped], memory_reference: Integer) -> void
31
43
  end
32
44
 
33
45
  module Vendor
34
46
  class StringScanner
35
- attr_reader pos: Integer
36
- attr_reader total: Integer
37
- attr_reader scanned: String
38
- attr_reader rest: String
39
- def initialize: (pos: Integer, total: Integer, scanned: String, rest: String) -> void
40
47
  end
41
48
 
42
49
  module Rails
43
50
  module Paths
44
51
  class Root
45
- attr_reader memory_reference: Integer
46
- attr_reader attributes: Hash[Symbol, parsed?]
47
- def initialize: (Integer memory_reference, Hash[Symbol, parsed?] attributes) -> void
48
52
  end
49
53
  end
50
54
  end
55
+
56
+ module ActiveSupport
57
+ class OrderedOptions
58
+ end
59
+ end
60
+
61
+ class IPAddr
62
+ end
63
+
64
+ class Pathname
65
+ end
51
66
  end
52
67
  end
data/tcepsni.gemspec CHANGED
@@ -9,10 +9,22 @@ Gem::Specification.new do |spec|
9
9
  spec.summary = 'inspected Ruby objects parser'
10
10
  spec.description = 'Tcepsni gem is a parser library for inspected strings of Ruby objects.'
11
11
  spec.license = 'Apache-2.0'
12
+
13
+ spec.homepage = 'https://codeberg.org/gemmaro/tcepsni'
14
+
12
15
  spec.required_ruby_version = '>= 3.1.0'
13
16
 
14
17
  spec.files = Dir['lib/**/*.rb'] + Dir['sig/**/*.rbs'] +
15
18
  ['CHANGELOG.md', 'tcepsni.gemspec', 'README.md', 'LICENSE.txt']
16
19
  spec.require_paths = ['lib']
17
- spec.metadata['rubygems_mfa_required'] = 'true'
20
+
21
+ spec.metadata = {
22
+ 'rubygems_mfa_required' => 'true',
23
+ 'bug_tracker_uri' => 'https://codeberg.org/gemmaro/tcepsni/issues',
24
+ 'changelog_uri' => 'https://codeberg.org/gemmaro/tcepsni/src/branch/main/CHANGELOG.md',
25
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/tcepsni',
26
+ 'homepage_uri' => spec.homepage,
27
+ 'source_code_uri' => spec.homepage,
28
+ 'wiki_uri' => 'https://codeberg.org/gemmaro/tcepsni/wiki'
29
+ }
18
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcepsni
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - gemmaro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-20 00:00:00.000000000 Z
11
+ date: 2024-07-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Tcepsni gem is a parser library for inspected strings of Ruby objects.
14
14
  email:
@@ -21,15 +21,27 @@ files:
21
21
  - LICENSE.txt
22
22
  - README.md
23
23
  - lib/tcepsni.rb
24
+ - lib/tcepsni/parser.rb
25
+ - lib/tcepsni/vendor/activesupport/ordered_options.rb
26
+ - lib/tcepsni/vendor/ipaddr.rb
27
+ - lib/tcepsni/vendor/pathname.rb
28
+ - lib/tcepsni/vendor/rails/paths/root.rb
29
+ - lib/tcepsni/vendor/string_scanner.rb
24
30
  - lib/tcepsni/version.rb
25
31
  - sig/tcepsni.gen.rbs
26
32
  - sig/tcepsni.rbs
27
33
  - tcepsni.gemspec
28
- homepage:
34
+ homepage: https://codeberg.org/gemmaro/tcepsni
29
35
  licenses:
30
36
  - Apache-2.0
31
37
  metadata:
32
38
  rubygems_mfa_required: 'true'
39
+ bug_tracker_uri: https://codeberg.org/gemmaro/tcepsni/issues
40
+ changelog_uri: https://codeberg.org/gemmaro/tcepsni/src/branch/main/CHANGELOG.md
41
+ documentation_uri: https://www.rubydoc.info/gems/tcepsni
42
+ homepage_uri: https://codeberg.org/gemmaro/tcepsni
43
+ source_code_uri: https://codeberg.org/gemmaro/tcepsni
44
+ wiki_uri: https://codeberg.org/gemmaro/tcepsni/wiki
33
45
  post_install_message:
34
46
  rdoc_options: []
35
47
  require_paths: