comment_strip-ruby 0.1.2.1 → 0.2.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.
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
1
2
  # ######################################################################## #
2
- # File: comment_strip/language_families/c.rb
3
+ # File: comment_strip/language_families/c.rb
3
4
  #
4
- # Purpose: Definition of strip() function for C-family languages.
5
+ # Purpose: Definition of strip() function for C-family languages.
5
6
  #
6
- # Created: 14th September 2020
7
- # Updated: 11th July 2022
7
+ # Created: 14th September 2020
8
+ # Updated: 30th August 2026
8
9
  #
9
- # Home: http://github.com/synesissoftware/comment_strip.r
10
+ # Home: https://github.com/synesissoftware/comment_strip.r
10
11
  #
11
- # Copyright (c) 2020-2022, Matthew Wilson and Synesis Information Systems
12
+ # Copyright (c) 2020-2026, Matthew Wilson and Synesis Information Systems
12
13
  # All rights reserved.
13
14
  #
14
15
  # Redistribution and use in source and binary forms, with or without
@@ -47,200 +48,324 @@ module LanguageFamilies
47
48
 
48
49
  module C
49
50
 
50
- def self.strip input, lf, **options
51
+ def self.decimal_digit? character
51
52
 
52
- return nil if input.nil?
53
- return input if input.empty?
53
+ character && character >= ?0 && character <= ?9
54
+ end
54
55
 
55
- line = 0
56
- column = 0
56
+ def self.identifier_character? character
57
57
 
58
- state = :text
58
+ return false unless character
59
59
 
60
- r = ''
60
+ case character
61
+ when ?a..?z, ?A..?Z, ?0..?9, '_'
62
+ true
63
+ else
64
+ false
65
+ end
66
+ end
67
+
68
+ def self.strip input, lf, **options
69
+
70
+ return input if input.nil?
71
+ return input if input.empty?
72
+
73
+ line = 0
74
+ column = 0
75
+
76
+ # States:
77
+ #
78
+ # - :c_comment - in a C comment, i.e. from immediately after "/*"
79
+ # - :c_comment_star - in a C comment when just received '*', e.g. from immediately after "/* comment *"
80
+ # - :cpp_comment - in a C++ comment, i.e. from immediately after "//"
81
+ # - :dq_string - within a double-quoted string
82
+ # - :dq_string_escape - within a double-quoted string when just received a '"', e.g. from immediately after '"the next word is quoted \'
83
+ # - :raw_string - within a C++ raw string
84
+ # - :raw_string_closing - waiting for the final '"' in a C++ raw string
85
+ # - :backtick_string - within a Go raw string
86
+ # - :backtick_string_open - waiting for the opening '`' in a Go raw string
87
+ # - :lifetime - within a Rust lifetime name
88
+ # - :verbatim_string - within a C# verbatim string
89
+ # - :verbatim_string_open - waiting for the opening '"' in a C# verbatim string
90
+ # - :verbatim_string_quote - waiting to determine whether a C# quote is doubled
91
+ # - :slash_start - having found a slash (not in a string)
92
+ # - :sq_string_closing - waiting for final '\'' in a single-quoted string
93
+ # - :sq_string_escape - within a escaped single-quoted string, i.e. from immediately after "'\"
94
+ # - :sq_string_open - within a single-quoted string, i.e. from immediately after "'"
95
+ # - :text - regular part of the code
96
+
97
+ state = :text
98
+
99
+ r = String.new
100
+ r.force_encoding input.encoding
101
+
102
+ cc_lines = 0
103
+ previous_was_cr = false
104
+
105
+ i = 0
106
+ while i < input.length
107
+ c = input[i]
108
+
109
+ if ?\\ == c
110
+ next_c = input[i + 1]
111
+
112
+ if ?\n == next_c
113
+ i += 2
114
+ previous_was_cr = false
115
+ next
116
+ elsif ?\r == next_c
117
+ i += 2
118
+ previous_was_cr = false
119
+
120
+ if ?\n == input[i]
121
+ i += 1
122
+ next
123
+ end
124
+
125
+ next if i >= input.length
126
+
127
+ c = input[i]
128
+ end
129
+ end
61
130
 
62
- cc_lines = 0
131
+ case c
132
+ when ?\r, ?\n
63
133
 
64
- input.each_char do |c|
134
+ line += 1 unless ?\n == c && previous_was_cr
135
+ column = 0
136
+ else
65
137
 
