/*!
  A simple syntax highlighter for AspectC++ code
*/

function escapeHTML(value) {
return value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');
}

function acHighlight(elem) {
  const tokens = [];
  const keywordRegex = /^(aspect|slice|pointcut|advice|attribute|order|execution|call|get|set|ref|alias|construction|destruction|builtin|args|result|that|target|cflow|within|before|after|around|auto|break|case|char|derived|base|class|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|namespace|template|typename|inline|private|protected|public|virtual)(?=[^a-zA-Z0-9_])/;
  const idRegex = /^[a-zA-Z_]\w*/;
  const commentRegex = /^((\/\/.*\n)|(\/\*[\s\S]*?\*\/))/; // Single-line or multi-line comments
  const stringLiteralRegex = /^"([^"\\]*(\\.[^"\\]*)*)"/;
  const numberLiteralRegex = /^-?\d+(\.\d+)?/;
  const whitespaceRegex = /^\s+/;
  const posMarkerRegex = /^\<\=\=\s*\\pos\{\w+\}/;

  elem.classList.add("acxx");
  let remainingCode = elem.textContent;
  let result = '';
  let checks = [ { "regex": commentRegex, "name": "comment" },
                 { "regex": keywordRegex, "name": "keyword" },
                 { "regex": idRegex, "name": "id" },
                 { "regex": whitespaceRegex, "name": null },
                 { "regex": stringLiteralRegex, "name": "string" },
                 { "regex": numberLiteralRegex, "name": "number" } ];

  while (remainingCode.length > 0) {

    let match = null;
    for (check of checks) {
        // Remove comments first
        match = remainingCode.match(check.regex);
        if (match) {
            remainingCode = remainingCode.substring(match[0].length);
            token = escapeHTML(match[0]);
            if (check.name)
                result += "<span class='" + check.name + "'>" + token + "</span>";
            else
                result += token;
            break;
        }
    }

    if (!match) {
        // If no match, treat as an identifier or operator
        const nextToken = remainingCode.substring(0, 1);
        remainingCode = remainingCode.substring(1);
        result += escapeHTML(nextToken);
    }
  }

  return result;
}
