为什么在 C++ 中注释掉多行注释不一致?

Phy*_*ida 0 c++ regex compiler-construction comments

所以我们知道

// This doesn't affect anything

/*
This doesn't affect anything either
*/

/*
/* /* /*
This doesn't affect anything
*/
This does because comments aren't recursive

/* /*
This doesn't affect anything
*/ */
This throws an error because the second * / is unmatched since comments aren't recursive
Run Code Online (Sandbox Code Playgroud)

我听说它们不递归的原因是因为它们会减慢编译器的速度,我想这是有道理的。然而现在,当我用更高级的语言(比如 Python)解析 C++ 代码时,我可以简单地使用正则表达式

"\/[\/]+((?![\n])[\s\S])*\r*\n"
Run Code Online (Sandbox Code Playgroud)

匹配// single line comments并使用

"\/\*((?!\*\/)[\s\S])*\*\/"
Run Code Online (Sandbox Code Playgroud)

匹配/* multiline comments */,然后循环遍历所有单行注释,将其删除,然后循环遍历所有多行注释并将其删除。或相反亦然。但这就是我被困住的地方。似乎只做其中之一还不够,因为:

// /*
An error is thrown because the /* is ignored
*/

/*
This doesn't affect things because of mysterious reasons
// */
Run Code Online (Sandbox Code Playgroud)

/*
This throws an error because the second * / is unmatched
// */ */
Run Code Online (Sandbox Code Playgroud)

这种行为的原因是什么?它也是编译器解析事物的方式的产物吗?需要明确的是,我不想改变 C++ 的行为,我只想知道第二组示例的行为背后的原因。

编辑:

所以,是的,更明确地说,我的问题是为什么以下三种(看似合理的)解释这种行为的方法不起作用:

  1. 只需忽略 // 之后的行上的所有字符,无论它们是 /* 还是 * /,即使您位于多行注释中。

  2. 允许 / * 或 */ 后跟 // 仍然有效。

  3. 以上两者皆有。

我理解为什么不允许嵌套注释,因为它们需要堆栈和任意大量的内存。但这三种情况则不会。

再次编辑:

如果有人感兴趣,这里有以下代码,用于按照此处讨论的正确注释规则提取 python 中 ac/c++ 文件的注释:

import re
commentScanner = re.Scanner([
  (r"\/[\/]+((?![\n])[\s\S])*\r*(\n{1})?", lambda scanner, token: ("//", token)),
  (r"\/\*((?!\*\/)[\s\S])*\*\/", lambda scanner, token: ("/* ... */", token)),
  (r"[\s\S]", lambda scanner, token: None)
])
commentScanner.scan("fds a45fsa//kjl fds4325lkjfa/*jfds/\nk\lj\/*4532jlfds5342a  l/*a/*b/*c\n//fdsafa\n\r\n/*jfd//a*/fd// fs54fdsa3\r\r//\r/*\r\n2a\n\n\nois")
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 5

这并不矛盾。现有行为既易于指定又易于实现,并且您的编译器正在正确实现它。请参阅标准中的 [lex.comment]。

\n\n
\n

字符/*开始注释,以字符 结束*/。这些注释不嵌套。这些字符//开始注释,并以下一个换行符结束。如果此类注释中存在换页符或垂直制表符,则其与结束注释的换行符之间只能出现空格字符;无需诊断。[ 注意:注释字符\n ///*、 和在注释*/中没有特殊含义//,并且像其他字符一样被处理。\n 同样,注释字符//和在注释/*中没有特殊含义/*。\xe2\x80\x94尾注]

\n
\n\n

正如您所看到的,//可用于注释掉/**/。只是注释不能嵌套,所以如果//已经在 a 内/*,那么//根本没有效果。

\n