cpp.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /*
  2. Language: C++
  3. Category: common, system
  4. Website: https://isocpp.org
  5. */
  6. /** @type LanguageFn */
  7. function cpp(hljs) {
  8. const regex = hljs.regex;
  9. // added for historic reasons because `hljs.C_LINE_COMMENT_MODE` does
  10. // not include such support nor can we be sure all the grammars depending
  11. // on it would desire this behavior
  12. const C_LINE_COMMENT_MODE = hljs.COMMENT('//', '$', { contains: [ { begin: /\\\n/ } ] });
  13. const DECLTYPE_AUTO_RE = 'decltype\\(auto\\)';
  14. const NAMESPACE_RE = '[a-zA-Z_]\\w*::';
  15. const TEMPLATE_ARGUMENT_RE = '<[^<>]+>';
  16. const FUNCTION_TYPE_RE = '(?!struct)('
  17. + DECLTYPE_AUTO_RE + '|'
  18. + regex.optional(NAMESPACE_RE)
  19. + '[a-zA-Z_]\\w*' + regex.optional(TEMPLATE_ARGUMENT_RE)
  20. + ')';
  21. const CPP_PRIMITIVE_TYPES = {
  22. className: 'type',
  23. begin: '\\b[a-z\\d_]*_t\\b'
  24. };
  25. // https://en.cppreference.com/w/cpp/language/escape
  26. // \\ \x \xFF \u2837 \u00323747 \374
  27. const CHARACTER_ESCAPES = '\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)';
  28. const STRINGS = {
  29. className: 'string',
  30. variants: [
  31. {
  32. begin: '(u8?|U|L)?"',
  33. end: '"',
  34. illegal: '\\n',
  35. contains: [ hljs.BACKSLASH_ESCAPE ]
  36. },
  37. {
  38. begin: '(u8?|U|L)?\'(' + CHARACTER_ESCAPES + '|.)',
  39. end: '\'',
  40. illegal: '.'
  41. },
  42. hljs.END_SAME_AS_BEGIN({
  43. begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
  44. end: /\)([^()\\ ]{0,16})"/
  45. })
  46. ]
  47. };
  48. const NUMBERS = {
  49. className: 'number',
  50. variants: [
  51. // Floating-point literal.
  52. { begin:
  53. "[+-]?(?:" // Leading sign.
  54. // Decimal.
  55. + "(?:"
  56. +"[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?"
  57. + "|\\.[0-9](?:'?[0-9])*"
  58. + ")(?:[Ee][+-]?[0-9](?:'?[0-9])*)?"
  59. + "|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*"
  60. // Hexadecimal.
  61. + "|0[Xx](?:"
  62. +"[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?"
  63. + "|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*"
  64. + ")[Pp][+-]?[0-9](?:'?[0-9])*"
  65. + ")(?:" // Literal suffixes.
  66. + "[Ff](?:16|32|64|128)?"
  67. + "|(BF|bf)16"
  68. + "|[Ll]"
  69. + "|" // Literal suffix is optional.
  70. + ")"
  71. },
  72. // Integer literal.
  73. { begin:
  74. "[+-]?\\b(?:" // Leading sign.
  75. + "0[Bb][01](?:'?[01])*" // Binary.
  76. + "|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*" // Hexadecimal.
  77. + "|0(?:'?[0-7])*" // Octal or just a lone zero.
  78. + "|[1-9](?:'?[0-9])*" // Decimal.
  79. + ")(?:" // Literal suffixes.
  80. + "[Uu](?:LL?|ll?)"
  81. + "|[Uu][Zz]?"
  82. + "|(?:LL?|ll?)[Uu]?"
  83. + "|[Zz][Uu]"
  84. + "|" // Literal suffix is optional.
  85. + ")"
  86. // Note: there are user-defined literal suffixes too, but perhaps having the custom suffix not part of the
  87. // literal highlight actually makes it stand out more.
  88. }
  89. ],
  90. relevance: 0
  91. };
  92. const PREPROCESSOR = {
  93. className: 'meta',
  94. begin: /#\s*[a-z]+\b/,
  95. end: /$/,
  96. keywords: { keyword:
  97. 'if else elif endif define undef warning error line '
  98. + 'pragma _Pragma ifdef ifndef include' },
  99. contains: [
  100. {
  101. begin: /\\\n/,
  102. relevance: 0
  103. },
  104. hljs.inherit(STRINGS, { className: 'string' }),
  105. {
  106. className: 'string',
  107. begin: /<.*?>/
  108. },
  109. C_LINE_COMMENT_MODE,
  110. hljs.C_BLOCK_COMMENT_MODE
  111. ]
  112. };
  113. const TITLE_MODE = {
  114. className: 'title',
  115. begin: regex.optional(NAMESPACE_RE) + hljs.IDENT_RE,
  116. relevance: 0
  117. };
  118. const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
  119. // https://en.cppreference.com/w/cpp/keyword
  120. const RESERVED_KEYWORDS = [
  121. 'alignas',
  122. 'alignof',
  123. 'and',
  124. 'and_eq',
  125. 'asm',
  126. 'atomic_cancel',
  127. 'atomic_commit',
  128. 'atomic_noexcept',
  129. 'auto',
  130. 'bitand',
  131. 'bitor',
  132. 'break',
  133. 'case',
  134. 'catch',
  135. 'class',
  136. 'co_await',
  137. 'co_return',
  138. 'co_yield',
  139. 'compl',
  140. 'concept',
  141. 'const_cast|10',
  142. 'consteval',
  143. 'constexpr',
  144. 'constinit',
  145. 'continue',
  146. 'decltype',
  147. 'default',
  148. 'delete',
  149. 'do',
  150. 'dynamic_cast|10',
  151. 'else',
  152. 'enum',
  153. 'explicit',
  154. 'export',
  155. 'extern',
  156. 'false',
  157. 'final',
  158. 'for',
  159. 'friend',
  160. 'goto',
  161. 'if',
  162. 'import',
  163. 'inline',
  164. 'module',
  165. 'mutable',
  166. 'namespace',
  167. 'new',
  168. 'noexcept',
  169. 'not',
  170. 'not_eq',
  171. 'nullptr',
  172. 'operator',
  173. 'or',
  174. 'or_eq',
  175. 'override',
  176. 'private',
  177. 'protected',
  178. 'public',
  179. 'reflexpr',
  180. 'register',
  181. 'reinterpret_cast|10',
  182. 'requires',
  183. 'return',
  184. 'sizeof',
  185. 'static_assert',
  186. 'static_cast|10',
  187. 'struct',
  188. 'switch',
  189. 'synchronized',
  190. 'template',
  191. 'this',
  192. 'thread_local',
  193. 'throw',
  194. 'transaction_safe',
  195. 'transaction_safe_dynamic',
  196. 'true',
  197. 'try',
  198. 'typedef',
  199. 'typeid',
  200. 'typename',
  201. 'union',
  202. 'using',
  203. 'virtual',
  204. 'volatile',
  205. 'while',
  206. 'xor',
  207. 'xor_eq'
  208. ];
  209. // https://en.cppreference.com/w/cpp/keyword
  210. const RESERVED_TYPES = [
  211. 'bool',
  212. 'char',
  213. 'char16_t',
  214. 'char32_t',
  215. 'char8_t',
  216. 'double',
  217. 'float',
  218. 'int',
  219. 'long',
  220. 'short',
  221. 'void',
  222. 'wchar_t',
  223. 'unsigned',
  224. 'signed',
  225. 'const',
  226. 'static'
  227. ];
  228. const TYPE_HINTS = [
  229. 'any',
  230. 'auto_ptr',
  231. 'barrier',
  232. 'binary_semaphore',
  233. 'bitset',
  234. 'complex',
  235. 'condition_variable',
  236. 'condition_variable_any',
  237. 'counting_semaphore',
  238. 'deque',
  239. 'false_type',
  240. 'flat_map',
  241. 'flat_set',
  242. 'future',
  243. 'imaginary',
  244. 'initializer_list',
  245. 'istringstream',
  246. 'jthread',
  247. 'latch',
  248. 'lock_guard',
  249. 'multimap',
  250. 'multiset',
  251. 'mutex',
  252. 'optional',
  253. 'ostringstream',
  254. 'packaged_task',
  255. 'pair',
  256. 'promise',
  257. 'priority_queue',
  258. 'queue',
  259. 'recursive_mutex',
  260. 'recursive_timed_mutex',
  261. 'scoped_lock',
  262. 'set',
  263. 'shared_future',
  264. 'shared_lock',
  265. 'shared_mutex',
  266. 'shared_timed_mutex',
  267. 'shared_ptr',
  268. 'stack',
  269. 'string_view',
  270. 'stringstream',
  271. 'timed_mutex',
  272. 'thread',
  273. 'true_type',
  274. 'tuple',
  275. 'unique_lock',
  276. 'unique_ptr',
  277. 'unordered_map',
  278. 'unordered_multimap',
  279. 'unordered_multiset',
  280. 'unordered_set',
  281. 'variant',
  282. 'vector',
  283. 'weak_ptr',
  284. 'wstring',
  285. 'wstring_view'
  286. ];
  287. const FUNCTION_HINTS = [
  288. 'abort',
  289. 'abs',
  290. 'acos',
  291. 'apply',
  292. 'as_const',
  293. 'asin',
  294. 'atan',
  295. 'atan2',
  296. 'calloc',
  297. 'ceil',
  298. 'cerr',
  299. 'cin',
  300. 'clog',
  301. 'cos',
  302. 'cosh',
  303. 'cout',
  304. 'declval',
  305. 'endl',
  306. 'exchange',
  307. 'exit',
  308. 'exp',
  309. 'fabs',
  310. 'floor',
  311. 'fmod',
  312. 'forward',
  313. 'fprintf',
  314. 'fputs',
  315. 'free',
  316. 'frexp',
  317. 'fscanf',
  318. 'future',
  319. 'invoke',
  320. 'isalnum',
  321. 'isalpha',
  322. 'iscntrl',
  323. 'isdigit',
  324. 'isgraph',
  325. 'islower',
  326. 'isprint',
  327. 'ispunct',
  328. 'isspace',
  329. 'isupper',
  330. 'isxdigit',
  331. 'labs',
  332. 'launder',
  333. 'ldexp',
  334. 'log',
  335. 'log10',
  336. 'make_pair',
  337. 'make_shared',
  338. 'make_shared_for_overwrite',
  339. 'make_tuple',
  340. 'make_unique',
  341. 'malloc',
  342. 'memchr',
  343. 'memcmp',
  344. 'memcpy',
  345. 'memset',
  346. 'modf',
  347. 'move',
  348. 'pow',
  349. 'printf',
  350. 'putchar',
  351. 'puts',
  352. 'realloc',
  353. 'scanf',
  354. 'sin',
  355. 'sinh',
  356. 'snprintf',
  357. 'sprintf',
  358. 'sqrt',
  359. 'sscanf',
  360. 'std',
  361. 'stderr',
  362. 'stdin',
  363. 'stdout',
  364. 'strcat',
  365. 'strchr',
  366. 'strcmp',
  367. 'strcpy',
  368. 'strcspn',
  369. 'strlen',
  370. 'strncat',
  371. 'strncmp',
  372. 'strncpy',
  373. 'strpbrk',
  374. 'strrchr',
  375. 'strspn',
  376. 'strstr',
  377. 'swap',
  378. 'tan',
  379. 'tanh',
  380. 'terminate',
  381. 'to_underlying',
  382. 'tolower',
  383. 'toupper',
  384. 'vfprintf',
  385. 'visit',
  386. 'vprintf',
  387. 'vsprintf'
  388. ];
  389. const LITERALS = [
  390. 'NULL',
  391. 'false',
  392. 'nullopt',
  393. 'nullptr',
  394. 'true'
  395. ];
  396. // https://en.cppreference.com/w/cpp/keyword
  397. const BUILT_IN = [ '_Pragma' ];
  398. const CPP_KEYWORDS = {
  399. type: RESERVED_TYPES,
  400. keyword: RESERVED_KEYWORDS,
  401. literal: LITERALS,
  402. built_in: BUILT_IN,
  403. _type_hints: TYPE_HINTS
  404. };
  405. const FUNCTION_DISPATCH = {
  406. className: 'function.dispatch',
  407. relevance: 0,
  408. keywords: {
  409. // Only for relevance, not highlighting.
  410. _hint: FUNCTION_HINTS },
  411. begin: regex.concat(
  412. /\b/,
  413. /(?!decltype)/,
  414. /(?!if)/,
  415. /(?!for)/,
  416. /(?!switch)/,
  417. /(?!while)/,
  418. hljs.IDENT_RE,
  419. regex.lookahead(/(<[^<>]+>|)\s*\(/))
  420. };
  421. const EXPRESSION_CONTAINS = [
  422. FUNCTION_DISPATCH,
  423. PREPROCESSOR,
  424. CPP_PRIMITIVE_TYPES,
  425. C_LINE_COMMENT_MODE,
  426. hljs.C_BLOCK_COMMENT_MODE,
  427. NUMBERS,
  428. STRINGS
  429. ];
  430. const EXPRESSION_CONTEXT = {
  431. // This mode covers expression context where we can't expect a function
  432. // definition and shouldn't highlight anything that looks like one:
  433. // `return some()`, `else if()`, `(x*sum(1, 2))`
  434. variants: [
  435. {
  436. begin: /=/,
  437. end: /;/
  438. },
  439. {
  440. begin: /\(/,
  441. end: /\)/
  442. },
  443. {
  444. beginKeywords: 'new throw return else',
  445. end: /;/
  446. }
  447. ],
  448. keywords: CPP_KEYWORDS,
  449. contains: EXPRESSION_CONTAINS.concat([
  450. {
  451. begin: /\(/,
  452. end: /\)/,
  453. keywords: CPP_KEYWORDS,
  454. contains: EXPRESSION_CONTAINS.concat([ 'self' ]),
  455. relevance: 0
  456. }
  457. ]),
  458. relevance: 0
  459. };
  460. const FUNCTION_DECLARATION = {
  461. className: 'function',
  462. begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
  463. returnBegin: true,
  464. end: /[{;=]/,
  465. excludeEnd: true,
  466. keywords: CPP_KEYWORDS,
  467. illegal: /[^\w\s\*&:<>.]/,
  468. contains: [
  469. { // to prevent it from being confused as the function title
  470. begin: DECLTYPE_AUTO_RE,
  471. keywords: CPP_KEYWORDS,
  472. relevance: 0
  473. },
  474. {
  475. begin: FUNCTION_TITLE,
  476. returnBegin: true,
  477. contains: [ TITLE_MODE ],
  478. relevance: 0
  479. },
  480. // needed because we do not have look-behind on the below rule
  481. // to prevent it from grabbing the final : in a :: pair
  482. {
  483. begin: /::/,
  484. relevance: 0
  485. },
  486. // initializers
  487. {
  488. begin: /:/,
  489. endsWithParent: true,
  490. contains: [
  491. STRINGS,
  492. NUMBERS
  493. ]
  494. },
  495. // allow for multiple declarations, e.g.:
  496. // extern void f(int), g(char);
  497. {
  498. relevance: 0,
  499. match: /,/
  500. },
  501. {
  502. className: 'params',
  503. begin: /\(/,
  504. end: /\)/,
  505. keywords: CPP_KEYWORDS,
  506. relevance: 0,
  507. contains: [
  508. C_LINE_COMMENT_MODE,
  509. hljs.C_BLOCK_COMMENT_MODE,
  510. STRINGS,
  511. NUMBERS,
  512. CPP_PRIMITIVE_TYPES,
  513. // Count matching parentheses.
  514. {
  515. begin: /\(/,
  516. end: /\)/,
  517. keywords: CPP_KEYWORDS,
  518. relevance: 0,
  519. contains: [
  520. 'self',
  521. C_LINE_COMMENT_MODE,
  522. hljs.C_BLOCK_COMMENT_MODE,
  523. STRINGS,
  524. NUMBERS,
  525. CPP_PRIMITIVE_TYPES
  526. ]
  527. }
  528. ]
  529. },
  530. CPP_PRIMITIVE_TYPES,
  531. C_LINE_COMMENT_MODE,
  532. hljs.C_BLOCK_COMMENT_MODE,
  533. PREPROCESSOR
  534. ]
  535. };
  536. return {
  537. name: 'C++',
  538. aliases: [
  539. 'cc',
  540. 'c++',
  541. 'h++',
  542. 'hpp',
  543. 'hh',
  544. 'hxx',
  545. 'cxx'
  546. ],
  547. keywords: CPP_KEYWORDS,
  548. illegal: '</',
  549. classNameAliases: { 'function.dispatch': 'built_in' },
  550. contains: [].concat(
  551. EXPRESSION_CONTEXT,
  552. FUNCTION_DECLARATION,
  553. FUNCTION_DISPATCH,
  554. EXPRESSION_CONTAINS,
  555. [
  556. PREPROCESSOR,
  557. { // containers: ie, `vector <int> rooms (9);`
  558. 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|flat_map|flat_set)\\s*<(?!<)',
  559. end: '>',
  560. keywords: CPP_KEYWORDS,
  561. contains: [
  562. 'self',
  563. CPP_PRIMITIVE_TYPES
  564. ]
  565. },
  566. {
  567. begin: hljs.IDENT_RE + '::',
  568. keywords: CPP_KEYWORDS
  569. },
  570. {
  571. match: [
  572. // extra complexity to deal with `enum class` and `enum struct`
  573. /\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,
  574. /\s+/,
  575. /\w+/
  576. ],
  577. className: {
  578. 1: 'keyword',
  579. 3: 'title.class'
  580. }
  581. }
  582. ])
  583. };
  584. }
  585. export { cpp as default };