tcepsni 0.1.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f68a9bde443479e50e62f0f201a17c986eaad09e686e48adb24fa6a600ce38cb
4
- data.tar.gz: 2e718d175261eb10ded9c3fbcad4926b6c98e5072d0a81d148aa1f40c6f04571
3
+ metadata.gz: 3c7e2dad3ee934784b32e2263cfd23a6a478ec4d648b7e02f1a02267238296e5
4
+ data.tar.gz: 5db7c50e53eea93481004efd7d2f359db19fe8099356bfd980564f3b861d52d1
5
5
  SHA512:
6
- metadata.gz: 232ff2963d9bca49cea25eb7cc90bc6fc08815808058289e61b6ffae5dc8ee1516b43a2d56b64fde23c707034b7d1d1c068c417fc66a1e21503327f32237d5bb
7
- data.tar.gz: aadf113b5b26b20fc9d648ead1b43bf29f1c48eddd977348f0ef195af98dc0ab5fed4654dfd79a7b4f3009411b47a3d97e4834143c3ee99f6dab0b724300135c
6
+ metadata.gz: fc943477c66e694f76a6711ec01a2f82893c756fe7e30b1f00e8ef82d04c63699899b28252e2d046d148af68195a049bf2ca79b8b90bde359474ac610d9d3804
7
+ data.tar.gz: 8daf45aa53eb860b306357831c0c86a17d0e847fba6cfa8a051fe932a6d355ccfee936aee3ef48949b05a418013b7e140ce37ff57108ae653f768c97359c2f94
data/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
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
+
16
+ ## 0.2.0 - 2023-10-20
17
+
18
+ ### Added
19
+
20
+ - `Time` support
21
+ - `Pathname` support
22
+ - `Encoding` support
23
+ - `IPAddr` support
24
+ - `ActiveSupport::OrderedOptions` support
25
+ - `Rails::Paths::Root` support
26
+ - `Float` support
27
+
28
+ ### Fixed
29
+
30
+ - Parsing the empty array
31
+ - Parsing the object with some attributes
32
+ - Parsing the `nil`, `true`, and `false` literals
33
+ - Detecting `StringScanner`-like object
34
+
5
35
  ## 0.1.1 - 2023-10-02
6
36
 
7
37
  ### Changed
@@ -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.1.1'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/tcepsni.rb CHANGED
@@ -1,135 +1,11 @@
1
- require 'strscan'
2
1
  require_relative 'tcepsni/version'
2
+ require_relative 'tcepsni/parser'
3
3
 
4
4
  module Tcepsni
5
5
  class Error < StandardError; end
6
6
 
