perl.js 55 KB

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