27

A few do, but not any of the popular ones as far as I know. Is there something bad about nesting comments?

I plan to have block comments nest in the (small) language I'm working on, but I would like to know if this is a bad idea.

5
  • re a few answers: ohh, that makes sense =) I'm totally doing nested block comments then; although I do have a separate lexing stage, it's not the limiting sort SK-logic described.
    – Vuntic
    Commented Jun 2, 2011 at 11:05
  • @Vuntic: If you have a separate lexing stage that uses stuff more complicated than regular expressions, you may have performance issues. REs are fast and easy to use by implementing DFAs. Commented Jun 2, 2011 at 16:18
  • It catches more errors earlier to not allow nesting
    – user1249
    Commented Jun 2, 2011 at 16:21
  • 4
    @David: ...not at all. It's actually really fast.
    – amara
    Commented Jun 2, 2011 at 20:28
  • I would suggest that if you want to allow nested comments, you allow start-comment tags to be marked with a token, and require that if a start-comment tag is thus marked, its end-comment tag must be marked identically. That would allow unbalanced start/end tags to be quickly identified, and avoid the possibility of bugs caused by undetected unbalanced tags.
    – supercat
    Commented May 16, 2014 at 20:40

11 Answers 11

5

One thing nobody's mentioned yet, so I'll mention it: The desire to nest comments often indicates that the programmer is Doing It Wrong.

First, let's agree that the only time "nesting" or "not nesting" is visible to the programmer is when the programmer writes something structurally like this:

do_something();
/* comment /* nested comment */ more comment */
do_something_else();

Now, when does such a thing come up in practice? Certainly the programmer isn't going to be writing nested comments that literally look like the above snippet! No, in practice when we nest comments (or wish we could nest them), it's because we want to write something like this:

do_something();  /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/

And this is BAD. This is not a pattern we (as language designers) want to encourage! The correct way to write the above snippet is:

do_something();  /* do a thing */

That "wrong" code, that false start or whatever it was, doesn't belong in the codebase. It belongs, at best, in the source-control history. Ideally, you'd never even write the wrong code to begin with, right? And if the wrong code was serving a purpose there, by warning maintainers not to reinstate it for some reason, well, that's probably a job for a well-written and intentional code comment. Trying to express "don't do X" by just leaving in some old code that does X, but commented out, is not the most readable or effective way to keep people from doing X.

This all boils down to a simple rule of thumb that you may have heard before: Don't comment out code. (Searching for this phrase will turn up a lot of opinions in agreement.)

Before you ask: yes, languages such as C, C#, and C++ already give the programmer another tool to "comment out" large blocks of code: #if 0. But this is just a particular application of the C preprocessor, which is a large and useful tool in its own right. It would actually be extremely difficult and special-casey for a language to support conditional compilation with #if and yet not support #if 0.


So, we've established that nested comments are relevant only when the programmer is commenting out code; and we've established (via consensus of a lot of experienced programmers) that commenting out code is a Bad Thing.

To complete the syllogism, we must accept that language designers have an interest in promoting Good Things and discouraging Bad Things (assuming that all else is equal).

In the case of nested comments, all else is equal — you can safely ignore the low-voted answers that claim that parsing nested /* would somehow be "difficult" for the parser. (Nested /* are no harder than nested (, which just about every parser in the world already needs to handle.)

So, all else being equal, should a language designer make it easy to nest comments (i.e., to comment out code), or difficult? Recall that commenting out code is a Bad Thing.

Q.E.D.


Footnote. Notice that if you don't allow nested comments, then

hello /* foo*/bar.txt */ world

is a misleading "comment" — it's equivalent to

hello bar.txt */ world

(which is likely a syntax error). But if you do allow nested comments, then

hello /* foo/*.txt */ world

is a misleading "comment" — it's equivalent to

hello

but leaves the comment open all the way to the end of the file (which again is almost certainly a syntax error). So neither way is particularly less prone to unintentional syntax errors. The only difference is in how they handle the intentional antipattern of commented-out code.

11
  • 10
    I have different opinion based on simply fact -- I didn't see everything (and neither did you). So while those golden rules like "Don't comment out code" look nice, life has its own paths. In this particular case, I do it very often as as switch, when I test some new feature and have to incrementally introduce some code, so I comment out the code, then less, less, less, and finally I have working piece and I can remove all the comments (over code). My perfect language will of course support nested comments :-). Commented Dec 4, 2017 at 16:07
  • @greenoldman: Most languages don't have nestable comments, but they'll have some actual feature for "remove a block of code" which is less-used than the "leave a comment" feature. C's #if DEAD is the canonical and best-designed example. In many languages you can just wrap the dead code in the equivalent of if (DEAD). And in many IDEs, you can actually remove the dead code and rely on Ctrl+Z and/or version control to get it back if you want it. Leaving a comment, docstring, whatever, whose text is a bunch of dead code, is still the worst option for readability. Commented Dec 4, 2017 at 19:10
  • 4
    Believe it or not, most languages are not this opinionated.
    – user20574
    Commented Aug 13, 2021 at 12:42
  • 1
    I also disagree about not commenting code. It's very useful in development and has occasional uses in production. (Mostly of the this-obvious-solution-doesn't-work as a warning not to clean up what looks like bad code.) In C# it's not a problem--just use // type comments. Commented Aug 22, 2021 at 0:57
  • 2
    It might be a bad idea to comment out code, but that is not the reason comments don't nest in C-derived languages. The reason is that comments are discarded in the lexing stage and lexers were traditionally implemented as a finite state machine which does not support nested structures. This was to keep the scanner and compiler simple and fast which was important on the limited hardware at the time. Probably not important today, but many languages with C-derived syntax have kept the syntax for familiarity. OTOH several newer languages does support nested comments.
    – JacquesB
    Commented Aug 22, 2021 at 10:54
