cpp.js 11 KB

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