/* Language: C++ Category: common, system Website: https://isocpp.org */ /** @type LanguageFn */ export default function(hljs) { const regex = hljs.regex; // added for historic reasons because `hljs.C_LINE_COMMENT_MODE` does // not include such support nor can we be sure all the grammars depending // on it would desire this behavior const C_LINE_COMMENT_MODE = hljs.COMMENT('//', '$', { contains: [ { begin: /\\\n/ } ] }); const DECLTYPE_AUTO_RE = 'decltype\\(auto\\)'; const NAMESPACE_RE = '[a-zA-Z_]\\w*::'; const TEMPLATE_ARGUMENT_RE = '<[^<>]+>'; const FUNCTION_TYPE_RE = '(?!struct)(' + DECLTYPE_AUTO_RE + '|' + regex.optional(NAMESPACE_RE) + '[a-zA-Z_]\\w*' + regex.optional(TEMPLATE_ARGUMENT_RE) + ')'; const CPP_PRIMITIVE_TYPES = { className: 'type', begin: '\\b[a-z\\d_]*_t\\b' }; // https://en.cppreference.com/w/cpp/language/escape // \\ \x \xFF \u2837 \u00323747 \374 const CHARACTER_ESCAPES = '\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)'; const STRINGS = { className: 'string', variants: [ { begin: '(u8?|U|L)?"', end: '"', illegal: '\\n', contains: [ hljs.BACKSLASH_ESCAPE ] }, { begin: '(u8?|U|L)?\'(' + CHARACTER_ESCAPES + '|.)', end: '\'', illegal: '.' }, hljs.END_SAME_AS_BEGIN({ begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/, end: /\)([^()\\ ]{0,16})"/ }) ] }; const NUMBERS = { className: 'number', variants: [ // Floating-point literal. { begin: "[+-]?(?:" // Leading sign. // Decimal. + "(?:" +"[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?" + "|\\.[0-9](?:'?[0-9])*" + ")(?:[Ee][+-]?[0-9](?:'?[0-9])*)?" + "|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*" // Hexadecimal. + "|0[Xx](?:" +"[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?" + "|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*" + ")[Pp][+-]?[0-9](?:'?[0-9])*" + ")(?:" // Literal suffixes. + "[Ff](?:16|32|64|128)?" + "|(BF|bf)16" + "|[Ll]" + "|" // Literal suffix is optional. + ")" }, // Integer literal. { begin: "[+-]?\\b(?:" // Leading sign. + "0[Bb][01](?:'?[01])*" // Binary. + "|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*" // Hexadecimal. + "|0(?:'?[0-7])*" // Octal or just a lone zero. + "|[1-9](?:'?[0-9])*" // Decimal. + ")(?:" // Literal suffixes. + "[Uu](?:LL?|ll?)" + "|[Uu][Zz]?" + "|(?:LL?|ll?)[Uu]?" + "|[Zz][Uu]" + "|" // Literal suffix is optional. + ")" // Note: there are user-defined literal suffixes too, but perhaps having the custom suffix not part of the // literal highlight actually makes it stand out more. } ], relevance: 0 }; const PREPROCESSOR = { className: 'meta', begin: /#\s*[a-z]+\b/, end: /$/, keywords: { keyword: 'if else elif endif define undef warning error line ' + 'pragma _Pragma ifdef ifndef include' }, contains: [ { begin: /\\\n/, relevance: 0 }, hljs.inherit(STRINGS, { className: 'string' }), { className: 'string', begin: /<.*?>/ }, C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE ] }; const TITLE_MODE = { className: 'title', begin: regex.optional(NAMESPACE_RE) + hljs.IDENT_RE, relevance: 0 }; const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\('; // https://en.cppreference.com/w/cpp/keyword const RESERVED_KEYWORDS = [ 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'atomic_cancel', 'atomic_commit', 'atomic_noexcept', 'auto', 'bitand', 'bitor', 'break', 'case', 'catch', 'class', 'co_await', 'co_return', 'co_yield', 'compl', 'concept', 'const_cast|10', 'consteval', 'constexpr', 'constinit', 'continue', 'decltype', 'default', 'delete', 'do', 'dynamic_cast|10', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'final', 'for', 'friend', 'goto', 'if', 'import', 'inline', 'module', 'mutable', 'namespace', 'new', 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'override', 'private', 'protected', 'public', 'reflexpr', 'register', 'reinterpret_cast|10', 'requires', 'return', 'sizeof', 'static_assert', 'static_cast|10', 'struct', 'switch', 'synchronized', 'template', 'this', 'thread_local', 'throw', 'transaction_safe', 'transaction_safe_dynamic', 'true', 'try', 'typedef', 'typeid', 'typename', 'union', 'using', 'virtual', 'volatile', 'while', 'xor', 'xor_eq' ]; // https://en.cppreference.com/w/cpp/keyword const RESERVED_TYPES = [ 'bool', 'char', 'char16_t', 'char32_t', 'char8_t', 'double', 'float', 'int', 'long', 'short', 'void', 'wchar_t', 'unsigned', 'signed', 'const', 'static' ]; const TYPE_HINTS = [ 'any', 'auto_ptr', 'barrier', 'binary_semaphore', 'bitset', 'complex', 'condition_variable', 'condition_variable_any', 'counting_semaphore', 'deque', 'false_type', 'future', 'imaginary', 'initializer_list', 'istringstream', 'jthread', 'latch', 'lock_guard', 'multimap', 'multiset', 'mutex', 'optional', 'ostringstream', 'packaged_task', 'pair', 'promise', 'priority_queue', 'queue', 'recursive_mutex', 'recursive_timed_mutex', 'scoped_lock', 'set', 'shared_future', 'shared_lock', 'shared_mutex', 'shared_timed_mutex', 'shared_ptr', 'stack', 'string_view', 'stringstream', 'timed_mutex', 'thread', 'true_type', 'tuple', 'unique_lock', 'unique_ptr', 'unordered_map', 'unordered_multimap', 'unordered_multiset', 'unordered_set', 'variant', 'vector', 'weak_ptr', 'wstring', 'wstring_view' ]; const FUNCTION_HINTS = [ 'abort', 'abs', 'acos', 'apply', 'as_const', 'asin', 'atan', 'atan2', 'calloc', 'ceil', 'cerr', 'cin', 'clog', 'cos', 'cosh', 'cout', 'declval', 'endl', 'exchange', 'exit', 'exp', 'fabs', 'floor', 'fmod', 'forward', 'fprintf', 'fputs', 'free', 'frexp', 'fscanf', 'future', 'invoke', 'isalnum', 'isalpha', 'iscntrl', 'isdigit', 'isgraph', 'islower', 'isprint', 'ispunct', 'isspace', 'isupper', 'isxdigit', 'labs', 'launder', 'ldexp', 'log', 'log10', 'make_pair', 'make_shared', 'make_shared_for_overwrite', 'make_tuple', 'make_unique', 'malloc', 'memchr', 'memcmp', 'memcpy', 'memset', 'modf', 'move', 'pow', 'printf', 'putchar', 'puts', 'realloc', 'scanf', 'sin', 'sinh', 'snprintf', 'sprintf', 'sqrt', 'sscanf', 'std', 'stderr', 'stdin', 'stdout', 'strcat', 'strchr', 'strcmp', 'strcpy', 'strcspn', 'strlen', 'strncat', 'strncmp', 'strncpy', 'strpbrk', 'strrchr', 'strspn', 'strstr', 'swap', 'tan', 'tanh', 'terminate', 'to_underlying', 'tolower', 'toupper', 'vfprintf', 'visit', 'vprintf', 'vsprintf' ]; const LITERALS = [ 'NULL', 'false', 'nullopt', 'nullptr', 'true' ]; // https://en.cppreference.com/w/cpp/keyword const BUILT_IN = [ '_Pragma' ]; const CPP_KEYWORDS = { type: RESERVED_TYPES, keyword: RESERVED_KEYWORDS, literal: LITERALS, built_in: BUILT_IN, _type_hints: TYPE_HINTS }; const FUNCTION_DISPATCH = { className: 'function.dispatch', relevance: 0, keywords: { // Only for relevance, not highlighting. _hint: FUNCTION_HINTS }, begin: regex.concat( /\b/, /(?!decltype)/, /(?!if)/, /(?!for)/, /(?!switch)/, /(?!while)/, hljs.IDENT_RE, regex.lookahead(/(<[^<>]+>|)\s*\(/)) }; const EXPRESSION_CONTAINS = [ FUNCTION_DISPATCH, PREPROCESSOR, CPP_PRIMITIVE_TYPES, C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE, NUMBERS, STRINGS ]; const EXPRESSION_CONTEXT = { // This mode covers expression context where we can't expect a function // definition and shouldn't highlight anything that looks like one: // `return some()`, `else if()`, `(x*sum(1, 2))` variants: [ { begin: /=/, end: /;/ }, { begin: /\(/, end: /\)/ }, { beginKeywords: 'new throw return else', end: /;/ } ], keywords: CPP_KEYWORDS, contains: EXPRESSION_CONTAINS.concat([ { begin: /\(/, end: /\)/, keywords: CPP_KEYWORDS, contains: EXPRESSION_CONTAINS.concat([ 'self' ]), relevance: 0 } ]), relevance: 0 }; const FUNCTION_DECLARATION = { className: 'function', begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE, returnBegin: true, end: /[{;=]/, excludeEnd: true, keywords: CPP_KEYWORDS, illegal: /[^\w\s\*&:<>.]/, contains: [ { // to prevent it from being confused as the function title begin: DECLTYPE_AUTO_RE, keywords: CPP_KEYWORDS, relevance: 0 }, { begin: FUNCTION_TITLE, returnBegin: true, contains: [ TITLE_MODE ], relevance: 0 }, // needed because we do not have look-behind on the below rule // to prevent it from grabbing the final : in a :: pair { begin: /::/, relevance: 0 }, // initializers { begin: /:/, endsWithParent: true, contains: [ STRINGS, NUMBERS ] }, // allow for multiple declarations, e.g.: // extern void f(int), g(char); { relevance: 0, match: /,/ }, { className: 'params', begin: /\(/, end: /\)/, keywords: CPP_KEYWORDS, relevance: 0, contains: [ C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE, STRINGS, NUMBERS, CPP_PRIMITIVE_TYPES, // Count matching parentheses. { begin: /\(/, end: /\)/, keywords: CPP_KEYWORDS, relevance: 0, contains: [ 'self', C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE, STRINGS, NUMBERS, CPP_PRIMITIVE_TYPES ] } ] }, CPP_PRIMITIVE_TYPES, C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE, PREPROCESSOR ] }; return { name: 'C++', aliases: [ 'cc', 'c++', 'h++', 'hpp', 'hh', 'hxx', 'cxx' ], keywords: CPP_KEYWORDS, illegal: ' rooms (9);` begin: '\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array|tuple|optional|variant|function)\\s*<(?!<)', end: '>', keywords: CPP_KEYWORDS, contains: [ 'self', CPP_PRIMITIVE_TYPES ] }, { begin: hljs.IDENT_RE + '::', keywords: CPP_KEYWORDS }, { match: [ // extra complexity to deal with `enum class` and `enum struct` /\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/, /\s+/, /\w+/ ], className: { 1: 'keyword', 3: 'title.class' } } ]) }; }