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.
- checksums.yaml +4 -4
- data/AUTHORS.md +21 -0
- data/CHANGES.md +62 -0
- data/CONTRIBUTING.md +36 -0
- data/EXAMPLES.md +9 -0
- data/FAQ.md +28 -0
- data/INSTALL.md +41 -0
- data/LICENSE +19 -18
- data/NEWS.md +16 -0
- data/README.md +81 -18
- data/Rakefile +21 -0
- data/SECURITY.md +23 -0
- data/TODO.md +49 -0
- data/examples/read_c_family_source.rb +39 -0
- data/examples/read_c_family_source_from_stdin.rb +39 -0
- data/lib/comment_strip/language_families/c.rb +259 -134
- data/lib/comment_strip/language_families/hash_line.rb +297 -0
- data/lib/comment_strip/strip.rb +31 -15
- data/lib/comment_strip/version.rb +8 -8
- data/lib/comment_strip.rb +7 -6
- data/test/unit/{tc_strip.rb → tc_strip_c.rb} +266 -236
- data/test/unit/tc_strip_c_defects.rb +179 -0
- data/test/unit/tc_strip_hash_line.rb +95 -0
- data/test/unit/tc_strip_hash_line_defects.rb +154 -0
- data/test/unit/ts_all.rb +1 -1
- metadata +37 -13
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
# ######################################################################## #
|
|
2
|
-
# File:
|
|
3
|
+
# File: comment_strip/language_families/c.rb
|
|
3
4
|
#
|
|
4
|
-
# Purpose:
|
|
5
|
+
# Purpose: Definition of strip() function for C-family languages.
|
|
5
6
|
#
|
|
6
|
-
# Created:
|
|
7
|
-
# Updated:
|
|
7
|
+
# Created: 14th September 2020
|
|
8
|
+
# Updated: 30th August 2026
|
|
8
9
|
#
|
|
9
|
-
# Home:
|
|
10
|
+
# Home: https://github.com/synesissoftware/comment_strip.r
|
|
10
11
|
#
|
|
11
|
-
# Copyright (c) 2020-
|
|
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
|
-
|
|
51
|
+
def self.decimal_digit? character
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
character && character >= ?0 && character <= ?9
|
|
54
|
+
end
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
column = 0
|
|
56
|
+
def self.identifier_character? character
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
return false unless character
|
|
59
59
|
|
|
60
|
-
|
|
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
|
-
|
|
131
|
+
case c
|
|
132
|
+
when ?\r, ?\n
|
|
63
133
|
|
|
64
|
-
|
|
134
|
+
line += 1 unless ?\n == c && previous_was_cr
|
|
135
|
+
column = 0
|
|
136
|
+
else
|
|
65
137
|
|
|
66
|
-
|
|
67
|
-
|
|
138
|
+
column += 1
|
|
139
|
+
end
|
|
68
140
|
|
|
69
|
-
|
|
70
|
-
column = 0
|
|
71
|
-
else
|
|
141
|
+
skip = false
|
|
72
142
|
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
153
|
+
case c
|
|
154
|
+
when ?\r, ?\n
|
|
77
155
|
|
|
78
|
-
|
|
79
|
-
|
|
156
|
+
case state
|
|
157
|
+
when :c_comment, :c_comment_star
|
|
80
158
|
|
|
81
|
-
|
|
82
|
-
when :c_comment, :c_comment_star
|
|
159
|
+
cc_lines += 1 unless ?\n == c && previous_was_cr
|
|
83
160
|
|
|
84
|
-
|
|
161
|
+
state = :c_comment
|
|
162
|
+
when :cpp_comment
|
|
85
163
|
|
|
86
|
-
|
|
87
|
-
|
|
164
|
+
state = :text
|
|
165
|
+
when :sq_string_escape, :sq_string_closing
|
|
88
166
|
|
|
89
|
-
|
|
90
|
-
|
|
167
|
+
state = :text
|
|
168
|
+
when :dq_string_escape
|
|
91
169
|
|
|
92
|
-
|
|
93
|
-
|
|
170
|
+
state = :dq_string
|
|
171
|
+
when :slash_start
|
|
94
172
|
|
|
95
|
-
|
|
96
|
-
when :slash_start
|
|
173
|
+
r << '/'
|
|
97
174
|
|
|
98
|
-
|
|
175
|
+
state = :text
|
|
176
|
+
end
|
|
177
|
+
else
|
|
99
178
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
179
|
+
# special cases:
|
|
180
|
+
#
|
|
181
|
+
# - for escaped single/double quote
|
|
182
|
+
# - for slash-start
|
|
183
|
+
# - for comment-star
|
|
103
184
|
|
|
104
|
-
|
|
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
|
-
|
|
111
|
-
|
|
188
|
+
state = :backtick_string if '`' == c
|
|
189
|
+
when :backtick_string
|
|
112
190
|
|
|
113
|
-
|
|
114
|
-
|
|
191
|
+
state = :text if '`' == c
|
|
192
|
+
when :lifetime
|
|
115
193
|
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
120
|
-
|
|
201
|
+
state = :verbatim_string if '"' == c
|
|
202
|
+
when :verbatim_string
|
|
121
203
|
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
126
|
-
|
|
210
|
+
state = :verbatim_string if '"' == c
|
|
211
|
+
when :raw_string
|
|
127
212
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
when '*'
|
|
213
|
+
state = :raw_string_closing if ')' == c && '"' == input[i + 1]
|
|
214
|
+
when :raw_string_closing
|
|
131
215
|
|
|
132
|
-
|
|
133
|
-
|
|
216
|
+
state = :text if '"' == c
|
|
217
|
+
when :sq_string_open
|
|
134
218
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
else
|
|
219
|
+
state = (?\\ == c) ? :sq_string_escape : :sq_string_closing
|
|
220
|
+
when :sq_string_escape
|
|
138
221
|
|
|
139
|
-
|
|
140
|
-
|
|
222
|
+
state = :sq_string_closing
|
|
223
|
+
when :dq_string_escape
|
|
141
224
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
else
|
|
225
|
+
state = :dq_string
|
|
226
|
+
when :c_comment_star
|
|
145
227
|
|
|
146
|
-
|
|
147
|
-
|
|
228
|
+
case c
|
|
229
|
+
when ?/
|
|
148
230
|
|
|
149
|
-
|
|
150
|
-
|
|
231
|
+
r << ?\n * cc_lines
|
|
232
|
+
cc_lines = 0
|
|
151
233
|
|
|
152
|
-
|
|
153
|
-
|
|
234
|
+
state = :text
|
|
235
|
+
skip = true
|
|
236
|
+
when '*'
|
|
154
237
|
|
|
155
|
-
|
|
156
|
-
|
|
238
|
+
;
|
|
239
|
+
else
|
|
157
240
|
|
|
158
|
-
|
|
159
|
-
|
|
241
|
+
state = :c_comment
|
|
242
|
+
end
|
|
243
|
+
else
|
|
160
244
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
end
|
|
164
|
-
when '*'
|
|
245
|
+
if false
|
|
246
|
+
elsif state == :slash_start && ('/' != c && '*' != c)
|
|
165
247
|
|
|
166
|
-
|
|
167
|
-
|
|
248
|
+
state = :text
|
|
249
|
+
r << '/'
|
|
250
|
+
else
|
|
168
251
|
|
|
169
|
-
|
|
170
|
-
|
|
252
|
+
case c
|
|
253
|
+
when '/'
|
|
171
254
|
|
|
172
|
-
|
|
173
|
-
|
|
255
|
+
case state
|
|
256
|
+
when :text
|
|
174
257
|
|
|
175
|
-
|
|
258
|
+
state = :slash_start
|
|
259
|
+
when :slash_start
|
|
176
260
|
|
|
177
|
-
|
|
261
|
+
state = :cpp_comment
|
|
262
|
+
when :c_comment_star
|
|
178
263
|
|
|
179
|
-
|
|
180
|
-
|
|
264
|
+
r << ?\n * cc_lines
|
|
265
|
+
cc_lines = 0
|
|
181
266
|
|
|
182
|
-
|
|
183
|
-
|
|
267
|
+
state = :text
|
|
268
|
+
skip = true
|
|
269
|
+
else
|
|
184
270
|
|
|
185
|
-
|
|
186
|
-
|
|
271
|
+
;
|
|
272
|
+
end
|
|
273
|
+
when '*'
|
|
187
274
|
|
|
188
|
-
|
|
189
|
-
|
|
275
|
+
case state
|
|
276
|
+
when :slash_start
|
|
190
277
|
|
|
191
|
-
|
|
192
|
-
|
|
278
|
+
state = :c_comment
|
|
279
|
+
when :c_comment
|
|
193
280
|
|
|
194
|
-
|
|
195
|
-
|
|
281
|
+
state = :c_comment_star
|
|
282
|
+
else
|
|
196
283
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
when ?\\
|
|
284
|
+
;
|
|
285
|
+
end
|
|
286
|
+
when ?\'
|
|
201
287
|
|
|
202
|
-
|
|
203
|
-
|
|
288
|
+
case state
|
|
289
|
+
when :text
|
|
204
290
|
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
209
|
-
|
|
298
|
+
state = :text
|
|
299
|
+
else
|
|
210
300
|
|
|
211
|
-
|
|
212
|
-
|
|
301
|
+
;
|
|
302
|
+
end
|
|
303
|
+
when '"'
|
|
213
304
|
|
|
214
|
-
|
|
215
|
-
|
|
305
|
+
case state
|
|
306
|
+
when :text
|
|
216
307
|
|
|
217
|
-
|
|
218
|
-
|
|
308
|
+
state = :dq_string
|
|
309
|
+
when :dq_string
|
|
219
310
|
|
|
220
|
-
|
|
221
|
-
|
|
311
|
+
state = :text
|
|
312
|
+
else
|
|
222
313
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
231
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|