1
// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
2
// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
3
CodeMirror.defineMode("perl",function(config,parserConfig){
4
// http://perldoc.perl.org
5
var PERL={ // null - magic touch
10
// 5 - variable-2 (predefined)
11
// [x,y] - x=1,2,3; y=must be defined if x{...}
17
// ! ~ \ and unary + and -
29
// named unary operators
62
// list operators (rightward)
67
// PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
89
'$LIST_SEPARATOR' : 5,
97
'$EFFECTIVE_GROUP_ID' : 5,
102
'$SUBSCRIPT_SEPARATOR' : 5,
108
'$EFFECTIVE_USER_ID' : 5,
120
'$SYSTEM_FD_MAX' : 5,
123
'${^GLOBAL_PHASE}' : 5,
143
'${^UTF8LOCALE}' : 5,
146
'${^WIN32_SLOPPY_STAT}' : 5,
147
'$EXECUTABLE_NAME' : 5,
149
'$1' : 5, // - regexp $1, $2...
159
'$LAST_PAREN_MATCH' : 5,
161
'$LAST_SUBMATCH_RESULT' : 5,
163
'@LAST_MATCH_END' : 5,
165
'%LAST_PAREN_MATCH' : 5,
167
'@LAST_MATCH_START' : 5,
169
'%LAST_MATCH_START' : 5,
171
'$LAST_REGEXP_CODE_RESULT' : 5,
173
'${^RE_DEBUG_FLAGS}' : 5,
174
'${^RE_TRIE_MAXBUF}' : 5,
179
'$OUTPUT_FIELD_SEPARATOR' : 5,
182
'$INPUT_LINE_NUMBER' : 5,
185
'$INPUT_RECORD_SEPARATOR' : 5,
188
'$OUTPUT_RECORD_SEPARATOR' : 5,
191
'$OUTPUT_AUTOFLUSH' : 5,
195
'$FORMAT_FORMFEED' : 5,
197
'$FORMAT_PAGE_NUMBER' : 5,
199
'$FORMAT_LINES_LEFT' : 5,
201
'$FORMAT_LINE_BREAK_CHARACTERS' : 5,
203
'$FORMAT_LINES_PER_PAGE' : 5,
205
'$FORMAT_TOP_NAME' : 5,
209
'${^CHILD_ERROR_NATIVE}' : 5,
210
'$EXTENDED_OS_ERROR' : 5,
212
'$EXCEPTIONS_BEING_CAUGHT' : 5,
216
'${^WARNING_BITS}' : 5,
232
'$OLD_PERL_VERSION' : 5,
243
'abs' :1, // - absolute value function
244
accept :1, // - accept an incoming socket connect
245
alarm :1, // - schedule a SIGALRM
246
'atan2' :1, // - arctangent of Y/X in the range -PI to PI
247
bind :1, // - binds an address to a socket
248
binmode :1, // - prepare binary files for I/O
249
bless :1, // - create an object
251
'break' :1, // - break out of a "given" block
252
caller :1, // - get context of the current subroutine call
253
chdir :1, // - change your current working directory
254
chmod :1, // - changes the permissions on a list of files
255
chomp :1, // - remove a trailing record separator from a string
256
chop :1, // - remove the last character from a string
257
chown :1, // - change the owership on a list of files
258
chr :1, // - get character this number represents
259
chroot :1, // - make directory new root for path lookups
260
close :1, // - close file (or pipe or socket) handle
261
closedir :1, // - close directory handle
262
connect :1, // - connect to a remote socket
263
'continue' :[1,1], // - optional trailing block in a while or foreach
264
'cos' :1, // - cosine function
265
crypt :1, // - one-way passwd-style encryption
266
dbmclose :1, // - breaks binding on a tied dbm file
267
dbmopen :1, // - create binding on a tied dbm file
269
defined :1, // - test whether a value, variable, or function is defined
270
'delete' :1, // - deletes a value from a hash
271
die :1, // - raise an exception or bail out
272
'do' :1, // - turn a BLOCK into a TERM
273
dump :1, // - create an immediate core dump
274
each :1, // - retrieve the next key/value pair from a hash
275
endgrent :1, // - be done using group file
276
endhostent :1, // - be done using hosts file
277
endnetent :1, // - be done using networks file
278
endprotoent :1, // - be done using protocols file
279
endpwent :1, // - be done using passwd file
280
endservent :1, // - be done using services file
281
eof :1, // - test a filehandle for its end
282
'eval' :1, // - catch exceptions or compile and run code
283
'exec' :1, // - abandon this program to run another
284
exists :1, // - test whether a hash key is present
285
exit :1, // - terminate this program
286
'exp' :1, // - raise I to a power
287
fcntl :1, // - file control system call
288
fileno :1, // - return file descriptor from filehandle
289
flock :1, // - lock an entire file with an advisory lock
290
fork :1, // - create a new process just like this one
291
format :1, // - declare a picture format with use by the write() function
292
formline :1, // - internal function used for formats
293
getc :1, // - get the next character from the filehandle
294
getgrent :1, // - get next group record
295
getgrgid :1, // - get group record given group user ID
296
getgrnam :1, // - get group record given group name
297
gethostbyaddr :1, // - get host record given its address
298
gethostbyname :1, // - get host record given name
299
gethostent :1, // - get next hosts record
300
getlogin :1, // - return who logged in at this tty
301
getnetbyaddr :1, // - get network record given its address
302
getnetbyname :1, // - get networks record given name
303
getnetent :1, // - get next networks record
304
getpeername :1, // - find the other end of a socket connection
305
getpgrp :1, // - get process group
306
getppid :1, // - get parent process ID
307
getpriority :1, // - get current nice value
308
getprotobyname :1, // - get protocol record given name
309
getprotobynumber :1, // - get protocol record numeric protocol
310
getprotoent :1, // - get next protocols record
311
getpwent :1, // - get next passwd record
312
getpwnam :1, // - get passwd record given user login name
313
getpwuid :1, // - get passwd record given user ID
314
getservbyname :1, // - get services record given its name
315
getservbyport :1, // - get services record given numeric port
316
getservent :1, // - get next services record
317
getsockname :1, // - retrieve the sockaddr for a given socket
318
getsockopt :1, // - get socket options on a given socket
320
glob :1, // - expand filenames using wildcards
321
gmtime :1, // - convert UNIX time into record or string using Greenwich time
322
'goto' :1, // - create spaghetti code
323
grep :1, // - locate elements in a list test true against a given criterion
324
hex :1, // - convert a string to a hexadecimal number
325
'import' :1, // - patch a module's namespace into your own
326
index :1, // - find a substring within a string
327
'int' :1, // - get the integer portion of a number
328
ioctl :1, // - system-dependent device control system call
329
'join' :1, // - join a list into a string using a separator
330
keys :1, // - retrieve list of indices from a hash
331
kill :1, // - send a signal to a process or process group
332
last :1, // - exit a block prematurely
333
lc :1, // - return lower-case version of a string
334
lcfirst :1, // - return a string with just the next letter in lower case
335
length :1, // - return the number of bytes in a string
336
'link' :1, // - create a hard link in the filesytem
337
listen :1, // - register your socket as a server
338
local : 2, // - create a temporary value for a global variable (dynamic scoping)
339
localtime :1, // - convert UNIX time into record or string using local time
340
lock :1, // - get a thread lock on a variable, subroutine, or method
341
'log' :1, // - retrieve the natural logarithm for a number
342
lstat :1, // - stat a symbolic link
343
m :null, // - match a string with a regular expression pattern
344
map :1, // - apply a change to a list to get back a new list with the changes
345
mkdir :1, // - create a directory
346
msgctl :1, // - SysV IPC message control operations
347
msgget :1, // - get SysV IPC message queue
348
msgrcv :1, // - receive a SysV IPC message from a message queue
349
msgsnd :1, // - send a SysV IPC message to a message queue
350
my : 2, // - declare and assign a local variable (lexical scoping)
352
next :1, // - iterate a block prematurely
353
no :1, // - unimport some module symbols or semantics at compile time
354
oct :1, // - convert a string to an octal number
355
open :1, // - open a file, pipe, or descriptor
356
opendir :1, // - open a directory
357
ord :1, // - find a character's numeric representation
358
our : 2, // - declare and assign a package variable (lexical scoping)
359
pack :1, // - convert a list into a binary representation
360
'package' :1, // - declare a separate global namespace
361
pipe :1, // - open a pair of connected filehandles
362
pop :1, // - remove the last element from an array and return it
363
pos :1, // - find or set the offset for the last/next m//g search
364
print :1, // - output a list to a filehandle
365
printf :1, // - output a formatted list to a filehandle
366
prototype :1, // - get the prototype (if any) of a subroutine
367
push :1, // - append one or more elements to an array
368
q :null, // - singly quote a string
369
qq :null, // - doubly quote a string
370
qr :null, // - Compile pattern
371
quotemeta :null, // - quote regular expression magic characters
372
qw :null, // - quote a list of words
373
qx :null, // - backquote quote a string
374
rand :1, // - retrieve the next pseudorandom number
375
read :1, // - fixed-length buffered input from a filehandle
376
readdir :1, // - get a directory from a directory handle
377
readline :1, // - fetch a record from a file
378
readlink :1, // - determine where a symbolic link is pointing
379
readpipe :1, // - execute a system command and collect standard output
380
recv :1, // - receive a message over a Socket
381
redo :1, // - start this loop iteration over again
382
ref :1, // - find out the type of thing being referenced
383
rename :1, // - change a filename
384
require :1, // - load in external functions from a library at runtime
385
reset :1, // - clear all variables of a given name
386
'return' :1, // - get out of a function early
387
reverse :1, // - flip a string or a list
388
rewinddir :1, // - reset directory handle
389
rindex :1, // - right-to-left substring search
390
rmdir :1, // - remove a directory
391
s :null, // - replace a pattern with a string
392
say :1, // - print with newline
393
scalar :1, // - force a scalar context
394
seek :1, // - reposition file pointer for random-access I/O
395
seekdir :1, // - reposition directory pointer
396
select :1, // - reset default output or do I/O multiplexing
397
semctl :1, // - SysV semaphore control operations
398
semget :1, // - get set of SysV semaphores
399
semop :1, // - SysV semaphore operations
400
send :1, // - send a message over a socket
401
setgrent :1, // - prepare group file for use
402
sethostent :1, // - prepare hosts file for use
403
setnetent :1, // - prepare networks file for use
404
setpgrp :1, // - set the process group of a process
405
setpriority :1, // - set a process's nice value
406
setprotoent :1, // - prepare protocols file for use
407
setpwent :1, // - prepare passwd file for use
408
setservent :1, // - prepare services file for use
409
setsockopt :1, // - set some socket options
410
shift :1, // - remove the first element of an array, and return it
411
shmctl :1, // - SysV shared memory operations
412
shmget :1, // - get SysV shared memory segment identifier
413
shmread :1, // - read SysV shared memory
414
shmwrite :1, // - write SysV shared memory
415
shutdown :1, // - close down just half of a socket connection
416
'sin' :1, // - return the sine of a number
417
sleep :1, // - block for some number of seconds
418
socket :1, // - create a socket
419
socketpair :1, // - create a pair of sockets
420
'sort' :1, // - sort a list of values
421
splice :1, // - add or remove elements anywhere in an array
422
'split' :1, // - split up a string using a regexp delimiter
423
sprintf :1, // - formatted print into a string
424
'sqrt' :1, // - square root function
425
srand :1, // - seed the random number generator
426
stat :1, // - get a file's status information
427
state :1, // - declare and assign a state variable (persistent lexical scoping)
428
study :1, // - optimize input data for repeated searches
429
'sub' :1, // - declare a subroutine, possibly anonymously
430
'substr' :1, // - get or alter a portion of a stirng
431
symlink :1, // - create a symbolic link to a file
432
syscall :1, // - execute an arbitrary system call
433
sysopen :1, // - open a file, pipe, or descriptor
434
sysread :1, // - fixed-length unbuffered input from a filehandle
435
sysseek :1, // - position I/O pointer on handle used with sysread and syswrite
436
system :1, // - run a separate program
437
syswrite :1, // - fixed-length unbuffered output to a filehandle
438
tell :1, // - get current seekpointer on a filehandle
439
telldir :1, // - get current seekpointer on a directory handle
440
tie :1, // - bind a variable to an object class
441
tied :1, // - get a reference to the object underlying a tied variable
442
time :1, // - return number of seconds since 1970
443
times :1, // - return elapsed time for self and child processes
444
tr :null, // - transliterate a string
445
truncate :1, // - shorten a file
446
uc :1, // - return upper-case version of a string
447
ucfirst :1, // - return a string with just the next letter in upper case
448
umask :1, // - set file creation mode mask
449
undef :1, // - remove a variable or function definition
450
unlink :1, // - remove one link to a file
451
unpack :1, // - convert binary structure into normal perl variables
452
unshift :1, // - prepend more elements to the beginning of a list
453
untie :1, // - break a tie binding to a variable
454
use :1, // - load in a module at compile time
455
utime :1, // - set a file's last access and modify times
456
values :1, // - return a list of the values in a hash
457
vec :1, // - test or set particular bits in a string
458
wait :1, // - wait for any child process to die
459
waitpid :1, // - wait for a particular child process to die
460
wantarray :1, // - get void vs scalar vs list context of current subroutine call
461
warn :1, // - print debugging info
463
write :1, // - print a picture record
464
y :null}; // - transliterate a string
466
var RXstyle="string-2";
467
var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
469
function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
470
state.chain=null; // 12 3tail
473
state.tokenize=function(stream,state){
475
while(c=stream.next()){
476
if(c===chain[i]&&!e){
477
if(chain[++i]!==undefined){
478
state.chain=chain[i];
482
stream.eatWhile(tail);
483
state.tokenize=tokenPerl;
487
return state.tokenize(stream,state)}
489
function tokenSOMETHING(stream,state,string){
490
state.tokenize=function(stream,state){
491
if(stream.string==string)
492
state.tokenize=tokenPerl;
495
return state.tokenize(stream,state)}
497
function tokenPerl(stream,state){
498
if(stream.eatSpace())
501
return tokenChain(stream,state,state.chain,state.style,state.tail);
502
if(stream.match(/^\-?[\d\.]/,false))
503
if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/))
505
if(stream.match(/^<<(?=\w)/)){ // NOTE: <<SOMETHING\n...\nSOMETHING\n
506
stream.eatWhile(/\w/);
507
return tokenSOMETHING(stream,state,stream.current().substr(2))}
508
if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n
509
return tokenSOMETHING(stream,state,'=cut')}
510
var ch=stream.next();
511
if(ch=='"'||ch=="'"){ // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n
512
if(stream.prefix(3)=="<<"+ch){
514
stream.eatWhile(/\w/);
515
var n=stream.current().substr(1);
516
if(n&&stream.eat(ch))
517
return tokenSOMETHING(stream,state,n);
519
return tokenChain(stream,state,[ch],"string")}
521
var c=stream.look(-2);
522
if(!(c&&/\w/.test(c))){
528
return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
531
return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
534
return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
537
return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}
538
if(/[\^'"!~\/]/.test(c)){
540
return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}
545
return tokenChain(stream,state,[")"],"string")}
548
return tokenChain(stream,state,["]"],"string")}
551
return tokenChain(stream,state,["}"],"string")}
554
return tokenChain(stream,state,[">"],"string")}
555
if(/[\^'"!~\/]/.test(c)){
557
return tokenChain(stream,state,[stream.eat(c)],"string")}}
562
return tokenChain(stream,state,[")"],"bracket")}
565
return tokenChain(stream,state,["]"],"bracket")}
568
return tokenChain(stream,state,["}"],"bracket")}
571
return tokenChain(stream,state,[">"],"bracket")}
572
if(/[\^'"!~\/]/.test(c)){
574
return tokenChain(stream,state,[stream.eat(c)],"bracket")}}
579
return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
582
return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
585
return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
588
return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}
589
if(/[\^'"!~\/]/.test(c)){
591
return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}
592
else if(/[\^'"!~\/(\[{<]/.test(c)){
595
return tokenChain(stream,state,[")"],"string")}
598
return tokenChain(stream,state,["]"],"string")}
601
return tokenChain(stream,state,["}"],"string")}
604
return tokenChain(stream,state,[">"],"string")}
605
if(/[\^'"!~\/]/.test(c)){
606
return tokenChain(stream,state,[stream.eat(c)],"string")}}}}
608
var c=stream.look(-2);
609
if(!(c&&/\w/.test(c))){
610
c=stream.eat(/[(\[{<\^'"!~\/]/);
612
if(/[\^'"!~\/]/.test(c)){
613
return tokenChain(stream,state,[c],RXstyle,RXmodifiers)}
615
return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)}
617
return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)}
619
return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)}
621
return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}}}}
623
var c=/[\/>\]})\w]/.test(stream.look(-2));
625
c=stream.eat(/[(\[{<\^'"!~\/]/);
628
return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
630
return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
632
return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
634
return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
635
return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}
637
var c=/[\/>\]})\w]/.test(stream.look(-2));
639
c=stream.eat(/[(\[{<\^'"!~\/]/);
642
return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
644
return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
646
return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
648
return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
649
return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}
651
var c=/[\/>\]})\w]/.test(stream.look(-2));
653
c=stream.eat("r");if(c){
654
c=stream.eat(/[(\[{<\^'"!~\/]/);
657
return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
659
return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
661
return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
663
return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
664
return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}}
666
return tokenChain(stream,state,[ch],"variable-2")}
668
if(!/~\s*$/.test(stream.prefix()))
671
return tokenChain(stream,state,[ch],RXstyle,RXmodifiers)}
674
if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
678
if(/[$@%]/.test(ch)){
680
if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
681
var c=stream.current();
685
if(/[$@%&]/.test(ch)){
686
if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){
687
var c=stream.current();
693
if(stream.look(-2)!="$"){
696
if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
698
stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
699
if(PERL[stream.current()])
705
if(stream.suffix(6)=="_END__"){
706
return tokenChain(stream,state,['\0'],"comment")}
707
else if(stream.suffix(7)=="_DATA__"){
708
return tokenChain(stream,state,['\0'],"variable-2")}
709
else if(stream.suffix(7)=="_C__"){
710
return tokenChain(stream,state,['\0'],"string")}}}
713
if(stream.look(-2)=="{"&&(stream.look(0)=="}"||stream.eatWhile(/\w/)&&stream.look(0)=="}"))
717
if(/[A-Z]/.test(ch)){
718
var l=stream.look(-2);
720
stream.eatWhile(/[A-Z_]/);
721
if(/[\da-z]/.test(stream.look(0))){
724
var c=PERL[stream.current()];
744
if(/[a-zA-Z_]/.test(ch)){
745
var l=stream.look(-2);
746
stream.eatWhile(/\w/);
747
var c=PERL[stream.current()];
770
startState:function(){
776
token:function(stream,state){
777
return (state.tokenize||tokenPerl)(stream,state)},
778
electricChars:"{}"}});
780
CodeMirror.defineMIME("text/x-perl", "perl");
782
// it's like "peek", but need for look-ahead or look-behind if index < 0
783
CodeMirror.StringStream.prototype.look=function(c){
784
return this.string.charAt(this.pos+(c||0))};
786
// return a part of prefix of current stream from current position
787
CodeMirror.StringStream.prototype.prefix=function(c){
790
return this.string.substr((x>=0?x:0),c)}
792
return this.string.substr(0,this.pos-1)}};
794
// return a part of suffix of current stream from current position
795
CodeMirror.StringStream.prototype.suffix=function(c){
796
var y=this.string.length;
798
return this.string.substr(this.pos,(c&&c<y?c:x))};
800
// return a part of suffix of current stream from current position and change current position
801
CodeMirror.StringStream.prototype.nsuffix=function(c){
803
var l=c||(this.string.length-this.pos+1);
805
return this.string.substr(p,l)};
807
// eating and vomiting a part of stream from current position
808
CodeMirror.StringStream.prototype.eatSuffix=function(c){
813
else if(x>=(y=this.string.length-1))