UNPKG

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