UNPKG

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