perl.js 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  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. (function(mod) {
  4. if (typeof exports == "object" && typeof module == "object") // CommonJS
  5. mod(require("../../lib/codemirror"));
  6. else if (typeof define == "function" && define.amd) // AMD
  7. define(["../../lib/codemirror"], mod);
  8. else // Plain browser env
  9. mod(CodeMirror);
  10. })(function(CodeMirror) {
  11. "use strict";
  12. CodeMirror.defineMode("perl",function(){
  13. // http://perldoc.perl.org
  14. var PERL={ // null - magic touch
  15. // 1 - keyword
  16. // 2 - def
  17. // 3 - atom
  18. // 4 - operator
  19. // 5 - variable-2 (predefined)
  20. // [x,y] - x=1,2,3; y=must be defined if x{...}
  21. // PERL operators
  22. '->' : 4,
  23. '++' : 4,
  24. '--' : 4,
  25. '**' : 4,
  26. // ! ~ \ and unary + and -
  27. '=~' : 4,
  28. '!~' : 4,
  29. '*' : 4,
  30. '/' : 4,
  31. '%' : 4,
  32. 'x' : 4,
  33. '+' : 4,
  34. '-' : 4,
  35. '.' : 4,
  36. '<<' : 4,
  37. '>>' : 4,
  38. // named unary operators
  39. '<' : 4,
  40. '>' : 4,
  41. '<=' : 4,
  42. '>=' : 4,
  43. 'lt' : 4,
  44. 'gt' : 4,
  45. 'le' : 4,
  46. 'ge' : 4,
  47. '==' : 4,
  48. '!=' : 4,
  49. '<=>' : 4,
  50. 'eq' : 4,
  51. 'ne' : 4,
  52. 'cmp' : 4,
  53. '~~' : 4,
  54. '&' : 4,
  55. '|' : 4,
  56. '^' : 4,
  57. '&&' : 4,
  58. '||' : 4,
  59. '//' : 4,
  60. '..' : 4,
  61. '...' : 4,
  62. '?' : 4,
  63. ':' : 4,
  64. '=' : 4,
  65. '+=' : 4,
  66. '-=' : 4,
  67. '*=' : 4, // etc. ???
  68. ',' : 4,
  69. '=>' : 4,
  70. '::' : 4,
  71. // list operators (rightward)
  72. 'not' : 4,
  73. 'and' : 4,
  74. 'or' : 4,
  75. 'xor' : 4,
  76. // 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?;)
  77. 'BEGIN' : [5,1],
  78. 'END' : [5,1],
  79. 'PRINT' : [5,1],
  80. 'PRINTF' : [5,1],
  81. 'GETC' : [5,1],
  82. 'READ' : [5,1],
  83. 'READLINE' : [5,1],
  84. 'DESTROY' : [5,1],
  85. 'TIE' : [5,1],
  86. 'TIEHANDLE' : [5,1],
  87. 'UNTIE' : [5,1],
  88. 'STDIN' : 5,
  89. 'STDIN_TOP' : 5,
  90. 'STDOUT' : 5,
  91. 'STDOUT_TOP' : 5,
  92. 'STDERR' : 5,
  93. 'STDERR_TOP' : 5,
  94. '$ARG' : 5,
  95. '$_' : 5,
  96. '@ARG' : 5,
  97. '@_' : 5,
  98. '$LIST_SEPARATOR' : 5,
  99. '$"' : 5,
  100. '$PROCESS_ID' : 5,
  101. '$PID' : 5,
  102. '$$' : 5,
  103. '$REAL_GROUP_ID' : 5,
  104. '$GID' : 5,
  105. '$(' : 5,
  106. '$EFFECTIVE_GROUP_ID' : 5,
  107. '$EGID' : 5,
  108. '$)' : 5,
  109. '$PROGRAM_NAME' : 5,
  110. '$0' : 5,
  111. '$SUBSCRIPT_SEPARATOR' : 5,
  112. '$SUBSEP' : 5,
  113. '$;' : 5,
  114. '$REAL_USER_ID' : 5,
  115. '$UID' : 5,
  116. '$<' : 5,
  117. '$EFFECTIVE_USER_ID' : 5,
  118. '$EUID' : 5,
  119. '$>' : 5,
  120. '$a' : 5,
  121. '$b' : 5,
  122. '$COMPILING' : 5,
  123. '$^C' : 5,
  124. '$DEBUGGING' : 5,
  125. '$^D' : 5,
  126. '${^ENCODING}' : 5,
  127. '$ENV' : 5,
  128. '%ENV' : 5,
  129. '$SYSTEM_FD_MAX' : 5,
  130. '$^F' : 5,
  131. '@F' : 5,
  132. '${^GLOBAL_PHASE}' : 5,
  133. '$^H' : 5,
  134. '%^H' : 5,
  135. '@INC' : 5,
  136. '%INC' : 5,
  137. '$INPLACE_EDIT' : 5,
  138. '$^I' : 5,
  139. '$^M' : 5,
  140. '$OSNAME' : 5,
  141. '$^O' : 5,
  142. '${^OPEN}' : 5,
  143. '$PERLDB' : 5,
  144. '$^P' : 5,
  145. '$SIG' : 5,
  146. '%SIG' : 5,
  147. '$BASETIME' : 5,
  148. '$^T' : 5,
  149. '${^TAINT}' : 5,
  150. '${^UNICODE}' : 5,
  151. '${^UTF8CACHE}' : 5,
  152. '${^UTF8LOCALE}' : 5,
  153. '$PERL_VERSION' : 5,
  154. '$^V' : 5,
  155. '${^WIN32_SLOPPY_STAT}' : 5,
  156. '$EXECUTABLE_NAME' : 5,
  157. '$^X' : 5,
  158. '$1' : 5, // - regexp $1, $2...
  159. '$MATCH' : 5,
  160. '$&' : 5,
  161. '${^MATCH}' : 5,
  162. '$PREMATCH' : 5,
  163. '$`' : 5,
  164. '${^PREMATCH}' : 5,
  165. '$POSTMATCH' : 5,
  166. "$'" : 5,
  167. '${^POSTMATCH}' : 5,
  168. '$LAST_PAREN_MATCH' : 5,
  169. '$+' : 5,
  170. '$LAST_SUBMATCH_RESULT' : 5,
  171. '$^N' : 5,
  172. '@LAST_MATCH_END' : 5,
  173. '@+' : 5,
  174. '%LAST_PAREN_MATCH' : 5,
  175. '%+' : 5,
  176. '@LAST_MATCH_START' : 5,
  177. '@-' : 5,
  178. '%LAST_MATCH_START' : 5,
  179. '%-' : 5,
  180. '$LAST_REGEXP_CODE_RESULT' : 5,
  181. '$^R' : 5,
  182. '${^RE_DEBUG_FLAGS}' : 5,
  183. '${^RE_TRIE_MAXBUF}' : 5,
  184. '$ARGV' : 5,
  185. '@ARGV' : 5,
  186. 'ARGV' : 5,
  187. 'ARGVOUT' : 5,
  188. '$OUTPUT_FIELD_SEPARATOR' : 5,
  189. '$OFS' : 5,
  190. '$,' : 5,
  191. '$INPUT_LINE_NUMBER' : 5,
  192. '$NR' : 5,
  193. '$.' : 5,
  194. '$INPUT_RECORD_SEPARATOR' : 5,
  195. '$RS' : 5,
  196. '$/' : 5,
  197. '$OUTPUT_RECORD_SEPARATOR' : 5,
  198. '$ORS' : 5,
  199. '$\\' : 5,
  200. '$OUTPUT_AUTOFLUSH' : 5,
  201. '$|' : 5,
  202. '$ACCUMULATOR' : 5,
  203. '$^A' : 5,
  204. '$FORMAT_FORMFEED' : 5,
  205. '$^L' : 5,
  206. '$FORMAT_PAGE_NUMBER' : 5,
  207. '$%' : 5,
  208. '$FORMAT_LINES_LEFT' : 5,
  209. '$-' : 5,
  210. '$FORMAT_LINE_BREAK_CHARACTERS' : 5,
  211. '$:' : 5,
  212. '$FORMAT_LINES_PER_PAGE' : 5,
  213. '$=' : 5,
  214. '$FORMAT_TOP_NAME' : 5,
  215. '$^' : 5,
  216. '$FORMAT_NAME' : 5,
  217. '$~' : 5,
  218. '${^CHILD_ERROR_NATIVE}' : 5,
  219. '$EXTENDED_OS_ERROR' : 5,
  220. '$^E' : 5,
  221. '$EXCEPTIONS_BEING_CAUGHT' : 5,
  222. '$^S' : 5,
  223. '$WARNING' : 5,
  224. '$^W' : 5,
  225. '${^WARNING_BITS}' : 5,
  226. '$OS_ERROR' : 5,
  227. '$ERRNO' : 5,
  228. '$!' : 5,
  229. '%OS_ERROR' : 5,
  230. '%ERRNO' : 5,
  231. '%!' : 5,
  232. '$CHILD_ERROR' : 5,
  233. '$?' : 5,
  234. '$EVAL_ERROR' : 5,
  235. '$@' : 5,
  236. '$OFMT' : 5,
  237. '$#' : 5,
  238. '$*' : 5,
  239. '$ARRAY_BASE' : 5,
  240. '$[' : 5,
  241. '$OLD_PERL_VERSION' : 5,
  242. '$]' : 5,
  243. // PERL blocks
  244. 'if' :[1,1],
  245. elsif :[1,1],
  246. 'else' :[1,1],
  247. 'while' :[1,1],
  248. unless :[1,1],
  249. 'for' :[1,1],
  250. foreach :[1,1],
  251. // PERL functions
  252. 'abs' :1, // - absolute value function
  253. accept :1, // - accept an incoming socket connect
  254. alarm :1, // - schedule a SIGALRM
  255. 'atan2' :1, // - arctangent of Y/X in the range -PI to PI
  256. bind :1, // - binds an address to a socket
  257. binmode :1, // - prepare binary files for I/O
  258. bless :1, // - create an object
  259. bootstrap :1, //
  260. 'break' :1, // - break out of a "given" block
  261. caller :1, // - get context of the current subroutine call
  262. chdir :1, // - change your current working directory
  263. chmod :1, // - changes the permissions on a list of files
  264. chomp :1, // - remove a trailing record separator from a string
  265. chop :1, // - remove the last character from a string
  266. chown :1, // - change the owership on a list of files
  267. chr :1, // - get character this number represents
  268. chroot :1, // - make directory new root for path lookups
  269. close :1, // - close file (or pipe or socket) handle
  270. closedir :1, // - close directory handle
  271. connect :1, // - connect to a remote socket
  272. 'continue' :[1,1], // - optional trailing block in a while or foreach
  273. 'cos' :1, // - cosine function
  274. crypt :1, // - one-way passwd-style encryption
  275. dbmclose :1, // - breaks binding on a tied dbm file
  276. dbmopen :1, // - create binding on a tied dbm file
  277. 'default' :1, //
  278. defined :1, // - test whether a value, variable, or function is defined
  279. 'delete' :1, // - deletes a value from a hash
  280. die :1, // - raise an exception or bail out
  281. 'do' :1, // - turn a BLOCK into a TERM
  282. dump :1, // - create an immediate core dump
  283. each :1, // - retrieve the next key/value pair from a hash
  284. endgrent :1, // - be done using group file
  285. endhostent :1, // - be done using hosts file
  286. endnetent :1, // - be done using networks file
  287. endprotoent :1, // - be done using protocols file
  288. endpwent :1, // - be done using passwd file
  289. endservent :1, // - be done using services file
  290. eof :1, // - test a filehandle for its end
  291. 'eval' :1, // - catch exceptions or compile and run code
  292. 'exec' :1, // - abandon this program to run another
  293. exists :1, // - test whether a hash key is present
  294. exit :1, // - terminate this program
  295. 'exp' :1, // - raise I to a power
  296. fcntl :1, // - file control system call
  297. fileno :1, // - return file descriptor from filehandle
  298. flock :1, // - lock an entire file with an advisory lock
  299. fork :1, // - create a new process just like this one
  300. format :1, // - declare a picture format with use by the write() function
  301. formline :1, // - internal function used for formats
  302. getc :1, // - get the next character from the filehandle
  303. getgrent :1, // - get next group record
  304. getgrgid :1, // - get group record given group user ID
  305. getgrnam :1, // - get group record given group name
  306. gethostbyaddr :1, // - get host record given its address
  307. gethostbyname :1, // - get host record given name
  308. gethostent :1, // - get next hosts record
  309. getlogin :1, // - return who logged in at this tty
  310. getnetbyaddr :1, // - get network record given its address
  311. getnetbyname :1, // - get networks record given name
  312. getnetent :1, // - get next networks record
  313. getpeername :1, // - find the other end of a socket connection
  314. getpgrp :1, // - get process group
  315. getppid :1, // - get parent process ID
  316. getpriority :1, // - get current nice value
  317. getprotobyname :1, // - get protocol record given name
  318. getprotobynumber :1, // - get protocol record numeric protocol
  319. getprotoent :1, // - get next protocols record
  320. getpwent :1, // - get next passwd record
  321. getpwnam :1, // - get passwd record given user login name
  322. getpwuid :1, // - get passwd record given user ID
  323. getservbyname :1, // - get services record given its name
  324. getservbyport :1, // - get services record given numeric port
  325. getservent :1, // - get next services record
  326. getsockname :1, // - retrieve the sockaddr for a given socket
  327. getsockopt :1, // - get socket options on a given socket
  328. given :1, //
  329. glob :1, // - expand filenames using wildcards
  330. gmtime :1, // - convert UNIX time into record or string using Greenwich time
  331. 'goto' :1, // - create spaghetti code
  332. grep :1, // - locate elements in a list test true against a given criterion
  333. hex :1, // - convert a string to a hexadecimal number
  334. 'import' :1, // - patch a module's namespace into your own
  335. index :1, // - find a substring within a string
  336. 'int' :1, // - get the integer portion of a number
  337. ioctl :1, // - system-dependent device control system call
  338. 'join' :1, // - join a list into a string using a separator
  339. keys :1, // - retrieve list of indices from a hash
  340. kill :1, // - send a signal to a process or process group
  341. last :1, // - exit a block prematurely
  342. lc :1, // - return lower-case version of a string
  343. lcfirst :1, // - return a string with just the next letter in lower case
  344. length :1, // - return the number of bytes in a string
  345. 'link' :1, // - create a hard link in the filesytem
  346. listen :1, // - register your socket as a server
  347. local : 2, // - create a temporary value for a global variable (dynamic scoping)
  348. localtime :1, // - convert UNIX time into record or string using local time
  349. lock :1, // - get a thread lock on a variable, subroutine, or method
  350. 'log' :1, // - retrieve the natural logarithm for a number
  351. lstat :1, // - stat a symbolic link
  352. m :null, // - match a string with a regular expression pattern
  353. map :1, // - apply a change to a list to get back a new list with the changes
  354. mkdir :1, // - create a directory
  355. msgctl :1, // - SysV IPC message control operations
  356. msgget :1, // - get SysV IPC message queue
  357. msgrcv :1, // - receive a SysV IPC message from a message queue
  358. msgsnd :1, // - send a SysV IPC message to a message queue
  359. my : 2, // - declare and assign a local variable (lexical scoping)
  360. 'new' :1, //
  361. next :1, // - iterate a block prematurely
  362. no :1, // - unimport some module symbols or semantics at compile time
  363. oct :1, // - convert a string to an octal number
  364. open :1, // - open a file, pipe, or descriptor
  365. opendir :1, // - open a directory
  366. ord :1, // - find a character's numeric representation
  367. our : 2, // - declare and assign a package variable (lexical scoping)
  368. pack :1, // - convert a list into a binary representation
  369. 'package' :1, // - declare a separate global namespace
  370. pipe :1, // - open a pair of connected filehandles
  371. pop :1, // - remove the last element from an array and return it
  372. pos :1, // - find or set the offset for the last/next m//g search
  373. print :1, // - output a list to a filehandle
  374. printf :1, // - output a formatted list to a filehandle
  375. prototype :1, // - get the prototype (if any) of a subroutine
  376. push :1, // - append one or more elements to an array
  377. q :null, // - singly quote a string
  378. qq :null, // - doubly quote a string
  379. qr :null, // - Compile pattern
  380. quotemeta :null, // - quote regular expression magic characters
  381. qw :null, // - quote a list of words
  382. qx :null, // - backquote quote a string
  383. rand :1, // - retrieve the next pseudorandom number
  384. read :1, // - fixed-length buffered input from a filehandle
  385. readdir :1, // - get a directory from a directory handle
  386. readline :1, // - fetch a record from a file
  387. readlink :1, // - determine where a symbolic link is pointing
  388. readpipe :1, // - execute a system command and collect standard output
  389. recv :1, // - receive a message over a Socket
  390. redo :1, // - start this loop iteration over again
  391. ref :1, // - find out the type of thing being referenced
  392. rename :1, // - change a filename
  393. require :1, // - load in external functions from a library at runtime
  394. reset :1, // - clear all variables of a given name
  395. 'return' :1, // - get out of a function early
  396. reverse :1, // - flip a string or a list
  397. rewinddir :1, // - reset directory handle
  398. rindex :1, // - right-to-left substring search
  399. rmdir :1, // - remove a directory
  400. s :null, // - replace a pattern with a string
  401. say :1, // - print with newline
  402. scalar :1, // - force a scalar context
  403. seek :1, // - reposition file pointer for random-access I/O
  404. seekdir :1, // - reposition directory pointer
  405. select :1, // - reset default output or do I/O multiplexing
  406. semctl :1, // - SysV semaphore control operations
  407. semget :1, // - get set of SysV semaphores
  408. semop :1, // - SysV semaphore operations
  409. send :1, // - send a message over a socket
  410. setgrent :1, // - prepare group file for use
  411. sethostent :1, // - prepare hosts file for use
  412. setnetent :1, // - prepare networks file for use
  413. setpgrp :1, // - set the process group of a process
  414. setpriority :1, // - set a process's nice value
  415. setprotoent :1, // - prepare protocols file for use
  416. setpwent :1, // - prepare passwd file for use
  417. setservent :1, // - prepare services file for use
  418. setsockopt :1, // - set some socket options
  419. shift :1, // - remove the first element of an array, and return it
  420. shmctl :1, // - SysV shared memory operations
  421. shmget :1, // - get SysV shared memory segment identifier
  422. shmread :1, // - read SysV shared memory
  423. shmwrite :1, // - write SysV shared memory
  424. shutdown :1, // - close down just half of a socket connection
  425. 'sin' :1, // - return the sine of a number
  426. sleep :1, // - block for some number of seconds
  427. socket :1, // - create a socket
  428. socketpair :1, // - create a pair of sockets
  429. 'sort' :1, // - sort a list of values
  430. splice :1, // - add or remove elements anywhere in an array
  431. 'split' :1, // - split up a string using a regexp delimiter
  432. sprintf :1, // - formatted print into a string
  433. 'sqrt' :1, // - square root function
  434. srand :1, // - seed the random number generator
  435. stat :1, // - get a file's status information
  436. state :1, // - declare and assign a state variable (persistent lexical scoping)
  437. study :1, // - optimize input data for repeated searches
  438. 'sub' :1, // - declare a subroutine, possibly anonymously
  439. 'substr' :1, // - get or alter a portion of a stirng
  440. symlink :1, // - create a symbolic link to a file
  441. syscall :1, // - execute an arbitrary system call
  442. sysopen :1, // - open a file, pipe, or descriptor
  443. sysread :1, // - fixed-length unbuffered input from a filehandle
  444. sysseek :1, // - position I/O pointer on handle used with sysread and syswrite
  445. system :1, // - run a separate program
  446. syswrite :1, // - fixed-length unbuffered output to a filehandle
  447. tell :1, // - get current seekpointer on a filehandle
  448. telldir :1, // - get current seekpointer on a directory handle
  449. tie :1, // - bind a variable to an object class
  450. tied :1, // - get a reference to the object underlying a tied variable
  451. time :1, // - return number of seconds since 1970
  452. times :1, // - return elapsed time for self and child processes
  453. tr :null, // - transliterate a string
  454. truncate :1, // - shorten a file
  455. uc :1, // - return upper-case version of a string
  456. ucfirst :1, // - return a string with just the next letter in upper case
  457. umask :1, // - set file creation mode mask
  458. undef :1, // - remove a variable or function definition
  459. unlink :1, // - remove one link to a file
  460. unpack :1, // - convert binary structure into normal perl variables
  461. unshift :1, // - prepend more elements to the beginning of a list
  462. untie :1, // - break a tie binding to a variable
  463. use :1, // - load in a module at compile time
  464. utime :1, // - set a file's last access and modify times
  465. values :1, // - return a list of the values in a hash
  466. vec :1, // - test or set particular bits in a string
  467. wait :1, // - wait for any child process to die
  468. waitpid :1, // - wait for a particular child process to die
  469. wantarray :1, // - get void vs scalar vs list context of current subroutine call
  470. warn :1, // - print debugging info
  471. when :1, //
  472. write :1, // - print a picture record
  473. y :null}; // - transliterate a string
  474. var RXstyle="string-2";
  475. var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
  476. function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
  477. state.chain=null; // 12 3tail
  478. state.style=null;
  479. state.tail=null;
  480. state.tokenize=function(stream,state){
  481. var e=false,c,i=0;
  482. while(c=stream.next()){
  483. if(c===chain[i]&&!e){
  484. if(chain[++i]!==undefined){
  485. state.chain=chain[i];
  486. state.style=style;
  487. state.tail=tail;}
  488. else if(tail)
  489. stream.eatWhile(tail);
  490. state.tokenize=tokenPerl;
  491. return style;}
  492. e=!e&&c=="\\";}
  493. return style;};
  494. return state.tokenize(stream,state);}
  495. function tokenSOMETHING(stream,state,string){
  496. state.tokenize=function(stream,state){
  497. if(stream.string==string)
  498. state.tokenize=tokenPerl;
  499. stream.skipToEnd();
  500. return "string";};
  501. return state.tokenize(stream,state);}
  502. function tokenPerl(stream,state){
  503. if(stream.eatSpace())
  504. return null;
  505. if(state.chain)
  506. return tokenChain(stream,state,state.chain,state.style,state.tail);
  507. if(stream.match(/^\-?[\d\.]/,false))
  508. if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/))
  509. return 'number';
  510. if(stream.match(/^<<(?=\w)/)){ // NOTE: <<SOMETHING\n...\nSOMETHING\n
  511. stream.eatWhile(/\w/);
  512. return tokenSOMETHING(stream,state,stream.current().substr(2));}
  513. if(stream.sol()&&stream.match(/^\=item(?!\w)/)){// NOTE: \n=item...\n=cut\n
  514. return tokenSOMETHING(stream,state,'=cut');}
  515. var ch=stream.next();
  516. if(ch=='"'||ch=="'"){ // NOTE: ' or " or <<'SOMETHING'\n...\nSOMETHING\n or <<"SOMETHING"\n...\nSOMETHING\n
  517. if(prefix(stream, 3)=="<<"+ch){
  518. var p=stream.pos;
  519. stream.eatWhile(/\w/);
  520. var n=stream.current().substr(1);
  521. if(n&&stream.eat(ch))
  522. return tokenSOMETHING(stream,state,n);
  523. stream.pos=p;}
  524. return tokenChain(stream,state,[ch],"string");}
  525. if(ch=="q"){
  526. var c=look(stream, -2);
  527. if(!(c&&/\w/.test(c))){
  528. c=look(stream, 0);
  529. if(c=="x"){
  530. c=look(stream, 1);
  531. if(c=="("){
  532. eatSuffix(stream, 2);
  533. return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
  534. if(c=="["){
  535. eatSuffix(stream, 2);
  536. return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
  537. if(c=="{"){
  538. eatSuffix(stream, 2);
  539. return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
  540. if(c=="<"){
  541. eatSuffix(stream, 2);
  542. return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
  543. if(/[\^'"!~\/]/.test(c)){
  544. eatSuffix(stream, 1);
  545. return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
  546. else if(c=="q"){
  547. c=look(stream, 1);
  548. if(c=="("){
  549. eatSuffix(stream, 2);
  550. return tokenChain(stream,state,[")"],"string");}
  551. if(c=="["){
  552. eatSuffix(stream, 2);
  553. return tokenChain(stream,state,["]"],"string");}
  554. if(c=="{"){
  555. eatSuffix(stream, 2);
  556. return tokenChain(stream,state,["}"],"string");}
  557. if(c=="<"){
  558. eatSuffix(stream, 2);
  559. return tokenChain(stream,state,[">"],"string");}
  560. if(/[\^'"!~\/]/.test(c)){
  561. eatSuffix(stream, 1);
  562. return tokenChain(stream,state,[stream.eat(c)],"string");}}
  563. else if(c=="w"){
  564. c=look(stream, 1);
  565. if(c=="("){
  566. eatSuffix(stream, 2);
  567. return tokenChain(stream,state,[")"],"bracket");}
  568. if(c=="["){
  569. eatSuffix(stream, 2);
  570. return tokenChain(stream,state,["]"],"bracket");}
  571. if(c=="{"){
  572. eatSuffix(stream, 2);
  573. return tokenChain(stream,state,["}"],"bracket");}
  574. if(c=="<"){
  575. eatSuffix(stream, 2);
  576. return tokenChain(stream,state,[">"],"bracket");}
  577. if(/[\^'"!~\/]/.test(c)){
  578. eatSuffix(stream, 1);
  579. return tokenChain(stream,state,[stream.eat(c)],"bracket");}}
  580. else if(c=="r"){
  581. c=look(stream, 1);
  582. if(c=="("){
  583. eatSuffix(stream, 2);
  584. return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
  585. if(c=="["){
  586. eatSuffix(stream, 2);
  587. return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
  588. if(c=="{"){
  589. eatSuffix(stream, 2);
  590. return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
  591. if(c=="<"){
  592. eatSuffix(stream, 2);
  593. return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
  594. if(/[\^'"!~\/]/.test(c)){
  595. eatSuffix(stream, 1);
  596. return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
  597. else if(/[\^'"!~\/(\[{<]/.test(c)){
  598. if(c=="("){
  599. eatSuffix(stream, 1);
  600. return tokenChain(stream,state,[")"],"string");}
  601. if(c=="["){
  602. eatSuffix(stream, 1);
  603. return tokenChain(stream,state,["]"],"string");}
  604. if(c=="{"){
  605. eatSuffix(stream, 1);
  606. return tokenChain(stream,state,["}"],"string");}
  607. if(c=="<"){
  608. eatSuffix(stream, 1);
  609. return tokenChain(stream,state,[">"],"string");}
  610. if(/[\^'"!~\/]/.test(c)){
  611. return tokenChain(stream,state,[stream.eat(c)],"string");}}}}
  612. if(ch=="m"){
  613. var c=look(stream, -2);
  614. if(!(c&&/\w/.test(c))){
  615. c=stream.eat(/[(\[{<\^'"!~\/]/);
  616. if(c){
  617. if(/[\^'"!~\/]/.test(c)){
  618. return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}
  619. if(c=="("){
  620. return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
  621. if(c=="["){
  622. return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
  623. if(c=="{"){
  624. return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
  625. if(c=="<"){
  626. return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}
  627. if(ch=="s"){
  628. var c=/[\/>\]})\w]/.test(look(stream, -2));
  629. if(!c){
  630. c=stream.eat(/[(\[{<\^'"!~\/]/);
  631. if(c){
  632. if(c=="[")
  633. return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
  634. if(c=="{")
  635. return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
  636. if(c=="<")
  637. return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
  638. if(c=="(")
  639. return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
  640. return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
  641. if(ch=="y"){
  642. var c=/[\/>\]})\w]/.test(look(stream, -2));
  643. if(!c){
  644. c=stream.eat(/[(\[{<\^'"!~\/]/);
  645. if(c){
  646. if(c=="[")
  647. return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
  648. if(c=="{")
  649. return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
  650. if(c=="<")
  651. return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
  652. if(c=="(")
  653. return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
  654. return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
  655. if(ch=="t"){
  656. var c=/[\/>\]})\w]/.test(look(stream, -2));
  657. if(!c){
  658. c=stream.eat("r");if(c){
  659. c=stream.eat(/[(\[{<\^'"!~\/]/);
  660. if(c){
  661. if(c=="[")
  662. return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
  663. if(c=="{")
  664. return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
  665. if(c=="<")
  666. return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
  667. if(c=="(")
  668. return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
  669. return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}
  670. if(ch=="`"){
  671. return tokenChain(stream,state,[ch],"variable-2");}
  672. if(ch=="/"){
  673. if(!/~\s*$/.test(prefix(stream)))
  674. return "operator";
  675. else
  676. return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}
  677. if(ch=="$"){
  678. var p=stream.pos;
  679. if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
  680. return "variable-2";
  681. else
  682. stream.pos=p;}
  683. if(/[$@%]/.test(ch)){
  684. var p=stream.pos;
  685. if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
  686. var c=stream.current();
  687. if(PERL[c])
  688. return "variable-2";}
  689. stream.pos=p;}
  690. if(/[$@%&]/.test(ch)){
  691. if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){
  692. var c=stream.current();
  693. if(PERL[c])
  694. return "variable-2";
  695. else
  696. return "variable";}}
  697. if(ch=="#"){
  698. if(look(stream, -2)!="$"){
  699. stream.skipToEnd();
  700. return "comment";}}
  701. if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
  702. var p=stream.pos;
  703. stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
  704. if(PERL[stream.current()])
  705. return "operator";
  706. else
  707. stream.pos=p;}
  708. if(ch=="_"){
  709. if(stream.pos==1){
  710. if(suffix(stream, 6)=="_END__"){
  711. return tokenChain(stream,state,['\0'],"comment");}
  712. else if(suffix(stream, 7)=="_DATA__"){
  713. return tokenChain(stream,state,['\0'],"variable-2");}
  714. else if(suffix(stream, 7)=="_C__"){
  715. return tokenChain(stream,state,['\0'],"string");}}}
  716. if(/\w/.test(ch)){
  717. var p=stream.pos;
  718. if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}"))
  719. return "string";
  720. else
  721. stream.pos=p;}
  722. if(/[A-Z]/.test(ch)){
  723. var l=look(stream, -2);
  724. var p=stream.pos;
  725. stream.eatWhile(/[A-Z_]/);
  726. if(/[\da-z]/.test(look(stream, 0))){
  727. stream.pos=p;}
  728. else{
  729. var c=PERL[stream.current()];
  730. if(!c)
  731. return "meta";
  732. if(c[1])
  733. c=c[0];
  734. if(l!=":"){
  735. if(c==1)
  736. return "keyword";
  737. else if(c==2)
  738. return "def";
  739. else if(c==3)
  740. return "atom";
  741. else if(c==4)
  742. return "operator";
  743. else if(c==5)
  744. return "variable-2";
  745. else
  746. return "meta";}
  747. else
  748. return "meta";}}
  749. if(/[a-zA-Z_]/.test(ch)){
  750. var l=look(stream, -2);
  751. stream.eatWhile(/\w/);
  752. var c=PERL[stream.current()];
  753. if(!c)
  754. return "meta";
  755. if(c[1])
  756. c=c[0];
  757. if(l!=":"){
  758. if(c==1)
  759. return "keyword";
  760. else if(c==2)
  761. return "def";
  762. else if(c==3)
  763. return "atom";
  764. else if(c==4)
  765. return "operator";
  766. else if(c==5)
  767. return "variable-2";
  768. else
  769. return "meta";}
  770. else
  771. return "meta";}
  772. return null;}
  773. return{
  774. startState:function(){
  775. return{
  776. tokenize:tokenPerl,
  777. chain:null,
  778. style:null,
  779. tail:null};},
  780. token:function(stream,state){
  781. return (state.tokenize||tokenPerl)(stream,state);},
  782. electricChars:"{}"};});
  783. CodeMirror.defineMIME("text/x-perl", "perl");
  784. // it's like "peek", but need for look-ahead or look-behind if index < 0
  785. function look(stream, c){
  786. return stream.string.charAt(stream.pos+(c||0));
  787. }
  788. // return a part of prefix of current stream from current position
  789. function prefix(stream, c){
  790. if(c){
  791. var x=stream.pos-c;
  792. return stream.string.substr((x>=0?x:0),c);}
  793. else{
  794. return stream.string.substr(0,stream.pos-1);
  795. }
  796. }
  797. // return a part of suffix of current stream from current position
  798. function suffix(stream, c){
  799. var y=stream.string.length;
  800. var x=y-stream.pos+1;
  801. return stream.string.substr(stream.pos,(c&&c<y?c:x));
  802. }
  803. // eating and vomiting a part of stream from current position
  804. function eatSuffix(stream, c){
  805. var x=stream.pos+c;
  806. var y;
  807. if(x<=0)
  808. stream.pos=0;
  809. else if(x>=(y=stream.string.length-1))
  810. stream.pos=y;
  811. else
  812. stream.pos=x;
  813. }
  814. });