c-like.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. Language: C-like foundation grammar for C/C++ grammars
  3. Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
  4. 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>
  5. Category: common, system
  6. */
  7. /* In the future the intention is to split out the C/C++ grammars distinctly
  8. since they are separate languages. They will likely share a common foundation
  9. though, and this file sets the groundwork for that - so that we get the breaking
  10. change in v10 and don't have to change the requirements again later.
  11. See: https://github.com/highlightjs/highlight.js/issues/2146
  12. */
  13. /** @type LanguageFn */
  14. function cLike(hljs) {
  15. function optional(s) {
  16. return '(?:' + s + ')?';
  17. }
  18. var DECLTYPE_AUTO_RE = 'decltype\\(auto\\)';
  19. var NAMESPACE_RE = '[a-zA-Z_]\\w*::';
  20. var TEMPLATE_ARGUMENT_RE = '<.*?>';
  21. var FUNCTION_TYPE_RE = '(' +
  22. DECLTYPE_AUTO_RE + '|' +
  23. optional(NAMESPACE_RE) +'[a-zA-Z_]\\w*' + optional(TEMPLATE_ARGUMENT_RE) +
  24. ')';
  25. var CPP_PRIMITIVE_TYPES = {
  26. className: 'keyword',
  27. begin: '\\b[a-z\\d_]*_t\\b'
  28. };
  29. // https://en.cppreference.com/w/cpp/language/escape
  30. // \\ \x \xFF \u2837 \u00323747 \374
  31. var CHARACTER_ESCAPES = '\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)';
  32. var STRINGS = {
  33. className: 'string',
  34. variants: [
  35. {
  36. begin: '(u8?|U|L)?"', end: '"',
  37. illegal: '\\n',
  38. contains: [hljs.BACKSLASH_ESCAPE]
  39. },
  40. {
  41. begin: '(u8?|U|L)?\'(' + CHARACTER_ESCAPES + "|.)", end: '\'',
  42. illegal: '.'
  43. },
  44. hljs.END_SAME_AS_BEGIN({
  45. begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
  46. end: /\)([^()\\ ]{0,16})"/,
  47. })
  48. ]
  49. };
  50. var NUMBERS = {
  51. className: 'number',
  52. variants: [
  53. { begin: '\\b(0b[01\']+)' },
  54. { begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)(u|U|l|L|ul|UL|f|F|b|B)' },
  55. { begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)' }
  56. ],
  57. relevance: 0
  58. };
  59. var PREPROCESSOR = {
  60. className: 'meta',
  61. begin: /#\s*[a-z]+\b/, end: /$/,
  62. keywords: {
  63. 'meta-keyword':
  64. 'if else elif endif define undef warning error line ' +
  65. 'pragma _Pragma ifdef ifndef include'
  66. },
  67. contains: [
  68. {
  69. begin: /\\\n/, relevance: 0
  70. },
  71. hljs.inherit(STRINGS, {className: 'meta-string'}),
  72. {
  73. className: 'meta-string',
  74. begin: /<.*?>/, end: /$/,
  75. illegal: '\\n',
  76. },
  77. hljs.C_LINE_COMMENT_MODE,
  78. hljs.C_BLOCK_COMMENT_MODE
  79. ]
  80. };
  81. var TITLE_MODE = {
  82. className: 'title',
  83. begin: optional(NAMESPACE_RE) + hljs.IDENT_RE,
  84. relevance: 0
  85. };
  86. var FUNCTION_TITLE = optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
  87. var CPP_KEYWORDS = {
  88. keyword: 'int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof ' +
  89. 'dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace ' +
  90. 'unsigned long volatile static protected bool template mutable if public friend ' +
  91. 'do goto auto void enum else break extern using asm case typeid wchar_t ' +
  92. 'short reinterpret_cast|10 default double register explicit signed typename try this ' +
  93. 'switch continue inline delete alignas alignof constexpr consteval constinit decltype ' +
  94. 'concept co_await co_return co_yield requires ' +
  95. 'noexcept static_assert thread_local restrict final override ' +
  96. 'atomic_bool atomic_char atomic_schar ' +
  97. 'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' +
  98. 'atomic_ullong new throw return ' +
  99. 'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq',
  100. built_in: 'std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' +
  101. 'auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set ' +
  102. 'unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos ' +
  103. 'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' +
  104. 'fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' +
  105. 'isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow ' +
  106. 'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' +
  107. 'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' +
  108. 'vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary',
  109. literal: 'true false nullptr NULL'
  110. };
  111. var EXPRESSION_CONTAINS = [
  112. CPP_PRIMITIVE_TYPES,
  113. hljs.C_LINE_COMMENT_MODE,
  114. hljs.C_BLOCK_COMMENT_MODE,
  115. NUMBERS,
  116. STRINGS
  117. ];
  118. var EXPRESSION_CONTEXT = {
  119. // This mode covers expression context where we can't expect a function
  120. // definition and shouldn't highlight anything that looks like one:
  121. // `return some()`, `else if()`, `(x*sum(1, 2))`
  122. variants: [
  123. {begin: /=/, end: /;/},
  124. {begin: /\(/, end: /\)/},
  125. {beginKeywords: 'new throw return else', end: /;/}
  126. ],
  127. keywords: CPP_KEYWORDS,
  128. contains: EXPRESSION_CONTAINS.concat([
  129. {
  130. begin: /\(/, end: /\)/,
  131. keywords: CPP_KEYWORDS,
  132. contains: EXPRESSION_CONTAINS.concat(['self']),
  133. relevance: 0
  134. }
  135. ]),
  136. relevance: 0
  137. };
  138. var FUNCTION_DECLARATION = {
  139. className: 'function',
  140. begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
  141. returnBegin: true, end: /[{;=]/,
  142. excludeEnd: true,
  143. keywords: CPP_KEYWORDS,
  144. illegal: /[^\w\s\*&:<>]/,
  145. contains: [
  146. { // to prevent it from being confused as the function title
  147. begin: DECLTYPE_AUTO_RE,
  148. keywords: CPP_KEYWORDS,
  149. relevance: 0,
  150. },
  151. {
  152. begin: FUNCTION_TITLE, returnBegin: true,
  153. contains: [TITLE_MODE],
  154. relevance: 0
  155. },
  156. {
  157. className: 'params',
  158. begin: /\(/, end: /\)/,
  159. keywords: CPP_KEYWORDS,
  160. relevance: 0,
  161. contains: [
  162. hljs.C_LINE_COMMENT_MODE,
  163. hljs.C_BLOCK_COMMENT_MODE,
  164. STRINGS,
  165. NUMBERS,
  166. CPP_PRIMITIVE_TYPES,
  167. // Count matching parentheses.
  168. {
  169. begin: /\(/, end: /\)/,
  170. keywords: CPP_KEYWORDS,
  171. relevance: 0,
  172. contains: [
  173. 'self',
  174. hljs.C_LINE_COMMENT_MODE,
  175. hljs.C_BLOCK_COMMENT_MODE,
  176. STRINGS,
  177. NUMBERS,
  178. CPP_PRIMITIVE_TYPES
  179. ]
  180. }
  181. ]
  182. },
  183. CPP_PRIMITIVE_TYPES,
  184. hljs.C_LINE_COMMENT_MODE,
  185. hljs.C_BLOCK_COMMENT_MODE,
  186. PREPROCESSOR
  187. ]
  188. };
  189. return {
  190. aliases: ['c', 'cc', 'h', 'c++', 'h++', 'hpp', 'hh', 'hxx', 'cxx'],
  191. keywords: CPP_KEYWORDS,
  192. // the base c-like language will NEVER be auto-detected, rather the
  193. // derivitives: c, c++, arduino turn auto-detect back on for themselves
  194. disableAutodetect: true,
  195. illegal: '</',
  196. contains: [].concat(
  197. EXPRESSION_CONTEXT,
  198. FUNCTION_DECLARATION,
  199. EXPRESSION_CONTAINS,
  200. [
  201. PREPROCESSOR,
  202. { // containers: ie, `vector <int> rooms (9);`
  203. 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*<', end: '>',
  204. keywords: CPP_KEYWORDS,
  205. contains: ['self', CPP_PRIMITIVE_TYPES]
  206. },
  207. {
  208. begin: hljs.IDENT_RE + '::',
  209. keywords: CPP_KEYWORDS
  210. },
  211. {
  212. className: 'class',
  213. beginKeywords: 'class struct', end: /[{;:]/,
  214. contains: [
  215. {begin: /</, end: />/, contains: ['self']}, // skip generic stuff
  216. hljs.TITLE_MODE
  217. ]
  218. }
  219. ]),
  220. exports: {
  221. preprocessor: PREPROCESSOR,
  222. strings: STRINGS,
  223. keywords: CPP_KEYWORDS
  224. }
  225. };
  226. }
  227. module.exports = cLike;