7
- def self.parse(str)
8
- scanner = ::StringScanner.new(str)
9
- parse_expression(scanner)
10
- end
11
-
12
- class << self
13
- private
14
-
15
- # If it returned nil when failed, it collides with normal nil value.
16
- def parse_expression(scanner)
17
- if scanner.skip('nil')
18
- nil
19
- elsif scanner.skip('true')
20
- true
21
- elsif scanner.skip('false')
22
- false
23
- elsif scanner.skip(':')
24
- parse_identifier(scanner)
25
- elsif scanner.skip('"')
26
- parse_string(scanner)
27
- elsif scanner.skip('[')
28
- parse_array(scanner)
29
- elsif scanner.skip('{')
30
- parse_hash(scanner)
31
- elsif scanner.skip('#<')
32
- parse_object(scanner)
33
- else
34
- parse_integer(scanner) or parse_class(scanner)
35
- end
36
- end
37
-
38
- # Returns nil if it's not integer.
39
- # This doesn't raise error for convenience.
40
- def parse_integer(scanner)
41
- int = scanner.scan(/\d+/) or return
42
- Integer(int)
43
- end
44
-
45
- def parse_identifier(scanner)
46
- id = scanner.scan(/[A-Za-z_][A-Za-z0-9_]*/) or raise Error, 'no identifier'
47
- id.intern
48
- end
49
-
50
- def parse_string(scanner)
51
- result = ''
52
- until scanner.eos?
53
- if scanner.skip('"')
54
- return result
55
- elsif scanner.skip('\\"')
56
- result << '"'
57
- else
58
- result << scanner.getch
59
- end
60
- end
61
- result
62
- end
63
-
64
- def parse_array(scanner)
65
- result = [parse_expression(scanner)]
66
- until scanner.eos?
67
- scanner.skip(', ') or break
68
- scanner.eos? and raise Error, 'incomplete array'
69
- result << parse_expression(scanner)
70
- end
71
- scanner.skip(']') or raise Error, 'no array closer'
72
- result
73
- end
74
-
75
- def parse_hash(scanner)
76
- result = {}
77
- until scanner.eos?
78
- key = parse_expression(scanner) rescue break
79
- scanner.skip('=>') or raise Error, 'no hash arrow'
80
- value = parse_expression(scanner)
81
- result[key] = value
82
- scanner.skip(', ') or break
83
- end
84
- scanner.skip('}') or raise Error, 'no hash closer'
85
- result
86
- end
87
-
88
- def parse_class(scanner)
89
- namespaces = [parse_capitalized_identifier(scanner)]
90
- until scanner.eos?
91
- scanner.skip('::') or break
92
- scanner.eos? and raise Error, 'incomplete class'
93
- namespaces << parse_capitalized_identifier(scanner)
94
- end
95
- *namespaces, name = namespaces
96
- Tcepsni::Class.new(name: name, namespaces: namespaces)
97
- end
98
-
99
- def parse_capitalized_identifier(scanner)
100
- id = scanner.scan(/[A-Z][A-Za-z0-9_]*/) or raise Error, 'no capitalized identifier'
101
- id.intern
102
- end
103
-
104
- def parse_object(scanner)
105
- klass = parse_class(scanner)
106
- if klass.string_scanner?
107
- scanner.skip(' ') or raise Error, 'no space after string scanner class name'
108
- pos = parse_integer(scanner) or raise Error, 'no string scanner pos'
109
- scanner.skip('/') or raise Error, 'no string scanner progress delimiter slash'
110
- total = parse_integer(scanner) or raise Error, 'no string scanner total size'
111
- scanner.skip(' "') or raise Error, 'no space after string scanner progress'
112
- scanned = parse_string(scanner)
113
- scanner.skip(' @ "') or raise Error, "no string scanner mark in string: #{scanner.inspect}"
114
- rest = parse_string(scanner)
115
- scanner.skip('>') or raise Error, 'no string scanner closer'
116
- Tcepsni::StringScanner.new(pos: pos, total: total, scanned: scanned, rest: rest)
117
- else
118
- scanner.skip(/:(?<memory_reference>0x[0-9a-f]{16})/) or raise Error, "no memory reference: #{scanner.inspect}"
119
- memory_reference = Integer(scanner[:memory_reference])
120
- attributes = {}
121
- unless scanner.skip('>')
122
- until scanner.eos?
123
- scanner.skip(' @') or break
124
- key = parse_identifier(scanner)
125
- scanner.skip('=') or raise Error, 'no attribute keyval equal char'
126
- attributes[key.intern] = parse_expression(scanner)
127
- scanner.skip(',') or break
128
- end
129
- end
130
- Tcepsni::Object.new(klass: klass, memory_reference: memory_reference, attributes: attributes)
131
- end
132
- end
7
+ def self.parse(str, vendors: [])
8
+ Parser.new(str, vendors: vendors).parse
133
9
  end
134
10
 
135
11
  class Class
@@ -140,8 +16,8 @@ module Tcepsni
140
16
  @namespaces = namespaces
141
17
  end
142
18
 
143
- def string_scanner?
144
- [name, *namespaces].include?(:StringScanner)
19
+ def encoding?
20
+ @name == :Encoding && @namespaces.empty?
145
21
  end
146
22
  end
147
23
 
@@ -154,15 +30,4 @@ module Tcepsni
154
30
  @memory_reference = memory_reference
155
31
  end
156
32
  end
157
-
158
- class StringScanner
159
- attr_reader :pos, :total, :scanned, :rest
160
-
161
- def initialize(pos:, total:, scanned:, rest:)
162
- @pos = pos
163
- @total = total
164
- @scanned = scanned
165
- @rest = rest
166
- end
167
- end
168
33
  end
