tcepsni 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3695b6a1a12979fa76824819d4f839ce4e3b9a2af040f97eca9e474609c5c1f2
4
- data.tar.gz: 373da53b2e230d3510f2043f25b8ae7cf017fae689fdfbaa92a388be4155ebcd
3
+ metadata.gz: 3c7e2dad3ee934784b32e2263cfd23a6a478ec4d648b7e02f1a02267238296e5
4
+ data.tar.gz: 5db7c50e53eea93481004efd7d2f359db19fe8099356bfd980564f3b861d52d1
5
5
  SHA512:
6
- metadata.gz: f646aecf1094e4e171581b52ca0e48dccddc4464bf158f4c30b93e8df7ef7b8989b240e9c61abf25a7cb65c2c9a29ec6978529f627a1c360f0fede299624d297
7
- data.tar.gz: 573e5e82c5c7a0b476ee93255fe6b6fc7992febcee911e54ee1b852c9acacca29950bc67183ec01cbed7c3cf3cfcce3edd21137f1c04400bff42959d6f1d72c8
6
+ metadata.gz: fc943477c66e694f76a6711ec01a2f82893c756fe7e30b1f00e8ef82d04c63699899b28252e2d046d148af68195a049bf2ca79b8b90bde359474ac610d9d3804
7
+ data.tar.gz: 8daf45aa53eb860b306357831c0c86a17d0e847fba6cfa8a051fe932a6d355ccfee936aee3ef48949b05a418013b7e140ce37ff57108ae653f768c97359c2f94
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.0 - 2023-11-18
6
+
7
+ ### Changed
8
+
9
+ - Introduced plugin system.
10
+ For example, if the source contains `Pathname` objects, use the `vendors` option like `Tcepsni.parse(str, vendors: [::Tcepsni::Vendor::Pathname])`.
11
+
12
+ ### Removed
13
+
14
+ - `Tcepsni::Class#string_scanner?`, `Tcepsni::Class#pathname?`, `Tcepsni::Class#ipaddr?`, `Tcepsni::Class#active_support_ordered_options?`, and `Tcepsni::Class#rails_paths_root?`.
15
+
5
16
  ## 0.2.0 - 2023-10-20
6
17
 
7
18
  ### Added
@@ -0,0 +1,161 @@
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
+ begin
31
+ @scanner.pos = pos
32
+ return vendor.parse(self)
33
+ rescue Error
34
+ next
35
+ end
36
+ end
37
+ @scanner.pos = pos
38
+ parse_object
39
+ else
40
+ if (digits = @scanner.scan(/\d+/))
41
+ int = Integer(digits)
42
+ if @scanner.skip('.')
43
+ int2 = parse_integer
44
+ Float("#{int}.#{int2}")
45
+ 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)/)
46
+ Time.new(Integer(int), @scanner[:month], @scanner[:day],
47
+ @scanner[:hour], @scanner[:minute], @scanner[:second],
48
+ @scanner[:zone])
49
+ else
50
+ int
51
+ end
52
+ else
53
+ parse_class
54
+ end
55
+ end
56
+ end
57
+
58
+ alias parse parse_expression
59
+
60
+ def parse_integer
61
+ int = @scanner.scan(/\d+/) or raise Error, 'no digits'
62
+ Integer(int)
63
+ end
64
+
65
+ def parse_identifier
66
+ id = @scanner.scan(/[A-Za-z_][A-Za-z0-9_]*/) or raise Error, 'no identifier'
67
+ id.intern
68
+ end
69
+
70
+ def parse_string
71
+ result = ''
72
+ until @scanner.eos?
73
+ if @scanner.skip('"')
74
+ return result
75
+ elsif @scanner.skip('\\"')
76
+ result << '"'
77
+ else
78
+ result << @scanner.getch
79
+ end
80
+ end
81
+ result
82
+ end
83
+
84
+ def parse_array
85
+ result = []
86
+ until @scanner.eos?
87
+ result << parse_expression rescue break
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 = parse_expression rescue break
98
+ @scanner.skip('=>') or raise Error, 'no hash arrow'
99
+ value = parse_expression
100
+ result[key] = value
101
+ @scanner.skip(', ') or break
102
+ end
103
+ @scanner.skip('}') or raise Error, 'no hash closer'
104
+ result
105
+ end
106
+
107
+ def parse_class
108
+ namespaces = [parse_capitalized_identifier]
109
+ until @scanner.eos?
110
+ @scanner.skip('::') or break
111
+ @scanner.eos? and raise Error, 'incomplete class'
112
+ namespaces << parse_capitalized_identifier
113
+ end
114
+ *namespaces, name = namespaces
115
+ Tcepsni::Class.new(name: name, namespaces: namespaces)
116
+ end
117
+
118
+ def parse_capitalized_identifier
119
+ id = @scanner.scan(/[A-Z][A-Za-z0-9_]*/) or raise Error, "no capitalized identifier: #{@scanner.inspect}"
120
+ id.intern
121
+ end
122
+
123
+ def parse_object
124
+ klass = parse_class
125
+ if klass.encoding?
126
+ @scanner.skip(':') or raise Error, 'no colon separator in encoding object'
127
+ @scanner.skip(/(?<name>[^>]+)>/) or raise Error, 'invalid encoding name'
128
+ Encoding.find(@scanner[:name])
129
+ else
130
+ memory_reference = parse_memory_reference
131
+ attributes = parse_attributes
132
+ Tcepsni::Object.new(klass: klass, memory_reference: memory_reference, attributes: attributes)
133
+ end
134
+ end
135
+
136
+ def parse_attributes
137
+ attributes = {}
138
+ unless @scanner.skip('>')
139
+ until @scanner.eos?
140
+ @scanner.skip(' @') or break
141
+ key = parse_identifier
142
+ @scanner.skip('=') or raise Error, 'no attribute keyval equal char'
143
+ attributes[key.intern] = parse_expression
144
+ unless @scanner.skip(',')
145
+ @scanner.skip('>') or raise Error, "no object closer: #{@scanner.inspect}"
146
+ break
147
+ end
148
+ end
149
+ end
150
+ attributes
151
+ end
152
+
153
+ def parse_memory_reference
154
+ @scanner.skip(/:(?<memory_reference>0x[0-9a-f]{16})/) or raise Error, "no memory reference: #{@scanner.inspect}"
155
+ Integer(@scanner[:memory_reference])
156
+ end
157
+
158
+ extend Forwardable
159
+ def_delegators :@scanner, :skip, :[]
160
+ end
161
+ 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
+ if parser.skip(' ...>')
19
+ attributes = {}
20
+ else
21
+ attributes = 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: pos, total: total, scanned: scanned, rest: 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.0'
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
5
  class Error < StandardError; end
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: 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
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.0
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: 2023-11-18 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,6 +21,12 @@ 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