Почему запрещены вложенные комментарии?
Почему в С++ Java вложенные комментарии запрещены, что связано с тем, что вложенные комментарии полезны, опрятны и элегантны и могут использоваться для комментирования высказываний с комментариями?
Ответы
Ответ 1
C и C++ делают это для простоты разбора. Таким образом, когда они попадают в начало комментария /*, анализатор может тривиально сканировать до конца. В противном случае он должен был бы настроить и поддерживать стек, а затем сообщать об ошибках, если токены комментариев не совпадают.
Что касается того, почему Java делает это, ответ прост - синтаксис Java был разработан для эмуляции C и C++. Если бы были разрешены вложенные комментарии, это могло бы сбить с толку некоторых программистов на С, и было бы написано много злых постов в блоге!
Ответ 2
По крайней мере, для С++, который только отчасти верен, нет проблем с:
/*
//
//
*/
Однако, если у вас уже есть комментарий /* в разделе, который вы хотите прокомментировать, вы можете сделать это, окружив его #if 0
, который, как мне кажется, многие компиляторы оптимизируют. Как в:
#if 0
/*
*/
#endif
Ответ 3
Для каждого языка (-семейно) это различно, но в целом они не "запрещены", а просто не поддерживаются. Поддержка их - это выбор дизайна.
Одной из причин выбора (для более старых языков) может быть легкость синтаксического анализа.
Примечание. Я помню компилятор С++, где он был возможностью разрешить им вложить. Он был отмечен как "нестандартный".
Ответ 4
Соответствие/совместимость с C.
Ответ 5
Рассмотрим следующий пример:
/* This is a comment /* Nested Comments */ are not allowed. */
Все, что находится между /*
и */
, рассматривается как комментарий. В приведенном выше примере от This
до Comments
все обрабатывается как комментарии, включая /*
.
Следовательно, are not allowed. */
не лежит в комментарии.
Это неправильная ошибка оператора C.
Рассмотрим этот пример:
// This is an /* valid */ comment
Все, что лежит в строке после //
, рассматривается как комментарий. Поскольку /* valid */
лежит в той же строке после //
, он рассматривается как часть комментария.
Ответ 6
В языках, которые допускают комментарии произвольной длины, очень часто программисты случайно комментируют или, в некоторых редких случаях, "раскомментируют обратно" более или менее код, чем хотелось бы. Во многих случаях такие ошибки приводят к ошибкам компиляции, но в других случаях они могут привести к простому коду. С помощью современных редакторов синтаксиса-подсветки правило, что каждый /*
будет увеличивать счетчик вложенных комментариев, а каждый */
, который будет уменьшаться, может не вызвать слишком много проблем, но без выделения синтаксиса даже при попытке выяснить, какой код прокомментирован и какой код не мог быть основной головной болью.
Если бы кто-то разрабатывал язык с нуля, хорошим подходом могло бы быть указание маркеров начала и конца комментария, которые включали необязательную строку, и чтобы язык применял требование о том, чтобы строка в конце Знак -of-comment должен соответствовать строке в соответствующем знаке начала комментария. Предположим, что синтаксис был <|String|
и |String|>
, тогда компилятор мог принять <|1| <|2| |2|> |1|>
, но отклонить <|1| <|2| |1|> |2|>
. Даже если бы кто-то одобрял использование директив #if
, а не комментариев, то была бы полезной возможность прикреплять маркеры, чтобы гарантировать, что каждая конечная директива сопоставлена с предполагаемой директивой начала.
Ответ 7
Проблема в том, что вы не можете просто "пропустить" блоки. блоки имеют неизвестное количество блоков внутри них, поэтому, чтобы знать, когда этот блок будет завершен, вы не можете использовать обычный язык, вам нужно использовать стек и пройти через каждый блок до тех пор, пока стек не будет пустым, и в этот момент вы знаете, что блок сделан.
Причина, по которой вы не можете пропускать блоки, состоит в том, что регулярное выражение для блока способно только сопоставлять /* с "первым */он видит потом" или "последним */он видит потом" или "nth */он видит потом".
Если мы перейдем к первому маркеру "*/", который мы видим, у нас может быть код типа
/*
/*
*/
the compiler matched /* with */ and this line and the next one will confuse it.
*/
Если мы перейдем к последнему маркеру "*/", который мы видим, у нас есть код, в котором компилятор будет пропускать вещи между первым комментарием в файле и последним комментарием конца файла. В этом случае следующий код будет анализироваться как пустая строка.
/*
/* hello, world! */
*/
int main(int argc, char ** argv) {
return 0;
}
/* end of file */
Мы не можем пойти с третьим вариантом пропустить n внутренних блоков, не заставляя все комментарии иметь точное количество глубин, иначе он не найдет внутренний комментарий и не запутается.
На самом деле есть четвертый вариант явного указания, что комментарий может быть единственным комментарием, комментарием по 2 области, комментарием 3-области и т.д.; Но делать это уродливо, и каждый уровень глубины требует значительно более длительного выражения, и этот подход ограничивает комментарии до определенной глубины, которая может поместиться некоторым людям, а не подходит другим: что, если вы закомментируете код, который был прокомментирован 3 раза?
Общее решение может быть реализовано с помощью препроцессора, например:
<?php
function stripComments($code) {
$stack = array();
$codeOut = '';
$stringStream = fopen('php://memory', 'r+');
fwrite($stringStream, $code);
rewind($stringStream);
while (!feof($stringStream)) {
$ch = fgetc($stringStream);
$nextChar = fgetc($stringStream);
if ($nextChar === false) {
break;
}
if ($ch == '/' && $nextChar == '*') {
array_push($stack, '/*');
} else if ($ch == '*' && $nextChar == '/') {
if (count($stack) > 0) {
array_pop($stack);
} else {
die('cannot pop from empty stack');
}
} else {
if (count($stack) == 0) {
$codeOut .= $ch;
fseek($stringStream, -1, SEEK_CUR);
}
}
$prevChar = $ch;
}
return $codeOut;
};
?>
Это немного сложнее, чем то, что в настоящее время использует C:
function stripComments($code) {
return preg_replace('/\/\*[^\*\/]*\*\//', '', $code);
}
Это не учитывает /**/
блоки внутри кавычек, требуется несколько более сложный стек, который может различать область "/*" и область "\".
Преимущество комментариев в комментариях заключается в том, что вы можете комментировать блоки, содержащие комментарии, не отбрасывая комментарии вручную, что особенно расстраивает блоки, которые комментируют каждую строку.
Резюме. Это можно сделать, но большинство языков не хотят обрабатывать комментарии так, как если бы они были их собственными областями, так как требуется больше усилий для синтаксического анализа.