UNPKG

8.92 kBJavaScriptView Raw
1/*
2Language: Perl
3Author: Peter Leonov <gojpeg@yandex.ru>
4Website: https://www.perl.org
5Category: common
6*/
7
8/** @type LanguageFn */
9function perl(hljs) {
10 const regex = hljs.regex;
11 const KEYWORDS = [
12 'abs',
13 'accept',
14 'alarm',
15 'and',
16 'atan2',
17 'bind',
18 'binmode',
19 'bless',
20 'break',
21 'caller',
22 'chdir',
23 'chmod',
24 'chomp',
25 'chop',
26 'chown',
27 'chr',
28 'chroot',
29 'close',
30 'closedir',
31 'connect',
32 'continue',
33 'cos',
34 'crypt',
35 'dbmclose',
36 'dbmopen',
37 'defined',
38 'delete',
39 'die',
40 'do',
41 'dump',
42 'each',
43 'else',
44 'elsif',
45 'endgrent',
46 'endhostent',
47 'endnetent',
48 'endprotoent',
49 'endpwent',
50 'endservent',
51 'eof',
52 'eval',
53 'exec',
54 'exists',
55 'exit',
56 'exp',
57 'fcntl',
58 'fileno',
59 'flock',
60 'for',
61 'foreach',
62 'fork',
63 'format',
64 'formline',
65 'getc',
66 'getgrent',
67 'getgrgid',
68 'getgrnam',
69 'gethostbyaddr',
70 'gethostbyname',
71 'gethostent',
72 'getlogin',
73 'getnetbyaddr',
74 'getnetbyname',
75 'getnetent',
76 'getpeername',
77 'getpgrp',
78 'getpriority',
79 'getprotobyname',
80 'getprotobynumber',
81 'getprotoent',
82 'getpwent',
83 'getpwnam',
84 'getpwuid',
85 'getservbyname',
86 'getservbyport',
87 'getservent',
88 'getsockname',
89 'getsockopt',
90 'given',
91 'glob',
92 'gmtime',
93 'goto',
94 'grep',
95 'gt',
96 'hex',
97 'if',
98 'index',
99 'int',
100 'ioctl',
101 'join',
102 'keys',
103 'kill',
104 'last',
105 'lc',
106 'lcfirst',
107 'length',
108 'link',
109 'listen',
110 'local',
111 'localtime',
112 'log',
113 'lstat',
114 'lt',
115 'ma',
116 'map',
117 'mkdir',
118 'msgctl',
119 'msgget',
120 'msgrcv',
121 'msgsnd',
122 'my',
123 'ne',
124 'next',
125 'no',
126 'not',
127 'oct',
128 'open',
129 'opendir',
130 'or',
131 'ord',
132 'our',
133 'pack',
134 'package',
135 'pipe',
136 'pop',
137 'pos',
138 'print',
139 'printf',
140 'prototype',
141 'push',
142 'q|0',
143 'qq',
144 'quotemeta',
145 'qw',
146 'qx',
147 'rand',
148 'read',
149 'readdir',
150 'readline',
151 'readlink',
152 'readpipe',
153 'recv',
154 'redo',
155 'ref',
156 'rename',
157 'require',
158 'reset',
159 'return',
160 'reverse',
161 'rewinddir',
162 'rindex',
163 'rmdir',
164 'say',
165 'scalar',
166 'seek',
167 'seekdir',
168 'select',
169 'semctl',
170 'semget',
171 'semop',
172 'send',
173 'setgrent',
174 'sethostent',
175 'setnetent',
176 'setpgrp',
177 'setpriority',
178 'setprotoent',
179 'setpwent',
180 'setservent',
181 'setsockopt',
182 'shift',
183 'shmctl',
184 'shmget',
185 'shmread',
186 'shmwrite',
187 'shutdown',
188 'sin',
189 'sleep',
190 'socket',
191 'socketpair',
192 'sort',
193 'splice',
194 'split',
195 'sprintf',
196 'sqrt',
197 'srand',
198 'stat',
199 'state',
200 'study',
201 'sub',
202 'substr',
203 'symlink',
204 'syscall',
205 'sysopen',
206 'sysread',
207 'sysseek',
208 'system',
209 'syswrite',
210 'tell',
211 'telldir',
212 'tie',
213 'tied',
214 'time',
215 'times',
216 'tr',
217 'truncate',
218 'uc',
219 'ucfirst',
220 'umask',
221 'undef',
222 'unless',
223 'unlink',
224 'unpack',
225 'unshift',
226 'untie',
227 'until',
228 'use',
229 'utime',
230 'values',
231 'vec',
232 'wait',
233 'waitpid',
234 'wantarray',
235 'warn',
236 'when',
237 'while',
238 'write',
239 'x|0',
240 'xor',
241 'y|0'
242 ];
243
244 // https://perldoc.perl.org/perlre#Modifiers
245 const REGEX_MODIFIERS = /[dualxmsipngr]{0,12}/; // aa and xx are valid, making max length 12
246 const PERL_KEYWORDS = {
247 $pattern: /[\w.]+/,
248 keyword: KEYWORDS.join(" ")
249 };
250 const SUBST = {
251 className: 'subst',
252 begin: '[$@]\\{',
253 end: '\\}',
254 keywords: PERL_KEYWORDS
255 };
256 const METHOD = {
257 begin: /->\{/,
258 end: /\}/
259 // contains defined later
260 };
261 const VAR = {
262 variants: [
263 {
264 begin: /\$\d/
265 },
266 {
267 begin: regex.concat(
268 /[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,
269 // negative look-ahead tries to avoid matching patterns that are not
270 // Perl at all like $ident$, @ident@, etc.
271 `(?![A-Za-z])(?![@$%])`
272 )
273 },
274 {
275 begin: /[$%@][^\s\w{]/,
276 relevance: 0
277 }
278 ]
279 };
280 const STRING_CONTAINS = [
281 hljs.BACKSLASH_ESCAPE,
282 SUBST,
283 VAR
284 ];
285 const REGEX_DELIMS = [
286 /!/,
287 /\//,
288 /\|/,
289 /\?/,
290 /'/,
291 /"/, // valid but infrequent and weird
292 /#/ // valid but infrequent and weird
293 ];
294 /**
295 * @param {string|RegExp} prefix
296 * @param {string|RegExp} open
297 * @param {string|RegExp} close
298 */
299 const PAIRED_DOUBLE_RE = (prefix, open, close = '\\1') => {
300 const middle = (close === '\\1')
301 ? close
302 : regex.concat(close, open);
303 return regex.concat(
304 regex.concat("(?:", prefix, ")"),
305 open,
306 /(?:\\.|[^\\\/])*?/,
307 middle,
308 /(?:\\.|[^\\\/])*?/,
309 close,
310 REGEX_MODIFIERS
311 );
312 };
313 /**
314 * @param {string|RegExp} prefix
315 * @param {string|RegExp} open
316 * @param {string|RegExp} close
317 */
318 const PAIRED_RE = (prefix, open, close) => {
319 return regex.concat(
320 regex.concat("(?:", prefix, ")"),
321 open,
322 /(?:\\.|[^\\\/])*?/,
323 close,
324 REGEX_MODIFIERS
325 );
326 };
327 const PERL_DEFAULT_CONTAINS = [
328 VAR,
329 hljs.HASH_COMMENT_MODE,
330 hljs.COMMENT(
331 /^=\w/,
332 /=cut/,
333 {
334 endsWithParent: true
335 }
336 ),
337 METHOD,
338 {
339 className: 'string',
340 contains: STRING_CONTAINS,
341 variants: [
342 {
343 begin: 'q[qwxr]?\\s*\\(',
344 end: '\\)',
345 relevance: 5
346 },
347 {
348 begin: 'q[qwxr]?\\s*\\[',
349 end: '\\]',
350 relevance: 5
351 },
352 {
353 begin: 'q[qwxr]?\\s*\\{',
354 end: '\\}',
355 relevance: 5
356 },
357 {
358 begin: 'q[qwxr]?\\s*\\|',
359 end: '\\|',
360 relevance: 5
361 },
362 {
363 begin: 'q[qwxr]?\\s*<',
364 end: '>',
365 relevance: 5
366 },
367 {
368 begin: 'qw\\s+q',
369 end: 'q',
370 relevance: 5
371 },
372 {
373 begin: '\'',
374 end: '\'',
375 contains: [ hljs.BACKSLASH_ESCAPE ]
376 },
377 {
378 begin: '"',
379 end: '"'
380 },
381 {
382 begin: '`',
383 end: '`',
384 contains: [ hljs.BACKSLASH_ESCAPE ]
385 },
386 {
387 begin: /\{\w+\}/,
388 relevance: 0
389 },
390 {
391 begin: '-?\\w+\\s*=>',
392 relevance: 0
393 }
394 ]
395 },
396 {
397 className: 'number',
398 begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
399 relevance: 0
400 },
401 { // regexp container
402 begin: '(\\/\\/|' + hljs.RE_STARTERS_RE + '|\\b(split|return|print|reverse|grep)\\b)\\s*',
403 keywords: 'split return print reverse grep',
404 relevance: 0,
405 contains: [
406 hljs.HASH_COMMENT_MODE,
407 {
408 className: 'regexp',
409 variants: [
410 // allow matching common delimiters
411 { begin: PAIRED_DOUBLE_RE("s|tr|y", regex.either(...REGEX_DELIMS, { capture: true })) },
412 // and then paired delmis
413 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\(", "\\)") },
414 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\[", "\\]") },
415 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\{", "\\}") }
416 ],
417 relevance: 2
418 },
419 {
420 className: 'regexp',
421 variants: [
422 {
423 // could be a comment in many languages so do not count
424 // as relevant
425 begin: /(m|qr)\/\//,
426 relevance: 0
427 },
428 // prefix is optional with /regex/
429 { begin: PAIRED_RE("(?:m|qr)?", /\//, /\//)},
430 // allow matching common delimiters
431 { begin: PAIRED_RE("m|qr", regex.either(...REGEX_DELIMS, { capture: true }), /\1/)},
432 // allow common paired delmins
433 { begin: PAIRED_RE("m|qr", /\(/, /\)/)},
434 { begin: PAIRED_RE("m|qr", /\[/, /\]/)},
435 { begin: PAIRED_RE("m|qr", /\{/, /\}/)}
436 ]
437 }
438 ]
439 },
440 {
441 className: 'function',
442 beginKeywords: 'sub',
443 end: '(\\s*\\(.*?\\))?[;{]',
444 excludeEnd: true,
445 relevance: 5,
446 contains: [ hljs.TITLE_MODE ]
447 },
448 {
449 begin: '-\\w\\b',
450 relevance: 0
451 },
452 {
453 begin: "^__DATA__$",
454 end: "^__END__$",
455 subLanguage: 'mojolicious',
456 contains: [
457 {
458 begin: "^@@.*",
459 end: "$",
460 className: "comment"
461 }
462 ]
463 }
464 ];
465 SUBST.contains = PERL_DEFAULT_CONTAINS;
466 METHOD.contains = PERL_DEFAULT_CONTAINS;
467
468 return {
469 name: 'Perl',
470 aliases: [
471 'pl',
472 'pm'
473 ],
474 keywords: PERL_KEYWORDS,
475 contains: PERL_DEFAULT_CONTAINS
476 };
477}
478
479export { perl as default };