66
- case c
67
- when ?\r, ?\n
138
+ column += 1
139
+ end
68
140
 
69
- line += 1
70
- column = 0
71
- else
141
+ skip = false
72
142
 
73
- column += 1
74
- end
143
+ if :text == state && 'R' == c && '"' == input[i + 1] && '(' == input[i + 2]
144
+ state = :raw_string
145
+ elsif :text == state && '@' == c && '"' == input[i + 1]
146
+ state = :verbatim_string_open
147
+ elsif :text == state && i > 0 && '<' == input[i - 1] && input[i + 1] && input[i + 1] >= ?a && input[i + 1] <= ?z
148
+ state = :lifetime
149
+ elsif :text == state && '`' == c
150
+ state = :backtick_string_open
151
+ end
75
152
 
76
- skip = false
153
+ case c
154
+ when ?\r, ?\n
77
155
 
78
- case c
79
- when ?\r, ?\n
156
+ case state
157
+ when :c_comment, :c_comment_star
80
158
 
81
- case state
82
- when :c_comment, :c_comment_star
159
+ cc_lines += 1 unless ?\n == c && previous_was_cr
83
160
 
84
- cc_lines += 1
161
+ state = :c_comment
162
+ when :cpp_comment
85
163
 
86
- state = :c_comment
87
- when :cpp_comment
164
+ state = :text
165
+ when :sq_string_escape, :sq_string_closing
88
166
 
89
- state = :text
90
- when :sq_string, :sq_string_escape, :sq_string_closing
167
+ state = :text
168
+ when :dq_string_escape
91
169
 
92
- state = :text
93
- when :dq_string_escape
170
+ state = :dq_string
171
+ when :slash_start
94
172
 
95
- state = :dq_string
96
- when :slash_start
173
+ r << '/'
97
174
 
98
- r << '/'
175
+ state = :text
176
+ end
177
+ else
99
178
 
100
- state = :text
101
- end
102
- else
179
+ # special cases:
180
+ #
181
+ # - for escaped single/double quote
182
+ # - for slash-start
183
+ # - for comment-star
103
184
 
104
- # special cases:
105
- #
106
- # - for escaped single/double quote
107
- # - for slash-start
108
- # - for comment-star
185
+ case state
186
+ when :backtick_string_open
109
187
 
110
- case state
111
- when :sq_string_open
188
+ state = :backtick_string if '`' == c
189
+ when :backtick_string
112
190
 
113
- state = (?\\ == c) ? :sq_string_escape : :sq_string_closing
114
- when :sq_string_escape
191
+ state = :text if '`' == c
192
+ when :lifetime
115
193
 
116
- state = :sq_string_closing
117
- when :dq_string_escape
194
+ if !identifier_character?(c)
195
+ state = :text
196
+ elsif !identifier_character?(input[i + 1])
197
+ state = :text
198
+ end
199
+ when :verbatim_string_open
118
200
 
119
- state = :dq_string
120
- when :c_comment_star
201
+ state = :verbatim_string if '"' == c
202
+ when :verbatim_string
121
203
 
122
- case c
123
- when ?/
204
+ if '"' == c
205
+ state = :verbatim_string_quote if '"' == input[i + 1]
206
+ state = :text unless '"' == input[i + 1]
207
+ end
208
+ when :verbatim_string_quote
124
209
 
125
- r << ?\n * cc_lines
126
- cc_lines = 0
210
+ state = :verbatim_string if '"' == c
211
+ when :raw_string
127
212
 
128
- state = :text
129
- skip = true
130
- when '*'
213
+ state = :raw_string_closing if ')' == c && '"' == input[i + 1]
214
+ when :raw_string_closing
131
215
 
132
- ;
133
- else
216
+ state = :text if '"' == c
217
+ when :sq_string_open
134
218
 
135
- state = :c_comment
136
- end
137
- else
219
+ state = (?\\ == c) ? :sq_string_escape : :sq_string_closing
220
+ when :sq_string_escape
138
221
 
139
- if false
140
- elsif state == :slash_start && ('/' != c && '*' != c)
222
+ state = :sq_string_closing
223
+ when :dq_string_escape
141
224
 
142
- state = :text
143
- r << '/'
144
- else
225
+ state = :dq_string
226
+ when :c_comment_star
145
227
 
146
- case c
147
- when '/'
228
+ case c
229
+ when ?/
148
230
 
149
- case state
150
- when :text
231
+ r << ?\n * cc_lines
232
+ cc_lines = 0
151
233
 
