c-like.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /**
  2. * @param {string} value
  3. * @returns {RegExp}
  4. * */
  5. /**
  6. * @param {RegExp | string } re
  7. * @returns {string}
  8. */
  9. function source(re) {
  10. if (!re) return null;
  11. if (typeof re === "string") return re;
  12. return re.source;
  13. }
  14. /**
  15. * @param {RegExp | string } re
  16. * @returns {string}
  17. */
  18. function lookahead(re) {
  19. return concat('(?=', re, ')');
  20. }
  21. /**
  22. * @param {RegExp | string } re
  23. * @returns {string}
  24. */
  25. function optional(re) {
  26. return concat('(', re, ')?');
  27. }
  28. /**
  29. * @param {...(RegExp | string) } args
  30. * @returns {string}
  31. */
  32. function concat(...args) {
  33. const joined = args.map((x) => source(x)).join("");
  34. return joined;
  35. }
  36. /*
  37. Language: C++
  38. Category: common, system
  39. Website: https://isocpp.org
  40. */
  41. /** @type LanguageFn */
  42. function cPlusPlus(hljs) {
  43. // added for historic reasons because `hljs.C_LINE_COMMENT_MODE` does
  44. // not include such support nor can we be sure all the grammars depending
  45. // on it would desire this behavior
  46. const C_LINE_COMMENT_MODE = hljs.COMMENT('//', '$', {
  47. contains: [
  48. {
  49. begin: /\\\n/
  50. }
  51. ]
  52. });
  53. const DECLTYPE_AUTO_RE = 'decltype\\(auto\\)';
  54. const NAMESPACE_RE = '[a-zA-Z_]\\w*::';
  55. const TEMPLATE_ARGUMENT_RE = '<[^<>]+>';
  56. const FUNCTION_TYPE_RE = '(' +
  57. DECLTYPE_AUTO_RE + '|' +
  58. optional(NAMESPACE_RE) +
  59. '[a-zA-Z_]\\w*' + optional(TEMPLATE_ARGUMENT_RE) +
  60. ')';
  61. const CPP_PRIMITIVE_TYPES = {
  62. className: 'keyword',
  63. begin: '\\b[a-z\\d_]*_t\\b'
  64. };
  65. // https://en.cppreference.com/w/cpp/language/escape
  66. // \\ \x \xFF \u2837 \u00323747 \374
  67. const CHARACTER_ESCAPES = '\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)';
  68. const STRINGS = {
  69. className: 'string',
  70. variants: [
  71. {
  72. begin: '(u8?|U|L)?"',
  73. end: '"',
  74. illegal: '\\n',
  75. contains: [ hljs.BACKSLASH_ESCAPE ]
  76. },
  77. {
  78. begin: '(u8?|U|L)?\'(' + CHARACTER_ESCAPES + "|.)",
  79. end: '\'',
  80. illegal: '.'
  81. },
  82. hljs.END_SAME_AS_BEGIN({
  83. begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
  84. end: /\)([^()\\ ]{0,16})"/
  85. })
  86. ]
  87. };
  88. const NUMBERS = {
  89. className: 'number',
  90. variants: [
  91. {
  92. begin: '\\b(0b[01\']+)'
  93. },
  94. {
  95. begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)'
  96. },
  97. {
  98. begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)'
  99. }
  100. ],
  101. relevance: 0
  102. };
  103. const PREPROCESSOR = {
  104. className: 'meta',
  105. begin: /#\s*[a-z]+\b/,
  106. end: /$/,
  107. keywords: {
  108. 'meta-keyword':
  109. 'if else elif endif define undef warning error line ' +
  110. 'pragma _Pragma ifdef ifndef include'
  111. },
  112. contains: [
  113. {
  114. begin: /\\\n/,
  115. relevance: 0
  116. },
  117. hljs.inherit(STRINGS, {
  118. className: 'meta-string'
  119. }),
  120. {
  121. className: 'meta-string',
  122. begin: /<.*?>/
  123. },
  124. C_LINE_COMMENT_MODE,
  125. hljs.C_BLOCK_COMMENT_MODE
  126. ]
  127. };
  128. const TITLE_MODE = {
  129. className: 'title',
  130. begin: optional(NAMESPACE_RE) + hljs.IDENT_RE,
  131. relevance: 0
  132. };
  133. const FUNCTION_TITLE = optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
  134. const COMMON_CPP_HINTS = [
  135. 'asin',
  136. 'atan2',
  137. 'atan',
  138. 'calloc',
  139. 'ceil',
  140. 'cosh',
  141. 'cos',
  142. 'exit',
  143. 'exp',
  144. 'fabs',
  145. 'floor',
  146. 'fmod',
  147. 'fprintf',
  148. 'fputs',
  149. 'free',
  150. 'frexp',
  151. 'auto_ptr',
  152. 'deque',
  153. 'list',
  154. 'queue',
  155. 'stack',
  156. 'vector',
  157. 'map',
  158. 'set',
  159. 'pair',
  160. 'bitset',
  161. 'multiset',
  162. 'multimap',
  163. 'unordered_set',
  164. 'fscanf',
  165. 'future',
  166. 'isalnum',
  167. 'isalpha',
  168. 'iscntrl',
  169. 'isdigit',
  170. 'isgraph',
  171. 'islower',
  172. 'isprint',
  173. 'ispunct',
  174. 'isspace',
  175. 'isupper',
  176. 'isxdigit',
  177. 'tolower',
  178. 'toupper',
  179. 'labs',
  180. 'ldexp',
  181. 'log10',
  182. 'log',
  183. 'malloc',
  184. 'realloc',
  185. 'memchr',
  186. 'memcmp',
  187. 'memcpy',
  188. 'memset',
  189. 'modf',
  190. 'pow',
  191. 'printf',
  192. 'putchar',
  193. 'puts',
  194. 'scanf',
  195. 'sinh',
  196. 'sin',
  197. 'snprintf',
  198. 'sprintf',
  199. 'sqrt',
  200. 'sscanf',
  201. 'strcat',
  202. 'strchr',
  203. 'strcmp',
  204. 'strcpy',
  205. 'strcspn',
  206. 'strlen',
  207. 'strncat',
  208. 'strncmp',
  209. 'strncpy',
  210. 'strpbrk',
  211. 'strrchr',
  212. 'strspn',
  213. 'strstr',
  214. 'tanh',
  215. 'tan',
  216. 'unordered_map',
  217. 'unordered_multiset',
  218. 'unordered_multimap',
  219. 'priority_queue',
  220. 'make_pair',
  221. 'array',
  222. 'shared_ptr',
  223. 'abort',
  224. 'terminate',
  225. 'abs',
  226. 'acos',
  227. 'vfprintf',
  228. 'vprintf',
  229. 'vsprintf',
  230. 'endl',
  231. 'initializer_list',
  232. 'unique_ptr',
  233. 'complex',
  234. 'imaginary',
  235. 'std',
  236. 'string',
  237. 'wstring',
  238. 'cin',
  239. 'cout',
  240. 'cerr',
  241. 'clog',
  242. 'stdin',
  243. 'stdout',
  244. 'stderr',
  245. 'stringstream',
  246. 'istringstream',
  247. 'ostringstream'
  248. ];
  249. const CPP_KEYWORDS = {
  250. keyword: 'int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof ' +
  251. 'dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace ' +
  252. 'unsigned long volatile static protected bool template mutable if public friend ' +
  253. 'do goto auto void enum else break extern using asm case typeid wchar_t ' +
  254. 'short reinterpret_cast|10 default double register explicit signed typename try this ' +
  255. 'switch continue inline delete alignas alignof constexpr consteval constinit decltype ' +
  256. 'concept co_await co_return co_yield requires ' +
  257. 'noexcept static_assert thread_local restrict final override ' +
  258. 'atomic_bool atomic_char atomic_schar ' +
  259. 'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' +
  260. 'atomic_ullong new throw return ' +
  261. 'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq',
  262. built_in: '_Bool _Complex _Imaginary',
  263. _relevance_hints: COMMON_CPP_HINTS,
  264. literal: 'true false nullptr NULL'
  265. };
  266. const FUNCTION_DISPATCH = {
  267. className: "function.dispatch",
  268. relevance: 0,
  269. keywords: CPP_KEYWORDS,
  270. begin: concat(
  271. /\b/,
  272. /(?!decltype)/,
  273. /(?!if)/,
  274. /(?!for)/,
  275. /(?!while)/,
  276. hljs.IDENT_RE,
  277. lookahead(/\s*\(/))
  278. };
  279. const EXPRESSION_CONTAINS = [
  280. FUNCTION_DISPATCH,
  281. PREPROCESSOR,
  282. CPP_PRIMITIVE_TYPES,
  283. C_LINE_COMMENT_MODE,
  284. hljs.C_BLOCK_COMMENT_MODE,
  285. NUMBERS,
  286. STRINGS
  287. ];
  288. const EXPRESSION_CONTEXT = {
  289. // This mode covers expression context where we can't expect a function
  290. // definition and shouldn't highlight anything that looks like one:
  291. // `return some()`, `else if()`, `(x*sum(1, 2))`
  292. variants: [
  293. {
  294. begin: /=/,
  295. end: /;/
  296. },
  297. {
  298. begin: /\(/,
  299. end: /\)/
  300. },
  301. {
  302. beginKeywords: 'new throw return else',
  303. end: /;/
  304. }
  305. ],
  306. keywords: CPP_KEYWORDS,
  307. contains: EXPRESSION_CONTAINS.concat([
  308. {
  309. begin: /\(/,
  310. end: /\)/,
  311. keywords: CPP_KEYWORDS,
  312. contains: EXPRESSION_CONTAINS.concat([ 'self' ]),
  313. relevance: 0
  314. }
  315. ]),
  316. relevance: 0
  317. };
  318. const FUNCTION_DECLARATION = {
  319. className: 'function',
  320. begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
  321. returnBegin: true,
  322. end: /[{;=]/,
  323. excludeEnd: true,
  324. keywords: CPP_KEYWORDS,
  325. illegal: /[^\w\s\*&:<>.]/,
  326. contains: [
  327. { // to prevent it from being confused as the function title
  328. begin: DECLTYPE_AUTO_RE,
  329. keywords: CPP_KEYWORDS,
  330. relevance: 0
  331. },
  332. {
  333. begin: FUNCTION_TITLE,
  334. returnBegin: true,
  335. contains: [ TITLE_MODE ],
  336. relevance: 0
  337. },
  338. // needed because we do not have look-behind on the below rule
  339. // to prevent it from grabbing the final : in a :: pair
  340. {
  341. begin: /::/,
  342. relevance: 0
  343. },
  344. // initializers
  345. {
  346. begin: /:/,
  347. endsWithParent: true,
  348. contains: [
  349. STRINGS,
  350. NUMBERS
  351. ]
  352. },
  353. {
  354. className: 'params',
  355. begin: /\(/,
  356. end: /\)/,
  357. keywords: CPP_KEYWORDS,
  358. relevance: 0,
  359. contains: [
  360. C_LINE_COMMENT_MODE,
  361. hljs.C_BLOCK_COMMENT_MODE,
  362. STRINGS,
  363. NUMBERS,
  364. CPP_PRIMITIVE_TYPES,
  365. // Count matching parentheses.
  366. {
  367. begin: /\(/,
  368. end: /\)/,
  369. keywords: CPP_KEYWORDS,
  370. relevance: 0,
  371. contains: [
  372. 'self',
  373. C_LINE_COMMENT_MODE,
  374. hljs.C_BLOCK_COMMENT_MODE,
  375. STRINGS,
  376. NUMBERS,
  377. CPP_PRIMITIVE_TYPES
  378. ]
  379. }
  380. ]
  381. },
  382. CPP_PRIMITIVE_TYPES,
  383. C_LINE_COMMENT_MODE,
  384. hljs.C_BLOCK_COMMENT_MODE,
  385. PREPROCESSOR
  386. ]
  387. };
  388. return {
  389. name: 'C++',
  390. aliases: [
  391. 'cc',
  392. 'c++',
  393. 'h++',
  394. 'hpp',
  395. 'hh',
  396. 'hxx',
  397. 'cxx'
  398. ],
  399. keywords: CPP_KEYWORDS,
  400. illegal: '</',
  401. classNameAliases: {
  402. "function.dispatch": "built_in"
  403. },
  404. contains: [].concat(
  405. EXPRESSION_CONTEXT,
  406. FUNCTION_DECLARATION,
  407. FUNCTION_DISPATCH,
  408. EXPRESSION_CONTAINS,
  409. [
  410. PREPROCESSOR,
  411. { // containers: ie, `vector <int> rooms (9);`
  412. begin: '\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<',
  413. end: '>',
  414. keywords: CPP_KEYWORDS,
  415. contains: [
  416. 'self',
  417. CPP_PRIMITIVE_TYPES
  418. ]
  419. },
  420. {
  421. begin: hljs.IDENT_RE + '::',
  422. keywords: CPP_KEYWORDS
  423. },
  424. {
  425. className: 'class',
  426. beginKeywords: 'enum class struct union',
  427. end: /[{;:<>=]/,
  428. contains: [
  429. {
  430. beginKeywords: "final class struct"
  431. },
  432. hljs.TITLE_MODE
  433. ]
  434. }
  435. ]),
  436. exports: {
  437. preprocessor: PREPROCESSOR,
  438. strings: STRINGS,
  439. keywords: CPP_KEYWORDS
  440. }
  441. };
  442. }
  443. /*
  444. Language: C-like (deprecated, use C and C++ instead)
  445. Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
  446. Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Zaven Muradyan <megalivoithos@gmail.com>, Roel Deckers <admin@codingcat.nl>, Sam Wu <samsam2310@gmail.com>, Jordi Petit <jordi.petit@gmail.com>, Pieter Vantorre <pietervantorre@gmail.com>, Google Inc. (David Benjamin) <davidben@google.com>
  447. */
  448. /** @type LanguageFn */
  449. function cLike(hljs) {
  450. const lang = cPlusPlus(hljs);
  451. const C_ALIASES = [
  452. "c",
  453. "h"
  454. ];
  455. const CPP_ALIASES = [
  456. 'cc',
  457. 'c++',
  458. 'h++',
  459. 'hpp',
  460. 'hh',
  461. 'hxx',
  462. 'cxx'
  463. ];
  464. lang.disableAutodetect = true;
  465. lang.aliases = [];
  466. // support users only loading c-like (legacy)
  467. if (!hljs.getLanguage("c")) lang.aliases.push(...C_ALIASES);
  468. if (!hljs.getLanguage("cpp")) lang.aliases.push(...CPP_ALIASES);
  469. // if c and cpp are loaded after then they will reclaim these
  470. // aliases for themselves
  471. return lang;
  472. }
  473. module.exports = cLike;