data/sig/tcepsni.gen.rbs CHANGED
@@ -4,37 +4,91 @@
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 | Integer | Object | String | StringScanner | bool)?] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Class | Integer | Object | String | StringScanner | bool)?] | Integer | Object | String | StringScanner | bool)?] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Array[(Class | Integer | Object | String | StringScanner | bool)?] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Class | Integer | Object | String | StringScanner | bool)?] | Integer | Object | String | StringScanner | bool)?] | Integer | Object | String | StringScanner | bool)?)
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 | Hash[(Class | Integer | Object | String | StringScanner | bool)?, untyped] | Integer | Object | String | StringScanner | bool)?] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Array[untyped] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, untyped] | Integer | Object | String | StringScanner | bool)?] | Integer | Object | String | StringScanner | bool)?])
13
- def self.parse_hash: (untyped scanner) -> (Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Array[(Array[untyped] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, untyped] | Integer | Object | String | StringScanner | bool)?] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, (Array[untyped] | Class | Hash[(Class | Integer | Object | String | StringScanner | bool)?, untyped] | Integer | Object | String | StringScanner | bool)?] | Integer | Object | String | StringScanner | bool)?])
14
- def self.parse_class: (untyped scanner) -> Class
15
- def self.parse_capitalized_identifier: (untyped scanner) -> untyped
16
- def self.parse_object: (untyped scanner) -> (Object | StringScanner)
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
17
28
 
18
29
  class Class
19
30
  # def initialize: (name: Symbol?, namespaces: Array[Symbol]) -> void
20
31
  # def ==: (Class other) -> bool
21
32
  # def string_scanner?: -> bool
33
+ # def pathname?: -> bool
34
+ # def encoding?: -> bool
35
+ # def ipaddr?: -> bool
36
+ # def active_support_ordered_options?: -> bool
37
+ # def rails_paths_root?: -> bool
22
38
  # attr_reader name: Symbol?
23
39
  # attr_reader namespaces: Array[Symbol]
24
40
  end
25
41
 
26
42
  class Object
27
- # 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
28
44
  # attr_reader klass: Class
29
- # 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]
30
46
  # attr_reader memory_reference: Integer
31
47
  end
32
48
 
33
- class StringScanner
34
- # def initialize: (pos: Integer, total: Integer, scanned: String, rest: String) -> void
35
- # attr_reader pos: Integer
36
- # attr_reader total: Integer
37
- # attr_reader scanned: String
38
- # attr_reader rest: String
49
+ module Vendor
50
+ class StringScanner
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
59
+ end
60
+
61
+ module Rails
62
+ module Paths
63
+ class Root
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)]
70
+ end
71
+ end
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
39
93
  end
40
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
@@ -16,20 +28,40 @@ module Tcepsni
16
28
  def initialize: (name: Symbol?, namespaces: Array[Symbol]) -> void
17
29
  def ==: (Class other) -> bool
18
30
  def string_scanner?: -> bool
31
+ def pathname?: -> bool
32
+ def encoding?: -> bool
33
+ def ipaddr?: -> bool
34
+ def active_support_ordered_options?: -> bool
35
+ def rails_paths_root?: -> bool
19
36
  end
20
37
 
21
38
  class Object
22
39
  attr_reader klass: ::Class
23
- attr_reader attributes: Hash[Symbol, parsed]
40
+ attr_reader attributes: Hash[Symbol, untyped]
24
41
  attr_reader memory_reference: Integer
25
- 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
26
43
  end
27
44
 
28
- class StringScanner
29
- attr_reader pos: Integer
30
- attr_reader total: Integer
31
- attr_reader scanned: String
32
- attr_reader rest: String
33
- def initialize: (pos: Integer, total: Integer, scanned: String, rest: String) -> void
45
+ module Vendor
46
+ class StringScanner
47
+ end
48
+
49
+ module Rails
50
+ module Paths
51
+ class Root
52
+ end
53
+ end
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
34
66
  end
35
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.1.1
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-01 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