UNPKG

8.84 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 = { variants: [
262 { begin: /\$\d/ },
263 { begin: regex.concat(
264 /[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,
265 // negative look-ahead tries to avoid matching patterns that are not
266 // Perl at all like $ident$, @ident@, etc.
267 `(?![A-Za-z])(?![@$%])`
268 ) },
269 {
270 begin: /[$%@][^\s\w{]/,
271 relevance: 0
272 }
273 ] };
274 const STRING_CONTAINS = [
275 hljs.BACKSLASH_ESCAPE,
276 SUBST,
277 VAR
278 ];
279 const REGEX_DELIMS = [
280 /!/,
281 /\//,
282 /\|/,
283 /\?/,
284 /'/,
285 /"/, // valid but infrequent and weird
286 /#/ // valid but infrequent and weird
287 ];
288 /**
289 * @param {string|RegExp} prefix
290 * @param {string|RegExp} open
291 * @param {string|RegExp} close
292 */
293 const PAIRED_DOUBLE_RE = (prefix, open, close = '\\1') => {
294 const middle = (close === '\\1')
295 ? close
296 : regex.concat(close, open);
297 return regex.concat(
298 regex.concat("(?:", prefix, ")"),
299 open,
300 /(?:\\.|[^\\\/])*?/,
301 middle,
302 /(?:\\.|[^\\\/])*?/,
303 close,
304 REGEX_MODIFIERS
305 );
306 };
307 /**
308 * @param {string|RegExp} prefix
309 * @param {string|RegExp} open
310 * @param {string|RegExp} close
311 */
312 const PAIRED_RE = (prefix, open, close) => {
313 return regex.concat(
314 regex.concat("(?:", prefix, ")"),
315 open,
316 /(?:\\.|[^\\\/])*?/,
317 close,
318 REGEX_MODIFIERS
319 );
320 };
321 const PERL_DEFAULT_CONTAINS = [
322 VAR,
323 hljs.HASH_COMMENT_MODE,
324 hljs.COMMENT(
325 /^=\w/,
326 /=cut/,
327 { endsWithParent: true }
328 ),
329 METHOD,
330 {
331 className: 'string',
332 contains: STRING_CONTAINS,
333 variants: [
334 {
335 begin: 'q[qwxr]?\\s*\\(',
336 end: '\\)',
337 relevance: 5
338 },
339 {
340 begin: 'q[qwxr]?\\s*\\[',
341 end: '\\]',
342 relevance: 5
343 },
344 {
345 begin: 'q[qwxr]?\\s*\\{',
346 end: '\\}',
347 relevance: 5
348 },
349 {
350 begin: 'q[qwxr]?\\s*\\|',
351 end: '\\|',
352 relevance: 5
353 },
354 {
355 begin: 'q[qwxr]?\\s*<',
356 end: '>',
357 relevance: 5
358 },
359 {
360 begin: 'qw\\s+q',
361 end: 'q',
362 relevance: 5
363 },
364 {
365 begin: '\'',
366 end: '\'',
367 contains: [ hljs.BACKSLASH_ESCAPE ]
368 },
369 {
370 begin: '"',
371 end: '"'
372 },
373 {
374 begin: '`',
375 end: '`',
376 contains: [ hljs.BACKSLASH_ESCAPE ]
377 },
378 {
379 begin: /\{\w+\}/,
380 relevance: 0
381 },
382 {
383 begin: '-?\\w+\\s*=>',
384 relevance: 0
385 }
386 ]
387 },
388 {
389 className: 'number',
390 begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
391 relevance: 0
392 },
393 { // regexp container
394 begin: '(\\/\\/|' + hljs.RE_STARTERS_RE + '|\\b(split|return|print|reverse|grep)\\b)\\s*',
395 keywords: 'split return print reverse grep',
396 relevance: 0,
397 contains: [
398 hljs.HASH_COMMENT_MODE,
399 {
400 className: 'regexp',
401 variants: [
402 // allow matching common delimiters
403 { begin: PAIRED_DOUBLE_RE("s|tr|y", regex.either(...REGEX_DELIMS, { capture: true })) },
404 // and then paired delmis
405 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\(", "\\)") },
406 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\[", "\\]") },
407 { begin: PAIRED_DOUBLE_RE("s|tr|y", "\\{", "\\}") }
408 ],
409 relevance: 2
410 },
411 {
412 className: 'regexp',
413 variants: [
414 {
415 // could be a comment in many languages so do not count
416 // as relevant
417 begin: /(m|qr)\/\//,
418 relevance: 0
419 },
420 // prefix is optional with /regex/
421 { begin: PAIRED_RE("(?:m|qr)?", /\//, /\//) },
422 // allow matching common delimiters
423 { begin: PAIRED_RE("m|qr", regex.either(...REGEX_DELIMS, { capture: true }), /\1/) },
424 // allow common paired delmins
425 { begin: PAIRED_RE("m|qr", /\(/, /\)/) },
426 { begin: PAIRED_RE("m|qr", /\[/, /\]/) },
427 { begin: PAIRED_RE("m|qr", /\{/, /\}/) }
428 ]
429 }
430 ]
431 },
432 {
433 className: 'function',
434 beginKeywords: 'sub',
435 end: '(\\s*\\(.*?\\))?[;{]',
436 excludeEnd: true,
437 relevance: 5,
438 contains: [ hljs.TITLE_MODE ]
439 },
440 {
441 begin: '-\\w\\b',
442 relevance: 0
443 },
444 {
445 begin: "^__DATA__$",
446 end: "^__END__$",
447 subLanguage: 'mojolicious',
448 contains: [
449 {
450 begin: "^@@.*",
451 end: "$",
452 className: "comment"
453 }
454 ]
455 }
456 ];
457 SUBST.contains = PERL_DEFAULT_CONTAINS;
458 METHOD.contains = PERL_DEFAULT_CONTAINS;
459
460 return {
461 name: 'Perl',
462 aliases: [
463 'pl',
464 'pm'
465 ],
466 keywords: PERL_KEYWORDS,
467 contains: PERL_DEFAULT_CONTAINS
468 };
469}
470
471module.exports = perl;