t-ruby 0.0.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.
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRuby
4
+ # Enhanced Parser using Parser Combinator for complex type expressions
5
+ # Maintains backward compatibility with original Parser interface
6
+ class Parser
7
+ # Type names that are recognized as valid
8
+ VALID_TYPES = %w[String Integer Boolean Array Hash Symbol void nil].freeze
9
+
10
+ attr_reader :source, :ir_program, :use_combinator
11
+
12
+ def initialize(source, use_combinator: true)
13
+ @source = source
14
+ @lines = source.split("\n")
15
+ @use_combinator = use_combinator
16
+ @type_parser = ParserCombinator::TypeParser.new if use_combinator
17
+ @ir_program = nil
18
+ end
19
+
20
+ def parse
21
+ functions = []
22
+ type_aliases = []
23
+ interfaces = []
24
+ i = 0
25
+
26
+ while i < @lines.length
27
+ line = @lines[i]
28
+
29
+ # Match type alias definitions
30
+ if line.match?(/^\s*type\s+\w+/)
31
+ alias_info = parse_type_alias(line)
32
+ type_aliases << alias_info if alias_info
33
+ end
34
+
35
+ # Match interface definitions
36
+ if line.match?(/^\s*interface\s+\w+/)
37
+ interface_info, next_i = parse_interface(i)
38
+ if interface_info
39
+ interfaces << interface_info
40
+ i = next_i
41
+ next
42
+ end
43
+ end
44
+
45
+ # Match function definitions
46
+ if line.match?(/^\s*def\s+\w+/)
47
+ func_info = parse_function_definition(line)
48
+ functions << func_info if func_info
49
+ end
50
+
51
+ i += 1
52
+ end
53
+
54
+ result = {
55
+ type: :success,
56
+ functions: functions,
57
+ type_aliases: type_aliases,
58
+ interfaces: interfaces
59
+ }
60
+
61
+ # Build IR if combinator is enabled
62
+ if @use_combinator
63
+ builder = IR::Builder.new
64
+ @ir_program = builder.build(result, source: @source)
65
+ end
66
+
67
+ result
68
+ end
69
+
70
+ # Parse to IR directly (new API)
71
+ def parse_to_ir
72
+ parse unless @ir_program
73
+ @ir_program
74
+ end
75
+
76
+ # Parse a type expression using combinator (new API)
77
+ def parse_type(type_string)
78
+ return nil unless @use_combinator
79
+
80
+ result = @type_parser.parse(type_string)
81
+ result[:success] ? result[:type] : nil
82
+ end
83
+
84
+ private
85
+
86
+ def parse_type_alias(line)
87
+ match = line.match(/^\s*type\s+(\w+)\s*=\s*(.+?)\s*$/)
88
+ return nil unless match
89
+
90
+ alias_name = match[1]
91
+ definition = match[2].strip
92
+
93
+ # Use combinator for complex type parsing if available
94
+ if @use_combinator
95
+ type_result = @type_parser.parse(definition)
96
+ if type_result[:success]
97
+ return {
98
+ name: alias_name,
99
+ definition: definition,
100
+ ir_type: type_result[:type]
101
+ }
102
+ end
103
+ end
104
+
105
+ {
106
+ name: alias_name,
107
+ definition: definition
108
+ }
109
+ end
110
+
111
+ def parse_function_definition(line)
112
+ match = line.match(/^\s*def\s+(\w+)\s*\((.*?)\)\s*(?::\s*(.+?))?\s*$/)
113
+ return nil unless match
114
+
115
+ function_name = match[1]
116
+ params_str = match[2]
117
+ return_type_str = match[3]&.strip
118
+
119
+ params = parse_parameters(params_str)
120
+
121
+ result = {
122
+ name: function_name,
123
+ params: params,
124
+ return_type: return_type_str
125
+ }
126
+
127
+ # Parse return type with combinator if available
128
+ if @use_combinator && return_type_str
129
+ type_result = @type_parser.parse(return_type_str)
130
+ result[:ir_return_type] = type_result[:type] if type_result[:success]
131
+ end
132
+
133
+ result
134
+ end
135
+
136
+ def parse_parameters(params_str)
137
+ return [] if params_str.empty?
138
+
139
+ parameters = []
140
+ param_list = split_params(params_str)
141
+
142
+ param_list.each do |param|
143
+ param_info = parse_single_parameter(param)
144
+ parameters << param_info if param_info
145
+ end
146
+
147
+ parameters
148
+ end
149
+
150
+ def split_params(params_str)
151
+ # Handle nested generics like Array<Map<String, Int>>
152
+ result = []
153
+ current = ""
154
+ depth = 0
155
+
156
+ params_str.each_char do |char|
157
+ case char
158
+ when "<", "[", "("
159
+ depth += 1
160
+ current += char
161
+ when ">", "]", ")"
162
+ depth -= 1
163
+ current += char
164
+ when ","
165
+ if depth == 0
166
+ result << current.strip
167
+ current = ""
168
+ else
169
+ current += char
170
+ end
171
+ else
172
+ current += char
173
+ end
174
+ end
175
+
176
+ result << current.strip unless current.empty?
177
+ result
178
+ end
179
+
180
+ def parse_single_parameter(param)
181
+ match = param.match(/^(\w+)(?::\s*(.+?))?$/)
182
+ return nil unless match
183
+
184
+ param_name = match[1]
185
+ type_str = match[2]&.strip
186
+
187
+ result = {
188
+ name: param_name,
189
+ type: type_str
190
+ }
191
+
192
+ # Parse type with combinator if available
193
+ if @use_combinator && type_str
194
+ type_result = @type_parser.parse(type_str)
195
+ result[:ir_type] = type_result[:type] if type_result[:success]
196
+ end
197
+
198
+ result
199
+ end
200
+
201
+ def parse_interface(start_index)
202
+ line = @lines[start_index]
203
+ match = line.match(/^\s*interface\s+(\w+)/)
204
+ return [nil, start_index] unless match
205
+
206
+ interface_name = match[1]
207
+ members = []
208
+ i = start_index + 1
209
+
210
+ while i < @lines.length
211
+ current_line = @lines[i]
212
+ break if current_line.match?(/^\s*end\s*$/)
213
+
214
+ if current_line.match?(/^\s*\w+\s*:\s*/)
215
+ member_match = current_line.match(/^\s*(\w+)\s*:\s*(.+?)\s*$/)
216
+ if member_match
217
+ member = {
218
+ name: member_match[1],
219
+ type: member_match[2].strip
220
+ }
221
+
222
+ # Parse member type with combinator
223
+ if @use_combinator
224
+ type_result = @type_parser.parse(member[:type])
225
+ member[:ir_type] = type_result[:type] if type_result[:success]
226
+ end
227
+
228
+ members << member
229
+ end
230
+ end
231
+
232
+ i += 1
233
+ end
234
+
235
+ [{ name: interface_name, members: members }, i]
236
+ end
237
+ end
238
+
239
+ # Legacy Parser for backward compatibility (regex-only)
240
+ class LegacyParser < Parser
241
+ def initialize(source)
242
+ super(source, use_combinator: false)
243
+ end
244
+ end
245
+ end