Strip block comments: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(34 intermediate revisions by 23 users not shown)
Line 1:
{{task|Text processing}}[[Category:String manipulation]]
[[Category:String manipulation]]
A block comment begins with a ''beginning delimiter'' and ends with a ''ending delimiter'', including the delimiters. These delimiters are often multi-character sequences.
[[Category:Strings]]
 
A block comment begins with a   ''beginning delimiter''   and ends with a   ''ending delimiter'',   including the delimiters.   These delimiters are often multi-character sequences.
 
 
;Task:
Strip block comments from program text (of a programming language much like classic [[C]]).
 
Your demos should at least handle simple, non-nested and multi-line block comment delimiters.
 
The block comment delimiters are the two-character sequences:
:::* &nbsp; &nbsp; <big><big> '''/*''' </big></big> &nbsp; &nbsp; (beginning delimiter)
:::* &nbsp; &nbsp; <big><big> '''*/''' </big></big> &nbsp; &nbsp; (ending delimiter)
 
'''Task:''' Strip block comments from program text (of a programming language much like classic [[C]]). Your demos should at least handle simple, non-nested and multiline block comment delimiters. The beginning delimiter is the two-character sequence “<tt>/*</tt>” and the ending delimiter is “<tt>*/</tt>”.
 
Sample text for stripping:
Line 24 ⟶ 36:
</pre>
 
;Extra credit:
'''Extra credit:''' Ensure that the stripping code is not hard-coded to the particular delimiters described above, but instead allows the caller to specify them. (If your language supports them, [[Optional parameters|optional parameters]] may be useful for this.)
Ensure that the stripping code is not hard-coded to the particular delimiters described above, but instead allows the caller to specify them. &nbsp; (If your language supports them, &nbsp; [[Optional parameters|optional parameters]] &nbsp; may be useful for this.)
 
 
C.f: [[Strip comments from a string]]
{{Template:Strings}}
<br><br>
 
=={{header|11l}}==
<syntaxhighlight lang="11l">F strip_comments(s, b_delim = ‘/*’, e_delim = ‘*/’)
V r = ‘’
V i = 0
L
V? p = s.find(b_delim, i)
I p == N
L.break
r ‘’= s[i .< p]
V? e = s.find(e_delim, p + b_delim.len)
assert(e != N)
i = e + e_delim.len
r ‘’= s[i..]
R r
 
V text = ‘
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}’
 
print(strip_comments(text))</syntaxhighlight>
 
{{out}}
<pre>
 
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
</pre>
 
=={{header|Ada}}==
strip.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Strings.Fixed;
with Ada.Strings.Unbounded;
with Ada.Text_IO;
Line 122 ⟶ 186:
end loop;
Ada.Text_IO.Close (File => File);
end Strip;</langsyntaxhighlight>
output:
<pre>
Line 140 ⟶ 204:
function something() {
}</pre>
 