20

Because most of the implementations are using separate lexing and parsing stages, and for lexing they're using plain old regular expressions. Comments are treated as whitespaces - i.e., ignored tokens, and thus should be resolved entirely in a lexing pass. The only advantage of this approach is parsing speed. Numerous disadvantages include severe limitations on syntax (e.g., a need to maintain a fixed, context-independent set of keywords).

26
  • 3
    I would disagree on 'most' nowadays. Certainly that's the traditional way, but I know that for C, EDG combines the preprocessor, lexing and parsing, and I suspect that both GCC and Microsoft do too. The benefit is that it allows you to implement them separately if you need to. Commented Jun 2, 2011 at 9:56
  • Clang is doing the same, too. But that's still only a tiny proportion of the existing popular languages compilers.
    – SK-logic
    Commented Jun 2, 2011 at 10:00
  • @Neil Butterworth, take a look at mcs, javac, gcc (yep, it back-patches a lexer, but still it is a dedicated lexing pass), clang (same as gcc), dmd, fpc, and many, many more.
    – SK-logic
    Commented Jun 4, 2011 at 23:09
  • No one is using regular expressions in their lexing for any non-trivial compiler.
    – Nuoji
    Commented Jan 10, 2019 at 11:47
  • 1
    @Nuoji that'd be a dirty hack - constructing some special kind of a state machine for only certain lexemes - all for what? To keep doing things the way Dragon Book prescribed? There is no point in it when you can just go lexerless and use exactly the same mechanism for parsing tokens and token streams. If you're lazy you'll use flex and alike and be restricted with it, otherwise you won't have a lexer at all.
    – SK-logic
    Commented Aug 10, 2021 at 16:02
12

It's perfectly possible to make a lexer that can handle nested comments. When it's eating whitespace, when it sees /* it can increment a depth counter, and decrement it when it sees */, and stop when the depth is zero. That said, I've done many parsers, and never found a good reason for comments to nest.

If comments can nest, then a downside is it's easy to get their ends unbalanced, and unless you have a fancy editor, it can invisibly hide code you assume is there.

An upside of comments that don't nest is something like this:

/*
some code
more code
blah blah blah
/**/

where you can easily comment the code in or out by removing or adding the first line - a 1-line edit. Of course, if that code itself contains a comment, this would break, unless you also allow C++-style // comments in there. So that's what I tend to do.

4
  • 1
    // comments are also C99-style.
    – JAB
    Commented Jun 2, 2011 at 20:58
  • 1
    Alternatively, a language could specify a start-of-comment is /*$token, where identifier is any alphanumeric token, and end-of-comment is token$*/. It would be relatively simple for tokenizer to include code to verify that every end-comment mark contains the proper token for its matching start-comment block.
    – supercat
    Commented May 16, 2014 at 20:36
  • A lexer which keep a stack is not really a lexer anymore, it is a parser.
    – JacquesB
    Commented Aug 11, 2021 at 13:16
  • The counter argument (easy to create unbalanced comments) makes no sense. The comments are part of the language, the compiler can and should bark on unbalanced comments just like on unbalanced braces or parentheses. Commented Aug 22, 2021 at 6:53
6

Since nobody else mentioned it, I'll list a few languages that do support nested comments: Rexx, Modula-2, Modula-3, Oberon. Despite all the complaints here about difficulty and speed issues, none of those seem to have any huge problems.

4
  • 5
    To which I add: Haskell, Frege
    – Ingo
    Commented Aug 24, 2011 at 9:31
  • 1
    Supported by Scala too.
    – Matt R
    Commented Aug 13, 2013 at 15:23
  • Of course. This is because the difficulty / speed claim has no basis in reality.
    – Nuoji
    Commented Aug 11, 2021 at 12:30
  • Swift does it as well.
    – gnasher729
    Commented Aug 11, 2021 at 14:57
6

A good point of nesting block comments is that you can comment out large portions of code easily (well, almost, unless you have the block comment end sequence in a string constant).

An alternative method is to prepend a bunch of line with the line comment start sequence if you have an editor that supports it.

Haskell has nested block comments, but most people dont seem to notice or to complain about it. I guess this is because people that do not expect nested comments tend to avoid them as this would be a lexical error in other languages.

