<?php
$string = <<<'STRING'
//single line comment
random text ... #another comment
Multiline comments:
/* this is a multiline comment
with 'squote and "dquote"
matches the whole thing */
// single line 'squoted' "dquoted" comment w/ extra " for no reason
More comments <!-- yatta yatta
yatta
yatta -->
Quotes:
"also matches strings with \" escaped quotes or 'the other kind of quotation marks in it' "
a "nested 'squote with nested \"dquote\"'" assuming only outermost quoting matters for formatting
'matches the end quote because it it not escaped \\'
STRING;
const PATTERN = <<<'PATTERN'
~(?|(")(?:[^"\\]|\\(?s).)*"|(')(?:[^'\\]|\\(?s).)*'|(#|//).*|(/\*)(?:[^*/]|\*(?!/)|(?<!\*)/)*\*/|(<!--)(?:[^->]|-(?!->)|(?<!--)>)*-->)~
PATTERN;
const LOOKUP = [
'#' => 'gainsboro',
'//' => 'lightgrey',
'/*' => 'silver',
'<!--' => 'darkgrey',
"'" => 'mint',
'"' => 'aqua'
];
echo preg_replace_callback(PATTERN, function($m) {
$marker = $m[1];
$encoded = addcslashes($marker, '"');
$class = LOOKUP[$marker] ?? "missing $encoded";
return "<span class=\"{$class}\" data-marker=\"{$encoded}\">{$m[0]}</span>";
}, $string);
<span class="lightgrey" data-marker="//">//single line comment</span>
random text ... <span class="gainsboro" data-marker="#">#another comment</span>
Multiline comments:
<span class="silver" data-marker="/*">/* this is a multiline comment
with 'squote and "dquote"
matches the whole thing */</span>
<span class="lightgrey" data-marker="//">// single line 'squoted' "dquoted" comment w/ extra " for no reason</span>
More comments <span class="darkgrey" data-marker="<!--"><!-- yatta yatta
yatta
yatta --></span>
Quotes:
<span class="aqua" data-marker="\"">"also matches strings with \" escaped quotes or 'the other kind of quotation marks in it' "</span>
a <span class="aqua" data-marker="\"">"nested 'squote with nested \"dquote\"'"</span> assuming only outermost quoting matters for formatting
<span class="mint" data-marker="'">'matches the end quote because it it not escaped \\'</span>