152
- state = :slash_start
153
- when :slash_start
234
+ state = :text
235
+ skip = true
236
+ when '*'
154
237
 
155
- state = :cpp_comment
156
- when :c_comment_star
238
+ ;
239
+ else
157
240
 
158
- r << ?\n * cc_lines
159
- cc_lines = 0
241
+ state = :c_comment
242
+ end
243
+ else
160
244
 
161
- state = :text
162
- skip = true
163
- end
164
- when '*'
245
+ if false
246
+ elsif state == :slash_start && ('/' != c && '*' != c)
165
247
 
166
- case state
167
- when :slash_start
248
+ state = :text
249
+ r << '/'
250
+ else
168
251
 
169
- state = :c_comment
170
- when :c_comment
252
+ case c
253
+ when '/'
171
254
 
172
- state = :c_comment_star
173
- else
255
+ case state
256
+ when :text
174
257
 
175
- end
258
+ state = :slash_start
259
+ when :slash_start
176
260
 
177
- when ?\'
261
+ state = :cpp_comment
262
+ when :c_comment_star
178
263
 
179
- case state
180
- when :text
264
+ r << ?\n * cc_lines
265
+ cc_lines = 0
181
266
 
182
- state = :sq_string_open
183
- when :sq_string_closing
267
+ state = :text
268
+ skip = true
269
+ else
184
270
 
185
- state = :text
186
- else
271
+ ;
272
+ end
273
+ when '*'
187
274
 
188
- end
189
- when '"'
275
+ case state
276
+ when :slash_start
190
277
 
191
- case state
192
- when :text
278
+ state = :c_comment
279
+ when :c_comment
193
280
 
194
- state = :dq_string
195
- when :dq_string
281
+ state = :c_comment_star
282
+ else
196
283
 
197
- state = :text
198
- else
199
- end
200
- when ?\\
284
+ ;
285
+ end
286
+ when ?\'
201
287
 
202
- case state
203
- when :sq_string_open
288
+ case state
289
+ when :text
204
290
 
205
- state = :sq_string_escape
206
- when :sq_string_escape
291
+ if i > 0 && decimal_digit?(input[i - 1]) && decimal_digit?(input[i + 1])
292
+ ;
293
+ else
294
+ state = :sq_string_open
295
+ end
296
+ when :sq_string_closing
207
297
 
208
- state = :sq_string
209
- when :dq_string
298
+ state = :text
299
+ else
210
300
 
211
- state = :dq_string_escape
212
- else
301
+ ;
302
+ end
303
+ when '"'
213
304
 
214
- end
215
- else
305
+ case state
306
+ when :text
216
307
 
217
- case state
218
- when :sq_string_escape
308
+ state = :dq_string
309
+ when :dq_string
219
310
 
220
- state = :sq_string_closing
221
- else
311
+ state = :text
312
+ else
222
313
 
223
- end
224
- end
225
- end
226
- end
227
- end
314
+ ;
315
+ end
316
+ when ?\\
317
+
318
+ case state
319
+ when :sq_string_open
228
320
 
321
+ state = :sq_string_escape
322
+ when :sq_string_escape
229
323
 
230
- case state
231
- when :slash_start
232
- when :cpp_comment
233
- when :c_comment
234
- when :c_comment_star
324
+ state = :sq_string_closing
325
+ when :dq_string
235
326
 
327
+ state = :dq_string_escape
328
+ else
329
+
330
+ ;
331
+ end
236
332
  else
237
333
 
238
- r << c unless skip
334
+ case state
335
+ when :sq_string_escape
336
+
337
+ state = :sq_string_closing
338
+ else
339
+
340
+ ;
341
+ end
239
342
  end
343
+ end
240
344
  end
345
+ end
241
346
 
242
- r
347
+
348
+ case state
349
+ when :slash_start
350
+ when :cpp_comment
351
+ when :c_comment
352
+ when :c_comment_star
353
+
354
+ ;
355
+ else
356
+
357
+ r << c unless skip
358
+ end
359
+
360
+ previous_was_cr = ?\r == c
361
+ i += 1
243
362
  end
363
+
364
+ r << '/' if :slash_start == state
365
+ r << ?\n * cc_lines if [ :c_comment, :c_comment_star, ].include?(state)
366
+
367
+ r
368
+ end
244
369
  end # module C
245
370
 
246
371
  end # module LanguageFamilies