Проблема в том, что вы не можете просто «пропустить» блоки. блоки имеют неизвестное количество блоков внутри них, поэтому, чтобы узнать, когда этот блок будет завершен, вы не можете использовать обычный язык, вы должны использовать стек и проходить через каждый блок, пока стек не будет пустым, и в этот момент Вы знаете, что блок сделан.
Причина, по которой вы не можете пропустить блоки, состоит в том, что регулярное выражение для блока способно сопоставить / * только с "первым * /, который он видит позже", или "последним * /, которое он видит позже", или "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 внутренних блоков, не заставляя все комментарии иметь точное количество глубины, иначе он не найдет внутренний комментарий и не запутается.
На самом деле, существует четвертый вариант явного указания, что комментарий может быть отдельным комментарием, комментарием с двумя областями, комментарием с тремя областями и т. Д .; Но делать это уродливо, и каждый уровень глубины требует значительно более длинного выражения, и этот подход ограничивает комментарии до определенной глубины, которая может подходить некоторым людям, а не другим: что делать, если вы закомментируете закомментированный код три раза?
Общее решение может быть реализовано с помощью препроцессора, например:
<?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);
}
Это не учитывает блоки /**/
внутри кавычек, требуется несколько более сложный стек, который может различать область видимости "/ *" и область видимости "\".
Преимущество наличия комментариев внутри комментариев состоит в том, что вы можете закомментировать блоки, содержащие комментарии, не разбирая комментарии вручную, что особенно неприятно для блоков, в которых комментарии находятся в каждой строке.
Резюме : Это можно сделать, но большинство языков не хотят обрабатывать комментарии, как если бы они были их собственными областями, так как для их анализа требуется больше усилий.