UNPKG

8.09 kBJavaScriptView Raw
1/*
2Language: C
3Category: common, system
4Website: https://en.wikipedia.org/wiki/C_(programming_language)
5*/
6
7/** @type LanguageFn */
8function c(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 = '(' +
24 DECLTYPE_AUTO_RE + '|' +
25 regex.optional(NAMESPACE_RE) +
26 '[a-zA-Z_]\\w*' + regex.optional(TEMPLATE_ARGUMENT_RE) +
27 ')';
28
29
30 const TYPES = {
31 className: 'type',
32 variants: [
33 { begin: '\\b[a-z\\d_]*_t\\b' },
34 { match: /\batomic_[a-z]{3,6}\b/}
35 ]
36
37 };
38
39 // https://en.cppreference.com/w/cpp/language/escape
40 // \\ \x \xFF \u2837 \u00323747 \374
41 const CHARACTER_ESCAPES = '\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)';
42 const STRINGS = {
43 className: 'string',
44 variants: [
45 {
46 begin: '(u8?|U|L)?"',
47 end: '"',
48 illegal: '\\n',
49 contains: [ hljs.BACKSLASH_ESCAPE ]
50 },
51 {
52 begin: '(u8?|U|L)?\'(' + CHARACTER_ESCAPES + "|.)",
53 end: '\'',
54 illegal: '.'
55 },
56 hljs.END_SAME_AS_BEGIN({
57 begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
58 end: /\)([^()\\ ]{0,16})"/
59 })
60 ]
61 };
62
63 const NUMBERS = {
64 className: 'number',
65 variants: [
66 {
67 begin: '\\b(0b[01\']+)'
68 },
69 {
70 begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)'
71 },
72 {
73 begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)'
74 }
75 ],
76 relevance: 0
77 };
78
79 const PREPROCESSOR = {
80 className: 'meta',
81 begin: /#\s*[a-z]+\b/,
82 end: /$/,
83 keywords: {
84 keyword:
85 'if else elif endif define undef warning error line ' +
86 'pragma _Pragma ifdef ifndef include'
87 },
88 contains: [
89 {
90 begin: /\\\n/,
91 relevance: 0
92 },
93 hljs.inherit(STRINGS, {
94 className: 'string'
95 }),
96 {
97 className: 'string',
98 begin: /<.*?>/
99 },
100 C_LINE_COMMENT_MODE,
101 hljs.C_BLOCK_COMMENT_MODE
102 ]
103 };
104
105 const TITLE_MODE = {
106 className: 'title',
107 begin: regex.optional(NAMESPACE_RE) + hljs.IDENT_RE,
108 relevance: 0
109 };
110
111 const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
112
113 const C_KEYWORDS = [
114 "asm",
115 "auto",
116 "break",
117 "case",
118 "continue",
119 "default",
120 "do",
121 "else",
122 "enum",
123 "extern",
124 "for",
125 "fortran",
126 "goto",
127 "if",
128 "inline",
129 "register",
130 "restrict",
131 "return",
132 "sizeof",
133 "struct",
134 "switch",
135 "typedef",
136 "union",
137 "volatile",
138 "while",
139 "_Alignas",
140 "_Alignof",
141 "_Atomic",
142 "_Generic",
143 "_Noreturn",
144 "_Static_assert",
145 "_Thread_local",
146 // aliases
147 "alignas",
148 "alignof",
149 "noreturn",
150 "static_assert",
151 "thread_local",
152 // not a C keyword but is, for all intents and purposes, treated exactly like one.
153 "_Pragma"
154 ];
155
156 const C_TYPES = [
157 "float",
158 "double",
159 "signed",
160 "unsigned",
161 "int",
162 "short",
163 "long",
164 "char",
165 "void",
166 "_Bool",
167 "_Complex",
168 "_Imaginary",
169 "_Decimal32",
170 "_Decimal64",
171 "_Decimal128",
172 // modifiers
173 "const",
174 "static",
175 // aliases
176 "complex",
177 "bool",
178 "imaginary"
179 ];
180
181 const KEYWORDS = {
182 keyword: C_KEYWORDS,
183 type: C_TYPES,
184 literal: 'true false NULL',
185 // TODO: apply hinting work similar to what was done in cpp.js
186 built_in: 'std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' +
187 'auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set ' +
188 'unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos ' +
189 'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' +
190 'fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' +
191 'isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow ' +
192 'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' +
193 'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' +
194 'vfprintf vprintf vsprintf endl initializer_list unique_ptr',
195 };
196
197 const EXPRESSION_CONTAINS = [
198 PREPROCESSOR,
199 TYPES,
200 C_LINE_COMMENT_MODE,
201 hljs.C_BLOCK_COMMENT_MODE,
202 NUMBERS,
203 STRINGS
204 ];
205
206 const EXPRESSION_CONTEXT = {
207 // This mode covers expression context where we can't expect a function
208 // definition and shouldn't highlight anything that looks like one:
209 // `return some()`, `else if()`, `(x*sum(1, 2))`
210 variants: [
211 {
212 begin: /=/,
213 end: /;/
214 },
215 {
216 begin: /\(/,
217 end: /\)/
218 },
219 {
220 beginKeywords: 'new throw return else',
221 end: /;/
222 }
223 ],
224 keywords: KEYWORDS,
225 contains: EXPRESSION_CONTAINS.concat([
226 {
227 begin: /\(/,
228 end: /\)/,
229 keywords: KEYWORDS,
230 contains: EXPRESSION_CONTAINS.concat([ 'self' ]),
231 relevance: 0
232 }
233 ]),
234 relevance: 0
235 };
236
237 const FUNCTION_DECLARATION = {
238 begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
239 returnBegin: true,
240 end: /[{;=]/,
241 excludeEnd: true,
242 keywords: KEYWORDS,
243 illegal: /[^\w\s\*&:<>.]/,
244 contains: [
245 { // to prevent it from being confused as the function title
246 begin: DECLTYPE_AUTO_RE,
247 keywords: KEYWORDS,
248 relevance: 0
249 },
250 {
251 begin: FUNCTION_TITLE,
252 returnBegin: true,
253 contains: [
254 hljs.inherit(TITLE_MODE, { className: "title.function" })
255 ],
256 relevance: 0
257 },
258 // allow for multiple declarations, e.g.:
259 // extern void f(int), g(char);
260 {
261 relevance: 0,
262 match: /,/
263 },
264 {
265 className: 'params',
266 begin: /\(/,
267 end: /\)/,
268 keywords: KEYWORDS,
269 relevance: 0,
270 contains: [
271 C_LINE_COMMENT_MODE,
272 hljs.C_BLOCK_COMMENT_MODE,
273 STRINGS,
274 NUMBERS,
275 TYPES,
276 // Count matching parentheses.
277 {
278 begin: /\(/,
279 end: /\)/,
280 keywords: KEYWORDS,
281 relevance: 0,
282 contains: [
283 'self',
284 C_LINE_COMMENT_MODE,
285 hljs.C_BLOCK_COMMENT_MODE,
286 STRINGS,
287 NUMBERS,
288 TYPES
289 ]
290 }
291 ]
292 },
293 TYPES,
294 C_LINE_COMMENT_MODE,
295 hljs.C_BLOCK_COMMENT_MODE,
296 PREPROCESSOR
297 ]
298 };
299
300 return {
301 name: "C",
302 aliases: [
303 'h'
304 ],
305 keywords: KEYWORDS,
306 // Until differentiations are added between `c` and `cpp`, `c` will
307 // not be auto-detected to avoid auto-detect conflicts between C and C++
308 disableAutodetect: true,
309 illegal: '</',
310 contains: [].concat(
311 EXPRESSION_CONTEXT,
312 FUNCTION_DECLARATION,
313 EXPRESSION_CONTAINS,
314 [
315 PREPROCESSOR,
316 {
317 begin: hljs.IDENT_RE + '::',
318 keywords: KEYWORDS
319 },
320 {
321 className: 'class',
322 beginKeywords: 'enum class struct union',
323 end: /[{;:<>=]/,
324 contains: [
325 {
326 beginKeywords: "final class struct"
327 },
328 hljs.TITLE_MODE
329 ]
330 }
331 ]),
332 exports: {
333 preprocessor: PREPROCESSOR,
334 strings: STRINGS,
335 keywords: KEYWORDS
336 }
337 };
338}
339
340export { c as default };