2

Supporting nested block comments complicates the parser, which is both more work and it could increase the compile time. I guess it is not a very needed feature for a language, so it is better to use the time and effort on other improvements and optimizations.

In my opinion simplicity is always a good thing in designing anything. Keep in mind that it is easier to add a feature than to remove it. Once you allow nested comments and there are programs out there using it, you won't be able to take them out without breaking compatibility.

3
  • 1
    +1 for "easier to add a feature than to remove it". Commented Jun 8, 2011 at 0:49
  • 4
    once you disallow nested comments you can't allow them as well because it'll break such comments: /*/**/
    – RiaD
    Commented Jun 19, 2014 at 20:23
  • @alexrs — it's not that much work to keep a counter of occurrences of comment start tokens and decrease it whenever a comment end token is encountered. Speed is not a thing here, compile time wouldn't be affected. That being said, I agree with simplicity in design, but personally find it useful to be able to comment out code while still coding (commented out code would stay there only temporarily and be removed as soon as possible, without making it into releases). But design–wise, in this specific case, adding nested comments later as a feature would as well break compatibility. Commented Jul 8, 2021 at 19:46
1

One probable reason is that nested comments must be handled by the parser, since the flavor of regular expressions commonly used in lexers don't support recursion. The simple ones can be eliminated as whitespace by the lexer, so they're simpler to implement in that way.

7
  • 3
    It's not the "flavor". The word "regular" in regular expression inherently excludes recursion. Commented Jun 8, 2011 at 0:48
  • 4
    @R: In mathematics, sure. But in programming, we have things that we call regexes that do support recursion.
    – amara
    Commented Jun 8, 2011 at 19:33
  • The question is: Is this even an issue? Most languages already have to deal with nesting parentheses. To name some: Lisp, C, Java, Python, Ruby, Perl. Commented Apr 23, 2014 at 20:34
  • 2
    @ThePopMachine: I'm sure of what I stated, that regular has a defined formal meaning, not the meaning you're using, and that the "regular" in "regular expression" was chosen for this meaning. Being non-recursive is one result of its definition. Commented Jun 19, 2014 at 20:57
  • 1
    @R.. : Maybe you're right about the origin of the term, but you're the one who picked on the word "flavour". In a programming context, where regular expression clearly doesn't (always) means what you say, why would you pick on what is effectively just a clarifying term. Commented Jun 20, 2014 at 14:45
0

Who knows? I would guess because supporting nested comments is more work - you would have to maintain a stack of some sort, and because it complicates the language grammar.

1
  • Not sure why this got downvoted. This is indeed at least part of the answer. At least historically, compilers have often been implemented as a "lexer" such as lex or flex (which typically understands a regular grammar, i.e., roughly, regexes without enhancements such as nesting) followed by a "parser" such as yacc or bison (which typically understands a LALR(1) grammar). A comment is typically recognized as a token in the lexer stage, which can't do nesting. So non-nestability of comments naturally falls out of these historical design constraints.
    – Don Hatch
    Commented Jan 16, 2020 at 10:30
0

Languages with nested comments: D, Haskell, Raku, Swift, Julia, Dart, Kotlin - to pick a few common ones. C has #if 0 ... #endif which works similar to nested comments, which means C++ also has it.

So it seems like the modern style is to include them as they're generally seen as a good idea. And comment syntax evolves, remember C didn't originally have // but rather that comes from C++.

There are some claims elsewhere that lexing would be harder with nested comments. Given that it's simple enough to do it manually AND it's straightforward to do in a tool like flex (for a solution, see this Stack Overflow question: https://stackoverflow.com/questions/34493467/how-to-handle-nested-comment-in-flex) it seems simple hard facts contradict that idea.

Not to mention that most popular languages use handwritten parsers and lexers: https://notes.eatonphil.com/parser-generators-vs-handwritten-parsers-survey-2021.html.

2
  • If a lexer keeps track of nested structures then it is by definition not a lexer anymore.
    – JacquesB
    Commented Aug 11, 2021 at 14:36
  • A lexer is a program that takes characters and transforms them into tokens. I have no idea what you got your definition from, but it is the first time I ever heard of that idea.
    – Nuoji
    Commented Aug 20, 2021 at 18:46
0

Once you define precisely what is and what isn’t a comment, it’s easy enough to implement. Nested comments would be slightly harder, but not so much that it would be a big deal.

So what’s the problem? Describing exactly what is and what isn’t a comment. And giving a description where you don’t have unexpected nested comments, when the user didn’t intend it.

-1

Nested comments mean extra work for the parser. Usually when you see the start of a comment you ignore everything until the end comment marker. In order to support nested comments you have to parse the text in the comments as well. The biggest issue, though, is that a programmer has to be careful to close all nested comments correctly or it will lead to compilation errors. Correctly implementing a compiler is something that can be done but keeping track of nested comments as a programmer is quite error-prone and irritating.

1
  • 3
    -1: not true. Sane parsers don't work like that.
    – amara
    Commented Jun 8, 2011 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.