GPQAPP
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
5// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
6
7(function(mod) {8if (typeof exports == "object" && typeof module == "object") // CommonJS9mod(require("../../lib/codemirror"));10else if (typeof define == "function" && define.amd) // AMD11define(["../../lib/codemirror"], mod);12else // Plain browser env13mod(CodeMirror);14})(function(CodeMirror) {15"use strict";16
17CodeMirror.defineMode("perl",function(){18// http://perldoc.perl.org19var PERL={ // null - magic touch20// 1 - keyword21// 2 - def22// 3 - atom23// 4 - operator24// 5 - variable-2 (predefined)25// [x,y] - x=1,2,3; y=must be defined if x{...}26// PERL operators27'->' : 4,28'++' : 4,29'--' : 4,30'**' : 4,31// ! ~ \ and unary + and -32'=~' : 4,33'!~' : 4,34'*' : 4,35'/' : 4,36'%' : 4,37'x' : 4,38'+' : 4,39'-' : 4,40'.' : 4,41'<<' : 4,42'>>' : 4,43// named unary operators44'<' : 4,45'>' : 4,46'<=' : 4,47'>=' : 4,48'lt' : 4,49'gt' : 4,50'le' : 4,51'ge' : 4,52'==' : 4,53'!=' : 4,54'<=>' : 4,55'eq' : 4,56'ne' : 4,57'cmp' : 4,58'~~' : 4,59'&' : 4,60'|' : 4,61'^' : 4,62'&&' : 4,63'||' : 4,64'//' : 4,65'..' : 4,66'...' : 4,67'?' : 4,68':' : 4,69'=' : 4,70'+=' : 4,71'-=' : 4,72'*=' : 4, // etc. ???73',' : 4,74'=>' : 4,75'::' : 4,76// list operators (rightward)77'not' : 4,78'and' : 4,79'or' : 4,80'xor' : 4,81// 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?;)82'BEGIN' : [5,1],83'END' : [5,1],84'PRINT' : [5,1],85'PRINTF' : [5,1],86'GETC' : [5,1],87'READ' : [5,1],88'READLINE' : [5,1],89'DESTROY' : [5,1],90'TIE' : [5,1],91'TIEHANDLE' : [5,1],92'UNTIE' : [5,1],93'STDIN' : 5,94'STDIN_TOP' : 5,95'STDOUT' : 5,96'STDOUT_TOP' : 5,97'STDERR' : 5,98'STDERR_TOP' : 5,99'$ARG' : 5,100'$_' : 5,101'@ARG' : 5,102'@_' : 5,103'$LIST_SEPARATOR' : 5,104'$"' : 5,105'$PROCESS_ID' : 5,106'$PID' : 5,107'$$' : 5,108'$REAL_GROUP_ID' : 5,109'$GID' : 5,110'$(' : 5,111'$EFFECTIVE_GROUP_ID' : 5,112'$EGID' : 5,113'$)' : 5,114'$PROGRAM_NAME' : 5,115'$0' : 5,116'$SUBSCRIPT_SEPARATOR' : 5,117'$SUBSEP' : 5,118'$;' : 5,119'$REAL_USER_ID' : 5,120'$UID' : 5,121'$<' : 5,122'$EFFECTIVE_USER_ID' : 5,123'$EUID' : 5,124'$>' : 5,125'$a' : 5,126'$b' : 5,127'$COMPILING' : 5,128'$^C' : 5,129'$DEBUGGING' : 5,130'$^D' : 5,131'${^ENCODING}' : 5,132'$ENV' : 5,133'%ENV' : 5,134'$SYSTEM_FD_MAX' : 5,135'$^F' : 5,136'@F' : 5,137'${^GLOBAL_PHASE}' : 5,138'$^H' : 5,139'%^H' : 5,140'@INC' : 5,141'%INC' : 5,142'$INPLACE_EDIT' : 5,143'$^I' : 5,144'$^M' : 5,145'$OSNAME' : 5,146'$^O' : 5,147'${^OPEN}' : 5,148'$PERLDB' : 5,149'$^P' : 5,150'$SIG' : 5,151'%SIG' : 5,152'$BASETIME' : 5,153'$^T' : 5,154'${^TAINT}' : 5,155'${^UNICODE}' : 5,156'${^UTF8CACHE}' : 5,157'${^UTF8LOCALE}' : 5,158'$PERL_VERSION' : 5,159'$^V' : 5,160'${^WIN32_SLOPPY_STAT}' : 5,161'$EXECUTABLE_NAME' : 5,162'$^X' : 5,163'$1' : 5, // - regexp $1, $2...164'$MATCH' : 5,165'$&' : 5,166'${^MATCH}' : 5,167'$PREMATCH' : 5,168'$`' : 5,169'${^PREMATCH}' : 5,170'$POSTMATCH' : 5,171"$'" : 5,172'${^POSTMATCH}' : 5,173'$LAST_PAREN_MATCH' : 5,174'$+' : 5,175'$LAST_SUBMATCH_RESULT' : 5,176'$^N' : 5,177'@LAST_MATCH_END' : 5,178'@+' : 5,179'%LAST_PAREN_MATCH' : 5,180'%+' : 5,181'@LAST_MATCH_START' : 5,182'@-' : 5,183'%LAST_MATCH_START' : 5,184'%-' : 5,185'$LAST_REGEXP_CODE_RESULT' : 5,186'$^R' : 5,187'${^RE_DEBUG_FLAGS}' : 5,188'${^RE_TRIE_MAXBUF}' : 5,189'$ARGV' : 5,190'@ARGV' : 5,191'ARGV' : 5,192'ARGVOUT' : 5,193'$OUTPUT_FIELD_SEPARATOR' : 5,194'$OFS' : 5,195'$,' : 5,196'$INPUT_LINE_NUMBER' : 5,197'$NR' : 5,198'$.' : 5,199'$INPUT_RECORD_SEPARATOR' : 5,200'$RS' : 5,201'$/' : 5,202'$OUTPUT_RECORD_SEPARATOR' : 5,203'$ORS' : 5,204'$\\' : 5,205'$OUTPUT_AUTOFLUSH' : 5,206'$|' : 5,207'$ACCUMULATOR' : 5,208'$^A' : 5,209'$FORMAT_FORMFEED' : 5,210'$^L' : 5,211'$FORMAT_PAGE_NUMBER' : 5,212'$%' : 5,213'$FORMAT_LINES_LEFT' : 5,214'$-' : 5,215'$FORMAT_LINE_BREAK_CHARACTERS' : 5,216'$:' : 5,217'$FORMAT_LINES_PER_PAGE' : 5,218'$=' : 5,219'$FORMAT_TOP_NAME' : 5,220'$^' : 5,221'$FORMAT_NAME' : 5,222'$~' : 5,223'${^CHILD_ERROR_NATIVE}' : 5,224'$EXTENDED_OS_ERROR' : 5,225'$^E' : 5,226'$EXCEPTIONS_BEING_CAUGHT' : 5,227'$^S' : 5,228'$WARNING' : 5,229'$^W' : 5,230'${^WARNING_BITS}' : 5,231'$OS_ERROR' : 5,232'$ERRNO' : 5,233'$!' : 5,234'%OS_ERROR' : 5,235'%ERRNO' : 5,236'%!' : 5,237'$CHILD_ERROR' : 5,238'$?' : 5,239'$EVAL_ERROR' : 5,240'$@' : 5,241'$OFMT' : 5,242'$#' : 5,243'$*' : 5,244'$ARRAY_BASE' : 5,245'$[' : 5,246'$OLD_PERL_VERSION' : 5,247'$]' : 5,248// PERL blocks249'if' :[1,1],250elsif :[1,1],251'else' :[1,1],252'while' :[1,1],253unless :[1,1],254'for' :[1,1],255foreach :[1,1],256// PERL functions257'abs' :1, // - absolute value function258accept :1, // - accept an incoming socket connect259alarm :1, // - schedule a SIGALRM260'atan2' :1, // - arctangent of Y/X in the range -PI to PI261bind :1, // - binds an address to a socket262binmode :1, // - prepare binary files for I/O263bless :1, // - create an object264bootstrap :1, //265'break' :1, // - break out of a "given" block266caller :1, // - get context of the current subroutine call267chdir :1, // - change your current working directory268chmod :1, // - changes the permissions on a list of files269chomp :1, // - remove a trailing record separator from a string270chop :1, // - remove the last character from a string271chown :1, // - change the ownership on a list of files272chr :1, // - get character this number represents273chroot :1, // - make directory new root for path lookups274close :1, // - close file (or pipe or socket) handle275closedir :1, // - close directory handle276connect :1, // - connect to a remote socket277'continue' :[1,1], // - optional trailing block in a while or foreach278'cos' :1, // - cosine function279crypt :1, // - one-way passwd-style encryption280dbmclose :1, // - breaks binding on a tied dbm file281dbmopen :1, // - create binding on a tied dbm file282'default' :1, //283defined :1, // - test whether a value, variable, or function is defined284'delete' :1, // - deletes a value from a hash285die :1, // - raise an exception or bail out286'do' :1, // - turn a BLOCK into a TERM287dump :1, // - create an immediate core dump288each :1, // - retrieve the next key/value pair from a hash289endgrent :1, // - be done using group file290endhostent :1, // - be done using hosts file291endnetent :1, // - be done using networks file292endprotoent :1, // - be done using protocols file293endpwent :1, // - be done using passwd file294endservent :1, // - be done using services file295eof :1, // - test a filehandle for its end296'eval' :1, // - catch exceptions or compile and run code297'exec' :1, // - abandon this program to run another298exists :1, // - test whether a hash key is present299exit :1, // - terminate this program300'exp' :1, // - raise I to a power301fcntl :1, // - file control system call302fileno :1, // - return file descriptor from filehandle303flock :1, // - lock an entire file with an advisory lock304fork :1, // - create a new process just like this one305format :1, // - declare a picture format with use by the write() function306formline :1, // - internal function used for formats307getc :1, // - get the next character from the filehandle308getgrent :1, // - get next group record309getgrgid :1, // - get group record given group user ID310getgrnam :1, // - get group record given group name311gethostbyaddr :1, // - get host record given its address312gethostbyname :1, // - get host record given name313gethostent :1, // - get next hosts record314getlogin :1, // - return who logged in at this tty315getnetbyaddr :1, // - get network record given its address316getnetbyname :1, // - get networks record given name317getnetent :1, // - get next networks record318getpeername :1, // - find the other end of a socket connection319getpgrp :1, // - get process group320getppid :1, // - get parent process ID321getpriority :1, // - get current nice value322getprotobyname :1, // - get protocol record given name323getprotobynumber :1, // - get protocol record numeric protocol324getprotoent :1, // - get next protocols record325getpwent :1, // - get next passwd record326getpwnam :1, // - get passwd record given user login name327getpwuid :1, // - get passwd record given user ID328getservbyname :1, // - get services record given its name329getservbyport :1, // - get services record given numeric port330getservent :1, // - get next services record331getsockname :1, // - retrieve the sockaddr for a given socket332getsockopt :1, // - get socket options on a given socket333given :1, //334glob :1, // - expand filenames using wildcards335gmtime :1, // - convert UNIX time into record or string using Greenwich time336'goto' :1, // - create spaghetti code337grep :1, // - locate elements in a list test true against a given criterion338hex :1, // - convert a string to a hexadecimal number339'import' :1, // - patch a module's namespace into your own340index :1, // - find a substring within a string341'int' :1, // - get the integer portion of a number342ioctl :1, // - system-dependent device control system call343'join' :1, // - join a list into a string using a separator344keys :1, // - retrieve list of indices from a hash345kill :1, // - send a signal to a process or process group346last :1, // - exit a block prematurely347lc :1, // - return lower-case version of a string348lcfirst :1, // - return a string with just the next letter in lower case349length :1, // - return the number of bytes in a string350'link' :1, // - create a hard link in the filesystem351listen :1, // - register your socket as a server352local : 2, // - create a temporary value for a global variable (dynamic scoping)353localtime :1, // - convert UNIX time into record or string using local time354lock :1, // - get a thread lock on a variable, subroutine, or method355'log' :1, // - retrieve the natural logarithm for a number356lstat :1, // - stat a symbolic link357m :null, // - match a string with a regular expression pattern358map :1, // - apply a change to a list to get back a new list with the changes359mkdir :1, // - create a directory360msgctl :1, // - SysV IPC message control operations361msgget :1, // - get SysV IPC message queue362msgrcv :1, // - receive a SysV IPC message from a message queue363msgsnd :1, // - send a SysV IPC message to a message queue364my : 2, // - declare and assign a local variable (lexical scoping)365'new' :1, //366next :1, // - iterate a block prematurely367no :1, // - unimport some module symbols or semantics at compile time368oct :1, // - convert a string to an octal number369open :1, // - open a file, pipe, or descriptor370opendir :1, // - open a directory371ord :1, // - find a character's numeric representation372our : 2, // - declare and assign a package variable (lexical scoping)373pack :1, // - convert a list into a binary representation374'package' :1, // - declare a separate global namespace375pipe :1, // - open a pair of connected filehandles376pop :1, // - remove the last element from an array and return it377pos :1, // - find or set the offset for the last/next m//g search378print :1, // - output a list to a filehandle379printf :1, // - output a formatted list to a filehandle380prototype :1, // - get the prototype (if any) of a subroutine381push :1, // - append one or more elements to an array382q :null, // - singly quote a string383qq :null, // - doubly quote a string384qr :null, // - Compile pattern385quotemeta :null, // - quote regular expression magic characters386qw :null, // - quote a list of words387qx :null, // - backquote quote a string388rand :1, // - retrieve the next pseudorandom number389read :1, // - fixed-length buffered input from a filehandle390readdir :1, // - get a directory from a directory handle391readline :1, // - fetch a record from a file392readlink :1, // - determine where a symbolic link is pointing393readpipe :1, // - execute a system command and collect standard output394recv :1, // - receive a message over a Socket395redo :1, // - start this loop iteration over again396ref :1, // - find out the type of thing being referenced397rename :1, // - change a filename398require :1, // - load in external functions from a library at runtime399reset :1, // - clear all variables of a given name400'return' :1, // - get out of a function early401reverse :1, // - flip a string or a list402rewinddir :1, // - reset directory handle403rindex :1, // - right-to-left substring search404rmdir :1, // - remove a directory405s :null, // - replace a pattern with a string406say :1, // - print with newline407scalar :1, // - force a scalar context408seek :1, // - reposition file pointer for random-access I/O409seekdir :1, // - reposition directory pointer410select :1, // - reset default output or do I/O multiplexing411semctl :1, // - SysV semaphore control operations412semget :1, // - get set of SysV semaphores413semop :1, // - SysV semaphore operations414send :1, // - send a message over a socket415setgrent :1, // - prepare group file for use416sethostent :1, // - prepare hosts file for use417setnetent :1, // - prepare networks file for use418setpgrp :1, // - set the process group of a process419setpriority :1, // - set a process's nice value420setprotoent :1, // - prepare protocols file for use421setpwent :1, // - prepare passwd file for use422setservent :1, // - prepare services file for use423setsockopt :1, // - set some socket options424shift :1, // - remove the first element of an array, and return it425shmctl :1, // - SysV shared memory operations426shmget :1, // - get SysV shared memory segment identifier427shmread :1, // - read SysV shared memory428shmwrite :1, // - write SysV shared memory429shutdown :1, // - close down just half of a socket connection430'sin' :1, // - return the sine of a number431sleep :1, // - block for some number of seconds432socket :1, // - create a socket433socketpair :1, // - create a pair of sockets434'sort' :1, // - sort a list of values435splice :1, // - add or remove elements anywhere in an array436'split' :1, // - split up a string using a regexp delimiter437sprintf :1, // - formatted print into a string438'sqrt' :1, // - square root function439srand :1, // - seed the random number generator440stat :1, // - get a file's status information441state :1, // - declare and assign a state variable (persistent lexical scoping)442study :1, // - optimize input data for repeated searches443'sub' :1, // - declare a subroutine, possibly anonymously444'substr' :1, // - get or alter a portion of a string445symlink :1, // - create a symbolic link to a file446syscall :1, // - execute an arbitrary system call447sysopen :1, // - open a file, pipe, or descriptor448sysread :1, // - fixed-length unbuffered input from a filehandle449sysseek :1, // - position I/O pointer on handle used with sysread and syswrite450system :1, // - run a separate program451syswrite :1, // - fixed-length unbuffered output to a filehandle452tell :1, // - get current seekpointer on a filehandle453telldir :1, // - get current seekpointer on a directory handle454tie :1, // - bind a variable to an object class455tied :1, // - get a reference to the object underlying a tied variable456time :1, // - return number of seconds since 1970457times :1, // - return elapsed time for self and child processes458tr :null, // - transliterate a string459truncate :1, // - shorten a file460uc :1, // - return upper-case version of a string461ucfirst :1, // - return a string with just the next letter in upper case462umask :1, // - set file creation mode mask463undef :1, // - remove a variable or function definition464unlink :1, // - remove one link to a file465unpack :1, // - convert binary structure into normal perl variables466unshift :1, // - prepend more elements to the beginning of a list467untie :1, // - break a tie binding to a variable468use :1, // - load in a module at compile time469utime :1, // - set a file's last access and modify times470values :1, // - return a list of the values in a hash471vec :1, // - test or set particular bits in a string472wait :1, // - wait for any child process to die473waitpid :1, // - wait for a particular child process to die474wantarray :1, // - get void vs scalar vs list context of current subroutine call475warn :1, // - print debugging info476when :1, //477write :1, // - print a picture record478y :null}; // - transliterate a string479
480var RXstyle="string-2";481var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type482
483function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)484state.chain=null; // 12 3tail485state.style=null;486state.tail=null;487state.tokenize=function(stream,state){488var e=false,c,i=0;489while(c=stream.next()){490if(c===chain[i]&&!e){491if(chain[++i]!==undefined){492state.chain=chain[i];493state.style=style;494state.tail=tail;}495else if(tail)496stream.eatWhile(tail);497state.tokenize=tokenPerl;498return style;}499e=!e&&c=="\\";}500return style;};501return state.tokenize(stream,state);}502
503function tokenSOMETHING(stream,state,string){504state.tokenize=function(stream,state){505if(stream.string==string)506state.tokenize=tokenPerl;507stream.skipToEnd();508return "string";};509return state.tokenize(stream,state);}510
511function tokenPerl(stream,state){512if(stream.eatSpace())513return null;514if(state.chain)515return tokenChain(stream,state,state.chain,state.style,state.tail);516if(stream.match(/^(\-?((\d[\d_]*)?\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F_]+|0b[01_]+|\d[\d_]*(e[+-]?\d+)?)/))517return 'number';518if(stream.match(/^<<(?=[_a-zA-Z])/)){ // NOTE: <<SOMETHING\n...\nSOMETHING\n519stream.eatWhile(/\w/);520return tokenSOMETHING(stream,state,stream.current().substr(2));}521if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n522return tokenSOMETHING(stream,state,'=cut');}523var ch=stream.next();524if(ch=='"'||ch=="'"){ // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n525if(prefix(stream, 3)=="<<"+ch){526var p=stream.pos;527stream.eatWhile(/\w/);528var n=stream.current().substr(1);529if(n&&stream.eat(ch))530return tokenSOMETHING(stream,state,n);531stream.pos=p;}532return tokenChain(stream,state,[ch],"string");}533if(ch=="q"){534var c=look(stream, -2);535if(!(c&&/\w/.test(c))){536c=look(stream, 0);537if(c=="x"){538c=look(stream, 1);539if(c=="("){540eatSuffix(stream, 2);541return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}542if(c=="["){543eatSuffix(stream, 2);544return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}545if(c=="{"){546eatSuffix(stream, 2);547return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}548if(c=="<"){549eatSuffix(stream, 2);550return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}551if(/[\^'"!~\/]/.test(c)){552eatSuffix(stream, 1);553return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}554else if(c=="q"){555c=look(stream, 1);556if(c=="("){557eatSuffix(stream, 2);558return tokenChain(stream,state,[")"],"string");}559if(c=="["){560eatSuffix(stream, 2);561return tokenChain(stream,state,["]"],"string");}562if(c=="{"){563eatSuffix(stream, 2);564return tokenChain(stream,state,["}"],"string");}565if(c=="<"){566eatSuffix(stream, 2);567return tokenChain(stream,state,[">"],"string");}568if(/[\^'"!~\/]/.test(c)){569eatSuffix(stream, 1);570return tokenChain(stream,state,[stream.eat(c)],"string");}}571else if(c=="w"){572c=look(stream, 1);573if(c=="("){574eatSuffix(stream, 2);575return tokenChain(stream,state,[")"],"bracket");}576if(c=="["){577eatSuffix(stream, 2);578return tokenChain(stream,state,["]"],"bracket");}579if(c=="{"){580eatSuffix(stream, 2);581return tokenChain(stream,state,["}"],"bracket");}582if(c=="<"){583eatSuffix(stream, 2);584return tokenChain(stream,state,[">"],"bracket");}585if(/[\^'"!~\/]/.test(c)){586eatSuffix(stream, 1);587return tokenChain(stream,state,[stream.eat(c)],"bracket");}}588else if(c=="r"){589c=look(stream, 1);590if(c=="("){591eatSuffix(stream, 2);592return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}593if(c=="["){594eatSuffix(stream, 2);595return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}596if(c=="{"){597eatSuffix(stream, 2);598return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}599if(c=="<"){600eatSuffix(stream, 2);601return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}602if(/[\^'"!~\/]/.test(c)){603eatSuffix(stream, 1);604return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}605else if(/[\^'"!~\/(\[{<]/.test(c)){606if(c=="("){607eatSuffix(stream, 1);608return tokenChain(stream,state,[")"],"string");}609if(c=="["){610eatSuffix(stream, 1);611return tokenChain(stream,state,["]"],"string");}612if(c=="{"){613eatSuffix(stream, 1);614return tokenChain(stream,state,["}"],"string");}615if(c=="<"){616eatSuffix(stream, 1);617return tokenChain(stream,state,[">"],"string");}618if(/[\^'"!~\/]/.test(c)){619return tokenChain(stream,state,[stream.eat(c)],"string");}}}}620if(ch=="m"){621var c=look(stream, -2);622if(!(c&&/\w/.test(c))){623c=stream.eat(/[(\[{<\^'"!~\/]/);624if(c){625if(/[\^'"!~\/]/.test(c)){626return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}627if(c=="("){628return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}629if(c=="["){630return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}631if(c=="{"){632return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}633if(c=="<"){634return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}635if(ch=="s"){636var c=/[\/>\]})\w]/.test(look(stream, -2));637if(!c){638c=stream.eat(/[(\[{<\^'"!~\/]/);639if(c){640if(c=="[")641return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);642if(c=="{")643return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);644if(c=="<")645return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);646if(c=="(")647return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);648return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}649if(ch=="y"){650var c=/[\/>\]})\w]/.test(look(stream, -2));651if(!c){652c=stream.eat(/[(\[{<\^'"!~\/]/);653if(c){654if(c=="[")655return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);656if(c=="{")657return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);658if(c=="<")659return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);660if(c=="(")661return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);662return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}663if(ch=="t"){664var c=/[\/>\]})\w]/.test(look(stream, -2));665if(!c){666c=stream.eat("r");if(c){667c=stream.eat(/[(\[{<\^'"!~\/]/);668if(c){669if(c=="[")670return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);671if(c=="{")672return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);673if(c=="<")674return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);675if(c=="(")676return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);677return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}678if(ch=="`"){679return tokenChain(stream,state,[ch],"variable-2");}680if(ch=="/"){681if(!/~\s*$/.test(prefix(stream)))682return "operator";683else684return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}685if(ch=="$"){686var p=stream.pos;687if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))688return "variable-2";689else690stream.pos=p;}691if(/[$@%]/.test(ch)){692var p=stream.pos;693if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){694var c=stream.current();695if(PERL[c])696return "variable-2";}697stream.pos=p;}698if(/[$@%&]/.test(ch)){699if(stream.eatWhile(/[\w$]/)||stream.eat("{")&&stream.eatWhile(/[\w$]/)&&stream.eat("}")){700var c=stream.current();701if(PERL[c])702return "variable-2";703else704return "variable";}}705if(ch=="#"){706if(look(stream, -2)!="$"){707stream.skipToEnd();708return "comment";}}709if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){710var p=stream.pos;711stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);712if(PERL[stream.current()])713return "operator";714else715stream.pos=p;}716if(ch=="_"){717if(stream.pos==1){718if(suffix(stream, 6)=="_END__"){719return tokenChain(stream,state,['\0'],"comment");}720else if(suffix(stream, 7)=="_DATA__"){721return tokenChain(stream,state,['\0'],"variable-2");}722else if(suffix(stream, 7)=="_C__"){723return tokenChain(stream,state,['\0'],"string");}}}724if(/\w/.test(ch)){725var p=stream.pos;726if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}"))727return "string";728else729stream.pos=p;}730if(/[A-Z]/.test(ch)){731var l=look(stream, -2);732var p=stream.pos;733stream.eatWhile(/[A-Z_]/);734if(/[\da-z]/.test(look(stream, 0))){735stream.pos=p;}736else{737var c=PERL[stream.current()];738if(!c)739return "meta";740if(c[1])741c=c[0];742if(l!=":"){743if(c==1)744return "keyword";745else if(c==2)746return "def";747else if(c==3)748return "atom";749else if(c==4)750return "operator";751else if(c==5)752return "variable-2";753else754return "meta";}755else756return "meta";}}757if(/[a-zA-Z_]/.test(ch)){758var l=look(stream, -2);759stream.eatWhile(/\w/);760var c=PERL[stream.current()];761if(!c)762return "meta";763if(c[1])764c=c[0];765if(l!=":"){766if(c==1)767return "keyword";768else if(c==2)769return "def";770else if(c==3)771return "atom";772else if(c==4)773return "operator";774else if(c==5)775return "variable-2";776else777return "meta";}778else779return "meta";}780return null;}781
782return {783startState: function() {784return {785tokenize: tokenPerl,786chain: null,787style: null,788tail: null789};790},791token: function(stream, state) {792return (state.tokenize || tokenPerl)(stream, state);793},794lineComment: '#'795};796});797
798CodeMirror.registerHelper("wordChars", "perl", /[\w$]/);799
800CodeMirror.defineMIME("text/x-perl", "perl");801
802// it's like "peek", but need for look-ahead or look-behind if index < 0
803function look(stream, c){804return stream.string.charAt(stream.pos+(c||0));805}
806
807// return a part of prefix of current stream from current position
808function prefix(stream, c){809if(c){810var x=stream.pos-c;811return stream.string.substr((x>=0?x:0),c);}812else{813return stream.string.substr(0,stream.pos-1);814}815}
816
817// return a part of suffix of current stream from current position
818function suffix(stream, c){819var y=stream.string.length;820var x=y-stream.pos+1;821return stream.string.substr(stream.pos,(c&&c<y?c:x));822}
823
824// eating and vomiting a part of stream from current position
825function eatSuffix(stream, c){826var x=stream.pos+c;827var y;828if(x<=0)829stream.pos=0;830else if(x>=(y=stream.string.length-1))831stream.pos=y;832else833stream.pos=x;834}
835
836});837