=={{header|ALGOL W}}==
Handles non-nested block comments, the start and end delimiters are specified as parameters. Comments inside string-literals are retained. The string quote and escape characters are specified as parameters.
<syntaxhighlight lang="algolw">begin
% strips block comments from a source %
% the source is read from standard input and the result written to %
% standard output, The comment start text is in cStart and the ending %
% is in cEnd. %
% As strings are fixed length in Algol W, the first space in cStart/cEnd %
% is assumed to terminate the delimiter, i.e. the comment start/end %
% delimiters cannot contain spaces. %
% If non-blank, quote1 and quote2 are the string quote characters. %
% If escape is non-blank it indicates that quotes can be embedded in %
% string literals by preceding them with escape (as in C, java, etc.). %
procedure stripBlockComments( string(32) value cStart, cEnd
; string(1) value quote1, quote2, escape
) ;
begin
integer columnNumber, lineWidth;
string(256) line;
string(1) currChar;
string(1) newlineChar;
% gets the next source character %
procedure nextChar ;
begin
if columnNumber = lineWidth then begin
currChar := newlineChar;
columnNumber := columnNumber + 1
end
else if columnNumber > lineWidth then begin
readcard( line );
lineWidth := 256;
while lineWidth > 0 and line( lineWidth - 1 // 1 ) = " " do lineWidth := lineWidth - 1;
columnNumber := 1;
currChar := line( 0 // 1 )
end
else begin
currChar := line( columnNumber // 1 );
columnNumber := columnNumber + 1
end
end nextChar ;
% copy the current character and get the next %
procedure copyAndNext ;
begin
if currChar = newlineChar then write()
else writeon( currChar );
nextChar
end copyAndNext ;
% skips the current character and gets the next %
procedure skipAndNext ;
begin
if currChar not = newlineChar then currChar := " ";
copyAndNext
end skipAndNext ;
% handle a string literal %
procedure stringLiteral( string(1) value quote, escape ) ;
begin
copyAndNext;
while currChar not = quote and not XCPNOTED(ENDFILE) do begin
if escape <> " " and currChar = escape then copyAndNext;
if not XCPNOTED(ENDFILE) then copyAndNext
end while_have_more_string ;
if currChar = quote then copyAndNext
end stringLiteral ;
% returns true if the line continues with the specified text %
% false if not. %
logical procedure remainingLineStartsWith ( string(32) value text ) ;
begin
logical haveText;
integer lPos, wPos;
haveText := currChar = text( 0 // 1 );
lPos := columnNumber;
wPos := 1;
while haveText and wPos <= 32 and text( wPos // 1 ) not = " " do begin
if lPos >= lineWidth then begin
% past the end of the line %
haveText := false
end
else begin
% still have text on the line %
haveText := line( lPos // 1 ) = text( wPos // 1 );
wPos := wPos + 1;
lPos := lPos + 1;
end if_past_end_of_line_
end while_have_text_and_more_text ;
haveText
end remainingLineStartsWith ;
% skips the number of leading non-blank characters in the delimiter %
procedure skipDelimiter( string(32) value delimiter ) ;
begin
integer dPos;
dPos := 0;
while dPos < 32 and not XCPNOTED(ENDFILE) and delimiter( dPos // 1 ) not = " " do begin
dPos := dPos + 1;
skipAndNext
end while_not_at_end_of_delimiter
end skipDelimiter ;
newlineChar := code( 10 );
lineWidth := 0;
columnNumber := lineWidth + 1;
currChar := " ";
% allow the program to continue after reaching end-of-file %
ENDFILE := EXCEPTION( false, 1, 0, false, "EOF" );
% get the first source character %
nextChar;
% strip the comments %
while not XCPNOTED(ENDFILE) do begin
if currChar = " " then copyAndNext
else if remainingLineStartsWith( cStart ) then begin
% have a comment %
skipDelimiter( cStart );
while not remainingLineStartsWith( cEnd ) and not XCPNOTED(ENDFILE) do skipAndNext;
skipDelimiter( cEnd )
end
else if currChar = quote1 then stringLiteral( quote1, escape )
else if currChar = quote2 then stringLiteral( quote2, escape )
else copyAndNext
end while_not_at_eof
end stripBlockComments ;
% text stripBlockComments for C-style source %
stripBlockComments( "/*", "*/", """", "'", "\" )
end.</syntaxhighlight>
{{out}}
<pre>
function subroutine() {
a = b + c ;
}
function something() {
}
</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">code =
(
/**
Line 168 ⟶ 373:
closeC:=RegExReplace(closeC,"(\*|\^|\?|\\|\+|\.|\!|\{|\}|\[|\]|\$|\|)","\$0")
;Display final result
MsgBox % sCode := RegExReplace(code,"s)(" . openC . ").*?(" . closeC . ")")</langsyntaxhighlight>
<pre>
 
Line 179 ⟶ 384:
function something() {
}</pre>
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f STRIP_BLOCK_COMMENTS.AWK filename
# source: https://www.gnu.org/software/gawk/manual/gawk.html#Plain-Getline
# Remove text between /* and */, inclusive
{ while ((start = index($0,"/*")) != 0) {
out = substr($0,1,start-1) # leading part of the string
rest = substr($0,start+2) # ... */ ...
while ((end = index(rest,"*/")) == 0) { # is */ in trailing part?
if (getline <= 0) { # get more text
printf("unexpected EOF or error: %s\n",ERRNO) >"/dev/stderr"
exit
}
rest = rest $0 # build up the line using string concatenation
}
rest = substr(rest,end+2) # remove comment
$0 = out rest # build up the output line using string concatenation
}
printf("%s\n",$0)
}
END {
exit(0)
}
</syntaxhighlight>
{{out}}
<pre>
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
 
</pre>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> infile$ = "C:\sample.c"
outfile$ = "C:\stripped.c"
Line 219 ⟶ 461:
CLOSE #infile%
CLOSE #outfile%
ENDPROC</langsyntaxhighlight>
Output file:
<pre>
Line 234 ⟶ 476:
 
=={{header|C}}==
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Line 286 ⟶ 528:
free(s);
return 0;
}</langsyntaxhighlight>
;Usage:
Specify an input file via the first command line argument, and optionally specify comment opening and closing delimiters with the next two args, or defaults of /* and */ are assumed.
Line 302 ⟶ 544:
 
</pre>
 
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">using System;
 
class Program
{
private static string BlockCommentStrip(string commentStart, string commentEnd, string sampleText)
{
while (sampleText.IndexOf(commentStart) > -1 && sampleText.IndexOf(commentEnd, sampleText.IndexOf(commentStart) + commentStart.Length) > -1)
{
int start = sampleText.IndexOf(commentStart);
int end = sampleText.IndexOf(commentEnd, start + commentStart.Length);
sampleText = sampleText.Remove(
start,
(end + commentEnd.Length) - start
);
}
return sampleText;
}
}</syntaxhighlight>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <string>
#include <iostream>
#include <iterator>
Line 327 ⟶ 589:
return 1 ;
}
}</langsyntaxhighlight>
Output:
<pre>
Line 341 ⟶ 603:
}
</pre>
 
=={{header|C sharp|C#}}==
<lang Csharp>using System;
 
class Program
{
private static string BlockCommentStrip(string commentStart, string commentEnd, string sampleText)
{
while (sampleText.IndexOf(commentStart) > -1 && sampleText.IndexOf(commentEnd, sampleText.IndexOf(commentStart) + commentStart.Length) > -1)
{
int start = sampleText.IndexOf(commentStart);
int end = sampleText.IndexOf(commentEnd, start + commentStart.Length);
sampleText = sampleText.Remove(
start,
(end + commentEnd.Length) - start
);
}
return sampleText;
}
}</lang>
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(defn comment-strip [txt & args]
(let [args (conj {:delim ["/*" "*/"]} (apply hash-map args)) ; This is the standard way of doing keyword/optional arguments in Clojure
[opener closer] (:delim args)]
Line 374 ⟶ 616:
(= (apply str hdtxt) closer) (recur out resttxt (dec delim-count))
(= delim-count 0)(recur (str out (first txt)) (rest txt) delim-count)
true (recur out (rest txt) delim-count))))))</langsyntaxhighlight>
<pre>user> (comment-strip "This /* is */ some /* /* /* */ funny */ */ text")
hdtxt= Th resttxt=is /* is */ some /* /* /* */ funny */ */ text out= txt=This /* is */ some /* /* /* */ funny */ */ text delim-count=0
Line 419 ⟶ 661:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.algorithm, std.regex;
 
string[2] separateComments(in string txt,
Line 507 ⟶ 749:
 
showResults(ex2, separateComments(ex2, `#|;`, `[\n\r]|$`));
}</langsyntaxhighlight>
{{out}}
<pre>===Original text:
Line 563 ⟶ 805:
===The stripped comments:
# and bananas; and bananas </pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|C#}}
<syntaxhighlight lang="delphi">
program Strip_block_comments;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils;
 
function BlockCommentStrip(commentStart, commentEnd, sampleText: string): string;
begin
while ((sampleText.IndexOf(commentStart) > -1) and (sampleText.IndexOf(commentEnd,
sampleText.IndexOf(commentStart) + commentStart.Length) > -1)) do
begin
var start := sampleText.IndexOf(commentStart);
var _end := sampleText.IndexOf(commentEnd, start + commentStart.Length);
sampleText := sampleText.Remove(start, (_end + commentEnd.Length) - start);
end;
Result := sampleText;
end;
 
const
test = '/**' + #10 + '* Some comments' + #10 +
'* longer comments here that we can parse.' + #10 + '*' + #10 + '* Rahoo ' +
#10 + '*/' + #10 + 'function subroutine() {' + #10 +
'a = /* inline comment */ b + c ;' + #10 + '}' + #10 +
'/*/ <-- tricky comments */' + #10 + '' + #10 + '/**' + #10 +
'* Another comment.' + #10 + '*/' + #10 + 'function something() {' + #10 + '}';
 
begin
 
writeln(BlockCommentStrip('/*', '*/', test));
readln;
end.</syntaxhighlight>
{{out}}
<pre>
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="easylang">
subr process
i = 1
while i <= len s$
if inc = 0 and substr s$ i 2 = "/*"
inc = 1
i += 1
elif inc = 1 and substr s$ i 2 = "*/"
inc = 0
i += 1
elif inc = 0
write substr s$ i 1
.
i += 1
.
if inc = 0
print ""
.
.
repeat
s$ = input
until error = 1
process
.
input_data
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
</syntaxhighlight>
 
 
=={{header|F_Sharp|F#}}==
Using .NET's regex counter feature to match nested comments.
If comments here are nested, they have to be correctly balanced.
<syntaxhighlight lang="fsharp">open System
open System.Text.RegularExpressions
 
let balancedComments opening closing =
new Regex(
String.Format("""
{0} # An outer opening delimiter
(?> # efficiency: no backtracking here
{0} (?<LEVEL>) # An opening delimiter, one level down
|
{1} (?<-LEVEL>) # A closing delimiter, one level up
|
(?! {0} | {1} ) . # With negative lookahead: Anything but delimiters
)* # As many times as we see these
(?(LEVEL)(?!)) # Fail, unless on level 0 here
{1} # Outer closing delimiter
""", Regex.Escape(opening), Regex.Escape(closing)),
RegexOptions.IgnorePatternWhitespace ||| RegexOptions.Singleline)
 
[<EntryPoint>]
let main args =
let sample = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
* /* nested balanced
*/ */
function something() {
}
"""
let balancedC = balancedComments "/*" "*/"
printfn "%s" (balancedC.Replace(sample, ""))
0</syntaxhighlight>
Output
<pre>
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
</pre>
 
=={{header|Factor}}==
===Regexp implementation===
<syntaxhighlight lang="factor">
: strip-block-comments ( string -- string )
R/ /\*.*?\*\// "" re-replace ;
</syntaxhighlight>
===Manual implementation===
<syntaxhighlight lang="factor">
USING: kernel io accessors strings math sequences locals
io.streams.string multiline prettyprint ;
 
IN: strip-block-comments
 
TUPLE: comment-state
{ is-in-comment initial: f }
{ delim-start string initial: "/*" }
{ delim-end string initial: "*/" }
{ chars-matched integer initial: 0 } ;
 
: set-delims ( cmnt-st start end -- cmnt-st )
[ >>delim-start ] dip
>>delim-end ;
 
: target-delim ( cmnt-st -- string )
dup is-in-comment>>
[ delim-end>> ]
[ delim-start>> ] if ;
 
: target-char ( cmnt-st -- ch )
dup chars-matched>> swap ! ( cmnt-st -- n cmnt-st )
target-delim nth ;
 
: got-delim? ( cmnt-st -- ? )
[ target-delim length ] keep
chars-matched>> <= ;
 
: update-is-in-comment ( cmnt-st -- cmnt-st )
dup got-delim?
[ [ not ] change-is-in-comment 0 >>chars-matched ]
when ;
 
: matched-chars ( cmnt-st -- string )
[ target-delim ] [ chars-matched>> ] bi
0 swap rot <slice> ;
 
:: process-char ( cmnt-st ch -- cmnt-st )
cmnt-st update-is-in-comment
target-char ch =
[
cmnt-st [ 1 + ] change-chars-matched
update-is-in-comment
]
[
cmnt-st is-in-comment>>
[ cmnt-st matched-chars >string write ch write1 ] unless
cmnt-st
] if ;
 
: process-string ( cmnt-st string -- cmnt-st )
[ process-char ] each ;
 
: strip-block-comments ( string -- string )
[ comment-state new swap process-string drop ]
with-string-writer ;
 
: strip-block-comments-with-delims ( string start end -- string )
[ comment-state new -rot set-delims swap process-string drop ] with-string-writer ;
 
CONSTANT: sample-text [[
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
]]
 
: test-strip-block-comments ( -- )
sample-text strip-block-comments write
"foo(bar)" "(" ")" strip-block-comments-with-delims "foo" assert= ;
 
MAIN: test-strip-block-comments
</syntaxhighlight>
 
=={{header|Fortran}}==
Line 578 ⟶ 1,063:
A feature of Fortran's character comparison is that trailing spaces are ignored, so that "x " and "x " and "x" are all deemed equal. Unfortunate choices of starting and ending delimiter texts can be made if they contain characters in common.
 
<syntaxhighlight lang="fortran">
<lang Fortran>
SUBROUTINE UNBLOCK(THIS,THAT) !Removes block comments bounded by THIS and THAT.
Copies from file INF to file OUT, record by record, except skipping null output records.
Line 662 ⟶ 1,147:
 
END !All open files are closed on exit..
</syntaxhighlight>
</lang>
 
Output: the report is "16 read, 8 written." And in the output file appears...
Line 697 ⟶ 1,182:
F90 allows the syntax END SUBROUTINE UNBLOCK (and insists on it within a MODULE) but F77 does not, otherwise the statement could have been <code>CALL UNBLOCK("SUBROUTINE","END SUBROUTINE")</code> which would be rather more structured.
 
=={{header|F_Sharp|F#}}==
Using .NET's regex counter feature to match nested comments.
If comments here are nested, they have to be correctly balanced.
<lang fsharp>open System
open System.Text.RegularExpressions
 
=={{header|FreeBASIC}}==
let balancedComments opening closing =
{{trans|Liberty BASIC}}
new Regex(
<syntaxhighlight lang="freebasic">Const CRLF = Chr(13) + Chr(10)
String.Format("""
{0} # An outer opening delimiter
(?> # efficiency: no backtracking here
{0} (?<LEVEL>) # An opening delimiter, one level down
|
{1} (?<-LEVEL>) # A closing delimiter, one level up
|
(?! {0} | {1} ) . # With negative lookahead: Anything but delimiters
)* # As many times as we see these
(?(LEVEL)(?!)) # Fail, unless on level 0 here
{1} # Outer closing delimiter
""", Regex.Escape(opening), Regex.Escape(closing)),
RegexOptions.IgnorePatternWhitespace ||| RegexOptions.Singleline)
 
Function stripBlocks(text As String, first As String, last As String) As String
[<EntryPoint>]
Dim As String temp = ""
let main args =
For i As Integer = 1 To Len(text) - Len(first)
let sample = """
If Mid(text, i, Len(first)) = first Then
/**
i += Len(first)
* Some comments
* longer comments here that we can parse. Do
If Mid(text, i, 2) = CRLF Then temp &= CRLF
*
* Rahoo i += 1
Loop Until (Mid(text, i, Len(last)) = last) Or (i = Len(text) - Len(last))
*/
function subroutine i += Len(last) {-1
a = /* inline comment */ b + c ;Else
temp &= Mid(text, i, 1)
}
/*/ <-- tricky comments */End If
Next i
Return temp
End Function
 
Dim As String source
/**
source = " /**" + CRLF + _
* Another comment.
" * Some comments" + CRLF + _
* /* nested balanced
" * longer comments here that we can parse." + CRLF + _
*/ */
" *" + CRLF + _
function something() {
" * Rahoo " + CRLF + _
}
" */"" + CRLF + _
" function subroutine() {" + CRLF + _
let balancedC = balancedComments "/*" "*/"
" a = /* inline comment */ b + c ;" + CRLF + _
printfn "%s" (balancedC.Replace(sample, ""))
" }" + CRLF + _
0</lang>
" /*/ <-- tricky comments */" + CRLF + _
Output
"" + CRLF + _
" /**" + CRLF + _
" * Another comment." + CRLF + _
" */" + CRLF + _
" function something() {" + CRLF + _
" }" + CRLF
 
Print stripBlocks(source, "/*", "*/")
Sleep</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de Liberty BASIC.
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
</pre>
 
=={{header|Go}}==
For the extra credit: No optional parameters in Go, but documented below is an efficient technique for letting the caller specify the delimiters.
<langsyntaxhighlight lang="go">package main
 
import (
Line 811 ⟶ 1,284:
function something() {
}`))
}</langsyntaxhighlight>
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def code = """
/**
* Some comments
Line 833 ⟶ 1,306:
"""
 
println ((code =~ "(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)").replaceAll(''))</langsyntaxhighlight>
 
=={{header|Haskell}}==
THE FOLLOWING SOLUTION IS WRONG, as it does not take string literals into account. For example:
<langsyntaxhighlight Haskelllang="haskell">test = "This {- is not the beginning of a block comment" -- Do your homework properly -}</langsyntaxhighlight>
Comment delimiters can be changed by calling stripComments with different start and end parameters.
<langsyntaxhighlight Haskelllang="haskell">import Data.List
 
stripComments :: String -> String -> String -> String
Line 854 ⟶ 1,327:
| otherwise = inComment $ tail xs
 
main = interact (stripComments "/*" "*/")</langsyntaxhighlight>
Output:
<pre>
Line 870 ⟶ 1,343:
=={{header|Icon}} and {{header|Unicon}}==
If one is willing to concede that the program file will fit in memory, then the following code works:
<langsyntaxhighlight Iconlang="icon">procedure main()
every (unstripped := "") ||:= !&input || "\n" # Load file as one string
write(stripBlockComment(unstripped,"/*","*/"))
Line 885 ⟶ 1,358:
return result || tab(0)
}
end</langsyntaxhighlight>
Otherwise, the following handles an arbitrary length input:
<langsyntaxhighlight Iconlang="icon">procedure main()
every writes(stripBlockComment(!&input,"/*","*/"))
end
Line 900 ⟶ 1,373:
else fail
}
end</langsyntaxhighlight>
 
=={{header|J}}==
<langsyntaxhighlight lang="j">strip=:#~1 0 _1*./@:(|."0 1)2>4{"1(5;(0,"0~".;._2]0 :0);'/*'i.a.)&;:
1 0 0
0 2 0
2 3 2
0 2 2
)</langsyntaxhighlight>
Example data:
<langsyntaxhighlight lang="j">example=: 0 :0
/**
* Some comments
Line 927 ⟶ 1,400:
function something() {
}
)</langsyntaxhighlight>
Example use:
<langsyntaxhighlight lang="j"> strip example
function subroutine() {
Line 938 ⟶ 1,411:
function something() {
}</langsyntaxhighlight>
Here is a version which allows the delimiters to be passed as an optional left argument as a pair of strings:
<langsyntaxhighlight lang="j">stripp=:3 :0
('/*';'*/') stripp y
:
Line 946 ⟶ 1,419:
marks=. (+./(-i._1+#open,close)|."0 1 open E. y) - close E.&.|. y
y #~ -. (+._1&|.) (1 <. 0 >. +)/\.&.|. marks
)</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.io.*;
 
public class StripBlockComments{
Line 998 ⟶ 1,471:
}
}
}</langsyntaxhighlight>
 
=={{header|jq}}==
Line 1,004 ⟶ 1,477:
 
The filter <tt>strip_block_comments/2</tt> as defined here does not attempt to recognize comments-within-comments.
<langsyntaxhighlight lang="jq">def strip_block_comments(open; close):
def deregex:
reduce ("\\\\", "\\*", "\\^", "\\?", "\\+", "\\.",
Line 1,012 ⟶ 1,485:
gsub( (open|deregex) + ".*?" + (close|deregex); ""; "m") ;
 
strip_block_comments("/*"; "*/")</langsyntaxhighlight>
'''Invocation''':
$ jq -s -R -r -f Strip_block_comments.jq sample_text_for_stripping.txt
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
{{trans|Python}}
<syntaxhighlight lang="julia">function _stripcomments(txt::AbstractString, dlm::Tuple{String,String})
"Strips first nest of block comments"
 
dlml, dlmr = dlm
indx = searchindex(txt, dlml)
if indx > 0
out = IOBuffer()
write(out, txt[1:indx-1])
txt = txt[indx+length(dlml):end]
txt = _stripcomments(txt, dlm)
indx = searchindex(txt, dlmr)
@assert(indx > 0, "cannot find a closer delimiter \"$dlmr\" in $txt")
write(out, txt[indx+length(dlmr):end])
else
out = txt
end
return String(out)
end
 
function stripcomments(txt::AbstractString, dlm::Tuple{String,String}=("/*", "*/"))
"Strips nests of block comments"
 
dlml, dlmr = dlm
while contains(txt, dlml)
txt = _stripcomments(txt, dlm)
end
 
return txt
end
 
function main()
println("\nNON-NESTED BLOCK COMMENT EXAMPLE:")
smpl = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
"""
println(stripcomments(smpl))
 
println("\nNESTED BLOCK COMMENT EXAMPLE:")
smpl = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*//*
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
*/
/**
* Another comment.
*/
function something() {
}
"""
println(stripcomments(smpl))
end
 
main()</syntaxhighlight>
 
{{out}}
<pre>
NON-NESTED BLOCK COMMENT EXAMPLE:
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
 
 
NESTED BLOCK COMMENT EXAMPLE:
 
 
function something() {
}
</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">// version 1.1.4-3
 
val sample = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
"""
 
val sample2 = """
``{
` Some comments
` longer comments here that we can parse.
`
` Rahoo
``}
function subroutine2() {
d = ``{ inline comment ``} e + f ;
}
``{ / <-- tricky comments ``}
 
``{
` Another comment.
``}
function something2() {
}
"""
 
fun stripBlockComments(text: String, del1: String = "/*", del2: String = "*/"): String {
val d1 = Regex.escape(del1)
val d2 = Regex.escape(del2)
val r = Regex("""(?s)$d1.*?$d2""")
return text.replace(r, "")
}
 
fun main(args: Array<String>) {
println(stripBlockComments(sample))
println(stripBlockComments(sample2, "``{", "``}"))
}</syntaxhighlight>
 
{{out}}
<pre>
 
function subroutine() {
a = b + c ;
}
 
function something() {
}
 
 
 
function subroutine2() {
d = e + f ;
}
 
function something2() {
}
 
</pre>
 
=={{header|Ksh}}==
<syntaxhighlight lang="ksh">
#!/bin/ksh
 
# Strip block comments
 
# # Variables:
#
bd=${1:-'/*'}
ed=${2:-'*/'}
 
testcase='/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
/**
* Another comment.
*/
function something() {
}'
 
######
# main #
######
 
testcase=${testcase%%"${bd}"*}
while [[ -n ${.sh.match} ]]; do # .sh.match stores the most recent match
if [[ -n ${testcase} ]]; then
sm="${.sh.match}"
sm="${sm/"${bd}"/}"
buff="${testcase}"
buff+="${sm#*"${ed}"}"
testcase="${buff}"
else
testcase="${.sh.match}"
testcase="${testcase#*"${ed}"}"
fi
testcase=${testcase%%"${bd}"*}
done
 
echo "${testcase}"
</syntaxhighlight>
{{out}}<pre>
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
</pre>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">global CRLF$
CRLF$ =chr$( 13) +chr$( 10)
 
Line 1,061 ⟶ 1,773:
end if
next i
end function</langsyntaxhighlight>
<pre>
 
Line 1,084 ⟶ 1,796:
=={{header|Lua}}==
It is assumed, that the code is in the file "Text1.txt".
<langsyntaxhighlight lang="lua">filename = "Text1.txt"
 
fp = io.open( filename, "r" )
Line 1,091 ⟶ 1,803:
 
stripped = string.gsub( str, "/%*.-%*/", "" )
print( stripped )</langsyntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">StringReplace[a,"/*"~~Shortest[___]~~"*/" -> ""]
 
->
Line 1,104 ⟶ 1,816:
function something() {
}</langsyntaxhighlight>
 
=={{header|MATLAB}} / {{header|Octave}}==
<langsyntaxhighlight Matlablang="matlab">function str = stripblockcomment(str,startmarker,endmarker)
while(1)
ix1 = strfind(str, startmarker);
Line 1,119 ⟶ 1,831:
end;
end;
end;</langsyntaxhighlight>
Output:
<pre>
Line 1,158 ⟶ 1,870:
=={{header|Nim}}==
{{trans|Python}}
<langsyntaxhighlight lang="nim">import strutils
 
proc commentStripper(txt: string; delim: tuple[l, r: string] = ("/*", "*/")): string =
let i = txt.find(delim.l)
if i < 0: return txt
return txt
 
result = if i > 0: txt[0 .. < i] else: ""
let tmp = commentStripper(txt[i+delim.l.len .. txt.high], delim)
let j = tmp.find(delim.r)
assert j >= 0
Line 1,205 ⟶ 1,916:
*/
function something() {
}""")</langsyntaxhighlight>
 
Output:
{{out}}
<pre>NON-NESTED BLOCK COMMENT EXAMPLE:
 
Line 1,225 ⟶ 1,937:
 
=={{header|Perl}}==
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl -w
use strict ;
use warnings ;
Line 1,237 ⟶ 1,949:
close FH ;
$code =~ s,/\*.*?\*/,,sg ;
print $code . "\n" ;</langsyntaxhighlight>
Output:
<pre>
Line 1,250 ⟶ 1,962:
</pre>
 
=={{header|Perl 6Phix}}==
Note that Phix itself supports nested block comments, which this simple approach will not handle properly - see ptok.e/SkipBlockComment() and/or pwa/src/p2js_tok.e/block_comment(), which both use a slightly more convoluted and recursive but also more precise character-by-character method.
<lang perl6>sample().split(/ '/*' .+? '*/' /).print;
<!--<syntaxhighlight lang="phix">(phixonline)-->
 
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
sub sample {
<span style="color: #008080;">constant</span> <span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
' /**
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <&lt;-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
'} """</langspan>
Output:
<span style="color: #008080;">function</span> <span style="color: #000000;">strip_comments</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">startc</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"/*"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">endc</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"*/"</span><span style="color: #0000FF;">)</span>
<pre>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
function subroutine() {
<span style="color: #004080;">integer</span> <span style="color: #000000;">startp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">startc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">text</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">endp</span>
a = b + c ;
<span style="color: #008080;">if</span> <span style="color: #000000;">startp</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
}
<span style="color: #000000;">endp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">endc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #000000;">startp</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">startc</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">endp</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"error"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">startp</span><span style="color: #0000FF;">..</span><span style="color: #000000;">endp</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">endc</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">text</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">strip_comments</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
 
function something() {
}
</pre>
 
=={{header|Phix}}==
<lang Phix>constant test = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
 
/**
 
* Another comment.
*/
function something() {
}
</pre>
"""
 
=={{header|PHP}}==
function strip_comments(string text, startc="/*", endc="*/")
<syntaxhighlight lang="php">
while 1 do
function strip_block_comments( $test_string ) {
integer startp = match(startc,text)
$pattern = "/^.*?(\K\/\*.*?\*\/)|^.*?(\K\/\*.*?^.*\*\/)$/mXus";
if startp=0 then exit end if
return preg_replace( $pattern, '', $test_string );
integer endp = match(endc,text,startp+length(startc))
}
if endp=0 then
 
puts(1,"error, aborting...")
echo "Result: '" . strip_block_comments( "
abort(0)
/**
end if
* Some comments
text[startp..endp+length(endc)-1] = ""
* longer comments here that we can parse.
end while
*
return text
* Rahoo
end function
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
" ) . "'";
</syntaxhighlight>
 
puts(1,strip_comments(test))</lang>
{{out}}
<pre>
Result: '
 
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
'
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(in "sample.txt"
(while (echo "/*")
(out "/dev/null" (echo "*/")) ) )</langsyntaxhighlight>
Output:
<pre>
Line 1,348 ⟶ 2,070:
 
=={{header|PL/I}}==
<langsyntaxhighlight PLlang="pl/Ii">/* A program to remove comments from text. */
strip: procedure options (main); /* 8/1/2011 */
declare text character (80) varying;
Line 1,381 ⟶ 2,103:
end;
 
end strip;</langsyntaxhighlight>
 
=={{header|Prolog}}==
 
Prolog enables grammar rules via the DCG that are ideally suited for this task .
 
<syntaxhighlight lang="prolog">
 
:- system:set_prolog_flag(double_quotes,codes) .
 
strip_block_comments(INPUTz)
:-
strip_block_comments(INPUTz,OUTPUTz) ,
system:format("```~n",[OUTPUTz]) ,
system:format("~s~n",[OUTPUTz]) ,
system:format("```~n",[OUTPUTz])
.
 
strip_block_comments(INPUTz,OUTPUTz)
:-
prolog:phrase(block(OUTPUTz),INPUTz)
.
 
block([]) --> \+ [_] , ! .
block([CODE|OUTPUTz]) --> \+ comment , ! , [CODE] , block(OUTPUTz) .
block(OUTPUTz) --> comment , ! , block(OUTPUTz) .
 
comment --> comment_entr , zero_or_more(comment_each) , comment_exit .
comment_entr --> "/*" .
comment_each --> comment , ! .
comment_each --> \+ comment_exit , ! , [_] .
comment_exit --> "*/" .
 
zero_or_more(CALLABLE) --> call(CALLABLE) , ! , zero_or_more(CALLABLE) .
zero_or_more(_) --> ! .
 
</syntaxhighlight>
 
{{out}}
<pre>
/*
?- strip_block_comments(
"
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
").
```
 
 
function subroutine() {
a = b + c ;
}
 
function something() {
}
 
```
true .
 
?-
*/
 
/*
?- strip_block_comments("abc/*p/*q*/r*/def") .
```
abcdef
```
true .
 
?- strip_block_comments("abcdef") .
```
abcdef
```
true .
 
</pre>
 
=={{header|PureBasic}}==
Solution using regular expressions. A procedure to stripBlocks() procedure is defined that will strip comments between any two delimeters.
<langsyntaxhighlight PureBasiclang="purebasic">Procedure.s escapeChars(text.s)
Static specialChars.s = "[\^$.|?*+()"
Protected output.s, nextChar.s, i, countChar = Len(text)
Line 1,435 ⟶ 2,248:
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf</langsyntaxhighlight>
Sample output:
<pre>--- source ---
Line 1,479 ⟶ 2,292:
=={{header|Python}}==
The code has comment delimeters as an argument and will also strip ''nested'' block comments.
<langsyntaxhighlight lang="python">def _commentstripper(txt, delim):
'Strips first nest of block comments'
Line 1,502 ⟶ 2,315:
while deliml in txt:
txt = _commentstripper(txt, delim)
return txt</langsyntaxhighlight>
;Tests and sample output
<langsyntaxhighlight lang="python">def test():
print('\nNON-NESTED BLOCK COMMENT EXAMPLE:')
sample = ''' /**
Line 1,544 ⟶ 2,357:
if __name__ == '__main__':
test()</langsyntaxhighlight>
 
<pre>
Line 1,566 ⟶ 2,379:
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang at-exp racket
 
Line 1,595 ⟶ 2,408:
}
})
</syntaxhighlight>
</lang>
 
(Outputs the expected text...)
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>sample().split(/ '/*' .+? '*/' /).print;
 
sub sample {
' /**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
'}</syntaxhighlight>
Output:
<pre>
function subroutine() {
a = b + c ;
}
 
function something() {
}
</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/* REXX ***************************************************************
* Split comments
* This program ignores comment delimiters within literal strings
Line 1,698 ⟶ 2,545:
 
oc: Return lineout(oic,oc)
op: Return lineout(oip,op)</langsyntaxhighlight>
Input:
<pre>
Line 1,760 ⟶ 2,607:
</pre>
 
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
example = "123/*456*/abc/*def*/789"
Line 1,777 ⟶ 2,623:
end
see example2 + nl
</syntaxhighlight>
</lang>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def remove_comments!(str, comment_start='/*', comment_end='*/')
while start_idx = str.index(comment_start)
end_idx = str.index(comment_end, start_idx + comment_start.length) + comment_end.length - 1
Line 1,811 ⟶ 2,657:
END_OF_STRING
 
puts remove_comments example</langsyntaxhighlight>
outputs
<pre>
Line 1,822 ⟶ 2,668:
function something() {
}</pre>
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">import java.util.regex.Pattern.quote
def strip1(x: String, s: String = "/*", e: String = "*/") =
x.replaceAll("(?s)"+quote(s)+".*?"+quote(e), "")</langsyntaxhighlight>
<langsyntaxhighlight Scalalang="scala">def strip2(x: String, s: String = "/*", e: String = "*/"): String = {
val a = x indexOf s
val b = x indexOf (e, a + s.length)
if (a == -1 || b == -1) x
else strip2(x.take(a) + x.drop(b + e.length), s, e)
}</langsyntaxhighlight>
<langsyntaxhighlight Scalalang="scala">def strip3(x: String, s: String = "/*", e: String = "*/"): String = x.indexOf(s) match {
case -1 => x
case i => x.indexOf(e, i + s.length) match {
Line 1,838 ⟶ 2,685:
case j => strip2(x.take(i) + x.drop(j + e.length), s, e)
}
}</langsyntaxhighlight>
 
=={{header|Seed7}}==
Line 1,844 ⟶ 2,691:
can be used to replace unnested comments.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const proc: main is func
Line 1,867 ⟶ 2,714:
begin
writeln(replace2(stri, "/*", "*/", " "));
end func;</langsyntaxhighlight>
Output:
<pre>
Line 1,883 ⟶ 2,730:
=={{header|Sidef}}==
For extra credit, it allows the caller to redefine the delimiters.
<langsyntaxhighlight lang="ruby">func strip_block_comments(code, beg='/*', end='*/') {
var re = Regex.new(beg.escape + '.*?' + end.escape, 's');
code.gsub(re, '');
}
 
say strip_block_comments(ARGF.slurp);</langsyntaxhighlight>
 
=={{header|SNOBOL4}}==
{{works with|SNOBOL4, SPITBOL for Linux}}
<syntaxhighlight lang="snobol4">
* Program: strip_block_comments.sbl
* To run: sbl -r extract_extension.sbl
* Description: Strip block comments.
* Can use different begin and end delimiters.
* Handles comment nesting and unmatched end delimiters.
* Unmatched begin delimiters remove text to end of file.
* Does not handle quoted delimiters.
* Most null lines are removed, which may not be
* what is desired.
* Comment: Tested using the Spitbol for Linux version of SNOBOL4
 
 
* Function strip_block_comments will read a file, or the text after
* the END statement below. Parameter bcom is the beginning comment
* string and parameter ecom is the ending comment string.
*
define('strip_block_comments(bcom,ecom)break_chars,c,newc,pre,pc,b')
pat1 = breakx(*break_chars) . pre (*bcom | *gt(b,0) *ecom) . pc
:(strip_block_comments_end)
strip_block_comments
break_chars = substr(bcom,1,1) substr(ecom,1,1)
newc = ""
b = 0
in1
c = input :f(p60)
 
p10
c ? pat1 = "" :f(p20)
 
* matches
le(b,0) :s(leb)f(gtb)
leb
b = leq(pc,bcom) b + 1 :f(leb2)
newc = newc pre :(p10)
leb2
b = leq(pc,ecom) b - 1 :f(error)
:(p10)
gtb
b = leq(pc,bcom) b + 1
b = leq(pc,ecom) b - 1
:(p10)
 
* nomatches
p20
newc = lt(b,1) newc c
ident(newc) :s(in1)
:(p50)
 
p50
output = newc
newc = "" :(in1)
 
p60
output = differ(newc) newc
:(return)
strip_block_comments_end
 
 
* Set "begin" comment delimiter (bcom) and "end" comment delimiter (ecom) below
bcom = "/*"
ecom = "*/"
* bcom = "{{*"
* ecom = "?/"
 
* Strip block comments from the text lines after the END statement
strip_block_comments(bcom,ecom)
 
END
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
 
----------------------------------------------
With nested comments/* Nested /* comment*/s*/*/!
Unmatched"/*" end delimiters simply remove
to end of file
</syntaxhighlight>
{{out}}
<pre>
function subroutine() {
a = b + c ;
}
function something() {
}
----------------------------------------------
With nested comments*/!
Unmatched"
</pre>
 
=={{header|Swift}}==
 
<syntaxhighlight lang="swift">import Foundation
 
func stripBlocks(from str: String, open: String = "/*", close: String = "*/") -> String {
guard !open.isEmpty && !close.isEmpty else {
return str
}
 
var ret = str
 
while let begin = ret.range(of: open), let end = ret[begin.upperBound...].range(of: close) {
ret.replaceSubrange(Range(uncheckedBounds: (begin.lowerBound, end.upperBound)), with: "")
}
 
return ret
}
 
let test = """
/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}
"""
 
print(stripBlocks(from: test))</syntaxhighlight>
 
{{out}}
 
<pre>
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}
 
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc stripBlockComment {string {openDelimiter "/*"} {closeDelimiter "*/"}} {
# Convert the delimiters to REs by backslashing all non-alnum characters
set openAsRE [regsub -all {\W} $openDelimiter {\\&}]
Line 1,898 ⟶ 2,905:
# Now remove the blocks using a dynamic non-greedy regular expression
regsub -all "$openAsRE.*?$closeAsRE" $string ""
}</langsyntaxhighlight>
Demonstration code:
<langsyntaxhighlight lang="tcl">puts [stripBlockComment " /**
* Some comments
* longer comments here that we can parse.
Line 1,916 ⟶ 2,923:
function something() {
}
"]</langsyntaxhighlight>
Output:
<pre>
Line 1,930 ⟶ 2,937:
 
</pre>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE DATA
$$ script=*
Line 1,969 ⟶ 2,977:
d=FILE("destfile")
TRACE *d
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,981 ⟶ 2,989:
</pre>
 
=={{header|zklVBA}}==
Stripping block comments might look easy ...
<lang zkl>fcn stripper(text,a="/*",b="*/"){
<syntaxhighlight lang="vb">'strip block comment NESTED comments
while(xy:=text.span(a,b,True)){ x,y:=xy; text=text[0,x]+text[x+y,*]}
'multi line comments
text
'and what if there are string literals with these delimeters?
}</lang>
'------------------------
The span method takes two tokens and matches the shortest or longest balanced match (if True). It assumes there are no escape characters (such as \ or ""). So we just repeatedly strip out the longest balanced comments until there aren't any left (span returns the empty list). If a comment was unbalanced, span would fail but this code doesn't check that and just assumes no more matches.
'delimeters for Block Comment can be specified, exactly two characters each
'Three states: Block_Comment, String_Literal, Other_Text
'Globals:
Dim t As String 'target string
Dim s() As Byte 'source array
Dim j As Integer 'index into the source string s, converted to byte array
Dim SourceLength As Integer 'of a base 0 array, so last byte is SourceLength - 1
Dim flag As Boolean
Private Sub Block_Comment(sOpBC As String, sClBC As String)
'inside a block comment, expecting close block comment delimeter
flag = False
Do While j < SourceLength - 2
Select Case s(j)
Case Asc(Left(sOpBC, 1))
If s(j + 1) = Asc(Right(sOpBC, 1)) Then
'open block NESTED comment delimeter found
j = j + 2
Block_Comment sOpBC, sClBC
End If
Case Asc(Left(sClBC, 1))
If s(j + 1) = Asc(Right(sClBC, 1)) Then
'close block comment delimeter found
flag = True
j = j + 2
Exit Do
End If
'just a lone star
Case Else
End Select
j = j + 1
Loop
If Not flag Then MsgBox "Error, missing close block comment delimeter"
End Sub
Private Sub String_Literal()
'inside as string literal, expecting double quote as delimeter
flag = False
Do While j < SourceLength - 2
If s(j) = Asc("""") Then
If s(j + 1) = Asc("""") Then
'found a double quote within a string literal
t = t + Chr(s(j))
j = j + 1
Else
'close string literal delimeter found
flag = True
t = t + Chr(s(j))
j = j + 1
Exit Do
End If
End If
t = t + Chr(s(j))
j = j + 1
Loop
If Not flag Then MsgBox "Error, missing closing string delimeter"
End Sub
Private Sub Other_Text(Optional sOpBC As String = "/*", Optional sClBC As String = "*/")
If Len(sOpBC) <> 2 Then
MsgBox "Error, open block comment delimeter must be 2" & _
" characters long, got " & Len(sOpBC) & " characters"
Exit Sub
End If
If Len(sClBC) <> 2 Then
MsgBox "Error, close block comment delimeter must be 2" & _
" characters long, got " & Len(sClBC) & " characters"
Exit Sub
End If
Do While j < SourceLength - 1
Select Case s(j)
Case Asc(""""):
t = t + Chr(s(j))
j = j + 1
String_Literal
Case Asc(Left(sOpBC, 1))
If s(j + 1) = Asc(Right(sOpBC, 1)) Then
'open block comment delimeter found
j = j + 2
Block_Comment sOpBC, sClBC
Else
t = t + Chr(s(j))
j = j + 1
End If
Case Else
t = t + Chr(s(j))
j = j + 1
End Select
Loop
If j = SourceLength - 1 Then t = t + Chr(s(j))
End Sub
Public Sub strip_block_comment()
Dim n As String
n = n & "/**" & vbCrLf
n = n & "* Some comments /*NESTED COMMENT*/" & vbCrLf
n = n & "* longer comments here that we can parse." & vbCrLf
n = n & "*" & vbCrLf
n = n & "* Rahoo" & vbCrLf
n = n & "*/" & vbCrLf
n = n & "mystring = ""This is the """"/*"""" open comment block mark.""" & vbCrLf
'VBA converts two double quotes in a row within a string literal to a single double quote
'see the output below. Quadruple double quotes become two double quotes within the string
'to represent a single double quote within a string.
n = n & "function subroutine() {" & vbCrLf
n = n & "a = /* inline comment */ b + c ;" & vbCrLf
n = n & "}" & vbCrLf
n = n & "/*/ <-- tricky /*NESTED*/ comments */" & vbCrLf
n = n & "" & vbCrLf
n = n & "/**" & vbCrLf
n = n & "* Another comment." & vbCrLf
n = n & "*/" & vbCrLf
n = n & "function something() {" & vbCrLf
n = n & "}"
s = StrConv(n, vbFromUnicode)
j = 0
t = ""
SourceLength = Len(n)
Other_Text 'The open and close delimeters for block comment are optional ;)
Debug.Print "Original text:"
Debug.Print String$(60, "-")
Debug.Print n & vbCrLf
Debug.Print "Text after deleting comment blocks, preserving string literals:"
Debug.Print String$(60, "-")
Debug.Print t
End Sub</syntaxhighlight>{{out}}<pre>Original text:
------------------------------------------------------------
/**
* Some comments /*NESTED COMMENT*/
* longer comments here that we can parse.
*
* Rahoo
*/
mystring = "This is the ""/*"" open comment block mark."
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky /*NESTED*/ comments */
 
/**
* Another comment.
*/
function something() {
}
 
Text after deleting comment blocks, preserving string literals:
------------------------------------------------------------
 
mystring = "This is the ""/*"" open comment block mark."
function subroutine() {
a = b + c ;
}
 
 
 
function something() {
}</pre>
 
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="wren">var stripper = Fn.new { |start, end|
if (start == "" || end == "") {
start = "/*"
end = "*/"
}
return Fn.new { |source|
while (true) {
var cs = source.indexOf(start)
if (cs == -1) break
var ce = source[cs+2..-1].indexOf(end)
if (ce == -1) break
source = source[0...cs] + source[cs+ce+4..-1]
}
return source
}
}
 
var source = "/**
* Some comments
* longer comments here that we can parse.
*
* Rahoo
*/
function subroutine() {
a = /* inline comment */ b + c ;
}
/*/ <-- tricky comments */
 
/**
* Another comment.
*/
function something() {
}"
 
var stripC = stripper.call("", "")
System.print(stripC.call(source))</syntaxhighlight>
 
{{out}}
<pre>
 
function subroutine() {
a = b + c ;
}
 
function something() {
}
</pre>
 
=={{header|XProfan}}==
<syntaxhighlight lang="xprofan">Proc strip_block_comments
Parameters string inhalt, beg_delim, end_delim
Declare long start, ende, anzahl
start = 1
start = InStr(beg_delim, inhalt, start)
While start > 0
ende = InStr(end_delim, inhalt, start + len(beg_delim))
If ende > 0
anzahl = ende + + len(end_delim) - start
inhalt = Del$(inhalt, start, anzahl)
Else
BREAK
EndIf
start = InStr(beg_delim, inhalt, start)
EndWhile
Return inhalt
EndProc
 
Cls
Declare string Text
Text = BlockRead("C:\Temp\Multiline_comment.txt")
Text = strip_block_comments(Text, "/*", "*/")
Print "Output:"
Print Text
WaitKey
End</syntaxhighlight>
{{out}}
The input is in a file because I'm too lazy to type it in:
<pre>
stripper(File("text.txt").read().text);
function subroutine() {
Line 2,001 ⟶ 3,240:
}
 
</pre>
 
=={{header|zkl}}==
<syntaxhighlight lang="zkl">fcn stripper(text, a="/*", b="*/"){
while(xy:=text.span(a,b,True)){ x,y:=xy; text=text[0,x] + text[x+y,*] }
text
}</syntaxhighlight>
The span method takes two tokens and matches the shortest or longest balanced match (if True). It assumes there are no escape characters (such as \ or ""). So we just repeatedly strip out the longest balanced comments until there aren't any left (span returns the empty list). If a comment was unbalanced, span would fail but this code doesn't check that and just assumes no more matches.
{{out}}
The input (from the task description) is in a file because I'm too lazy to type it in:
<pre>
 
function subroutine() {
a = b + c ;
}
 
function something() {
}
</pre>
 
9,485

edits