vbscript.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. /*
  4. For extra ASP classic objects, initialize CodeMirror instance with this option:
  5. isASP: true
  6. E.G.:
  7. var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
  8. lineNumbers: true,
  9. isASP: true
  10. });
  11. */
  12. ;(function (mod) {
  13. if (typeof exports == 'object' && typeof module == 'object')
  14. // CommonJS
  15. mod(require('../../lib/codemirror'))
  16. else if (typeof define == 'function' && define.amd)
  17. // AMD
  18. define(['../../lib/codemirror'], mod)
  19. // Plain browser env
  20. else mod(CodeMirror)
  21. })(function (CodeMirror) {
  22. 'use strict'
  23. CodeMirror.defineMode('vbscript', function (conf, parserConf) {
  24. var ERRORCLASS = 'error'
  25. function wordRegexp(words) {
  26. return new RegExp('^((' + words.join(')|(') + '))\\b', 'i')
  27. }
  28. var singleOperators = new RegExp('^[\\+\\-\\*/&\\\\\\^<>=]')
  29. var doubleOperators = new RegExp('^((<>)|(<=)|(>=))')
  30. var singleDelimiters = new RegExp('^[\\.,]')
  31. var brackets = new RegExp('^[\\(\\)]')
  32. var identifiers = new RegExp('^[A-Za-z][_A-Za-z0-9]*')
  33. var openingKeywords = ['class', 'sub', 'select', 'while', 'if', 'function', 'property', 'with', 'for']
  34. var middleKeywords = ['else', 'elseif', 'case']
  35. var endKeywords = ['next', 'loop', 'wend']
  36. var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp'])
  37. var commonkeywords = [
  38. 'dim',
  39. 'redim',
  40. 'then',
  41. 'until',
  42. 'randomize',
  43. 'byval',
  44. 'byref',
  45. 'new',
  46. 'property',
  47. 'exit',
  48. 'in',
  49. 'const',
  50. 'private',
  51. 'public',
  52. 'get',
  53. 'set',
  54. 'let',
  55. 'stop',
  56. 'on error resume next',
  57. 'on error goto 0',
  58. 'option explicit',
  59. 'call',
  60. 'me',
  61. ]
  62. //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx
  63. var atomWords = ['true', 'false', 'nothing', 'empty', 'null']
  64. //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx
  65. var builtinFuncsWords = [
  66. 'abs',
  67. 'array',
  68. 'asc',
  69. 'atn',
  70. 'cbool',
  71. 'cbyte',
  72. 'ccur',
  73. 'cdate',
  74. 'cdbl',
  75. 'chr',
  76. 'cint',
  77. 'clng',
  78. 'cos',
  79. 'csng',
  80. 'cstr',
  81. 'date',
  82. 'dateadd',
  83. 'datediff',
  84. 'datepart',
  85. 'dateserial',
  86. 'datevalue',
  87. 'day',
  88. 'escape',
  89. 'eval',
  90. 'execute',
  91. 'exp',
  92. 'filter',
  93. 'formatcurrency',
  94. 'formatdatetime',
  95. 'formatnumber',
  96. 'formatpercent',
  97. 'getlocale',
  98. 'getobject',
  99. 'getref',
  100. 'hex',
  101. 'hour',
  102. 'inputbox',
  103. 'instr',
  104. 'instrrev',
  105. 'int',
  106. 'fix',
  107. 'isarray',
  108. 'isdate',
  109. 'isempty',
  110. 'isnull',
  111. 'isnumeric',
  112. 'isobject',
  113. 'join',
  114. 'lbound',
  115. 'lcase',
  116. 'left',
  117. 'len',
  118. 'loadpicture',
  119. 'log',
  120. 'ltrim',
  121. 'rtrim',
  122. 'trim',
  123. 'maths',
  124. 'mid',
  125. 'minute',
  126. 'month',
  127. 'monthname',
  128. 'msgbox',
  129. 'now',
  130. 'oct',
  131. 'replace',
  132. 'rgb',
  133. 'right',
  134. 'rnd',
  135. 'round',
  136. 'scriptengine',
  137. 'scriptenginebuildversion',
  138. 'scriptenginemajorversion',
  139. 'scriptengineminorversion',
  140. 'second',
  141. 'setlocale',
  142. 'sgn',
  143. 'sin',
  144. 'space',
  145. 'split',
  146. 'sqr',
  147. 'strcomp',
  148. 'string',
  149. 'strreverse',
  150. 'tan',
  151. 'time',
  152. 'timer',
  153. 'timeserial',
  154. 'timevalue',
  155. 'typename',
  156. 'ubound',
  157. 'ucase',
  158. 'unescape',
  159. 'vartype',
  160. 'weekday',
  161. 'weekdayname',
  162. 'year',
  163. ]
  164. //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx
  165. var builtinConsts = [
  166. 'vbBlack',
  167. 'vbRed',
  168. 'vbGreen',
  169. 'vbYellow',
  170. 'vbBlue',
  171. 'vbMagenta',
  172. 'vbCyan',
  173. 'vbWhite',
  174. 'vbBinaryCompare',
  175. 'vbTextCompare',
  176. 'vbSunday',
  177. 'vbMonday',
  178. 'vbTuesday',
  179. 'vbWednesday',
  180. 'vbThursday',
  181. 'vbFriday',
  182. 'vbSaturday',
  183. 'vbUseSystemDayOfWeek',
  184. 'vbFirstJan1',
  185. 'vbFirstFourDays',
  186. 'vbFirstFullWeek',
  187. 'vbGeneralDate',
  188. 'vbLongDate',
  189. 'vbShortDate',
  190. 'vbLongTime',
  191. 'vbShortTime',
  192. 'vbObjectError',
  193. 'vbOKOnly',
  194. 'vbOKCancel',
  195. 'vbAbortRetryIgnore',
  196. 'vbYesNoCancel',
  197. 'vbYesNo',
  198. 'vbRetryCancel',
  199. 'vbCritical',
  200. 'vbQuestion',
  201. 'vbExclamation',
  202. 'vbInformation',
  203. 'vbDefaultButton1',
  204. 'vbDefaultButton2',
  205. 'vbDefaultButton3',
  206. 'vbDefaultButton4',
  207. 'vbApplicationModal',
  208. 'vbSystemModal',
  209. 'vbOK',
  210. 'vbCancel',
  211. 'vbAbort',
  212. 'vbRetry',
  213. 'vbIgnore',
  214. 'vbYes',
  215. 'vbNo',
  216. 'vbCr',
  217. 'VbCrLf',
  218. 'vbFormFeed',
  219. 'vbLf',
  220. 'vbNewLine',
  221. 'vbNullChar',
  222. 'vbNullString',
  223. 'vbTab',
  224. 'vbVerticalTab',
  225. 'vbUseDefault',
  226. 'vbTrue',
  227. 'vbFalse',
  228. 'vbEmpty',
  229. 'vbNull',
  230. 'vbInteger',
  231. 'vbLong',
  232. 'vbSingle',
  233. 'vbDouble',
  234. 'vbCurrency',
  235. 'vbDate',
  236. 'vbString',
  237. 'vbObject',
  238. 'vbError',
  239. 'vbBoolean',
  240. 'vbVariant',
  241. 'vbDataObject',
  242. 'vbDecimal',
  243. 'vbByte',
  244. 'vbArray',
  245. ]
  246. //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx
  247. var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp']
  248. var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count']
  249. var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit']
  250. var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application']
  251. var aspKnownProperties = [
  252. 'buffer',
  253. 'cachecontrol',
  254. 'charset',
  255. 'contenttype',
  256. 'expires',
  257. 'expiresabsolute',
  258. 'isclientconnected',
  259. 'pics',
  260. 'status', //response
  261. 'clientcertificate',
  262. 'cookies',
  263. 'form',
  264. 'querystring',
  265. 'servervariables',
  266. 'totalbytes', //request
  267. 'contents',
  268. 'staticobjects', //application
  269. 'codepage',
  270. 'lcid',
  271. 'sessionid',
  272. 'timeout', //session
  273. 'scripttimeout',
  274. ] //server
  275. var aspKnownMethods = [
  276. 'addheader',
  277. 'appendtolog',
  278. 'binarywrite',
  279. 'end',
  280. 'flush',
  281. 'redirect', //response
  282. 'binaryread', //request
  283. 'remove',
  284. 'removeall',
  285. 'lock',
  286. 'unlock', //application
  287. 'abandon', //session
  288. 'getlasterror',
  289. 'htmlencode',
  290. 'mappath',
  291. 'transfer',
  292. 'urlencode',
  293. ] //server
  294. var knownWords = knownMethods.concat(knownProperties)
  295. builtinObjsWords = builtinObjsWords.concat(builtinConsts)
  296. if (conf.isASP) {
  297. builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords)
  298. knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties)
  299. }
  300. var keywords = wordRegexp(commonkeywords)
  301. var atoms = wordRegexp(atomWords)
  302. var builtinFuncs = wordRegexp(builtinFuncsWords)
  303. var builtinObjs = wordRegexp(builtinObjsWords)
  304. var known = wordRegexp(knownWords)
  305. var stringPrefixes = '"'
  306. var opening = wordRegexp(openingKeywords)
  307. var middle = wordRegexp(middleKeywords)
  308. var closing = wordRegexp(endKeywords)
  309. var doubleClosing = wordRegexp(['end'])
  310. var doOpening = wordRegexp(['do'])
  311. var noIndentWords = wordRegexp(['on error resume next', 'exit'])
  312. var comment = wordRegexp(['rem'])
  313. function indent(_stream, state) {
  314. state.currentIndent++
  315. }
  316. function dedent(_stream, state) {
  317. state.currentIndent--
  318. }
  319. // tokenizers
  320. function tokenBase(stream, state) {
  321. if (stream.eatSpace()) {
  322. return 'space'
  323. //return null;
  324. }
  325. var ch = stream.peek()
  326. // Handle Comments
  327. if (ch === "'") {
  328. stream.skipToEnd()
  329. return 'comment'
  330. }
  331. if (stream.match(comment)) {
  332. stream.skipToEnd()
  333. return 'comment'
  334. }
  335. // Handle Number Literals
  336. if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) {
  337. var floatLiteral = false
  338. // Floats
  339. if (stream.match(/^\d*\.\d+/i)) {
  340. floatLiteral = true
  341. } else if (stream.match(/^\d+\.\d*/)) {
  342. floatLiteral = true
  343. } else if (stream.match(/^\.\d+/)) {
  344. floatLiteral = true
  345. }
  346. if (floatLiteral) {
  347. // Float literals may be "imaginary"
  348. stream.eat(/J/i)
  349. return 'number'
  350. }
  351. // Integers
  352. var intLiteral = false
  353. // Hex
  354. if (stream.match(/^&H[0-9a-f]+/i)) {
  355. intLiteral = true
  356. }
  357. // Octal
  358. else if (stream.match(/^&O[0-7]+/i)) {
  359. intLiteral = true
  360. }
  361. // Decimal
  362. else if (stream.match(/^[1-9]\d*F?/)) {
  363. // Decimal literals may be "imaginary"
  364. stream.eat(/J/i)
  365. // TODO - Can you have imaginary longs?
  366. intLiteral = true
  367. }
  368. // Zero by itself with no other piece of number.
  369. else if (stream.match(/^0(?![\dx])/i)) {
  370. intLiteral = true
  371. }
  372. if (intLiteral) {
  373. // Integer literals may be "long"
  374. stream.eat(/L/i)
  375. return 'number'
  376. }
  377. }
  378. // Handle Strings
  379. if (stream.match(stringPrefixes)) {
  380. state.tokenize = tokenStringFactory(stream.current())
  381. return state.tokenize(stream, state)
  382. }
  383. // Handle operators and Delimiters
  384. if (stream.match(doubleOperators) || stream.match(singleOperators) || stream.match(wordOperators)) {
  385. return 'operator'
  386. }
  387. if (stream.match(singleDelimiters)) {
  388. return null
  389. }
  390. if (stream.match(brackets)) {
  391. return 'bracket'
  392. }
  393. if (stream.match(noIndentWords)) {
  394. state.doInCurrentLine = true
  395. return 'keyword'
  396. }
  397. if (stream.match(doOpening)) {
  398. indent(stream, state)
  399. state.doInCurrentLine = true
  400. return 'keyword'
  401. }
  402. if (stream.match(opening)) {
  403. if (!state.doInCurrentLine) indent(stream, state)
  404. else state.doInCurrentLine = false
  405. return 'keyword'
  406. }
  407. if (stream.match(middle)) {
  408. return 'keyword'
  409. }
  410. if (stream.match(doubleClosing)) {
  411. dedent(stream, state)
  412. dedent(stream, state)
  413. return 'keyword'
  414. }
  415. if (stream.match(closing)) {
  416. if (!state.doInCurrentLine) dedent(stream, state)
  417. else state.doInCurrentLine = false
  418. return 'keyword'
  419. }
  420. if (stream.match(keywords)) {
  421. return 'keyword'
  422. }
  423. if (stream.match(atoms)) {
  424. return 'atom'
  425. }
  426. if (stream.match(known)) {
  427. return 'variable-2'
  428. }
  429. if (stream.match(builtinFuncs)) {
  430. return 'builtin'
  431. }
  432. if (stream.match(builtinObjs)) {
  433. return 'variable-2'
  434. }
  435. if (stream.match(identifiers)) {
  436. return 'variable'
  437. }
  438. // Handle non-detected items
  439. stream.next()
  440. return ERRORCLASS
  441. }
  442. function tokenStringFactory(delimiter) {
  443. var singleline = delimiter.length == 1
  444. var OUTCLASS = 'string'
  445. return function (stream, state) {
  446. while (!stream.eol()) {
  447. stream.eatWhile(/[^'"]/)
  448. if (stream.match(delimiter)) {
  449. state.tokenize = tokenBase
  450. return OUTCLASS
  451. } else {
  452. stream.eat(/['"]/)
  453. }
  454. }
  455. if (singleline) {
  456. if (parserConf.singleLineStringErrors) {
  457. return ERRORCLASS
  458. } else {
  459. state.tokenize = tokenBase
  460. }
  461. }
  462. return OUTCLASS
  463. }
  464. }
  465. function tokenLexer(stream, state) {
  466. var style = state.tokenize(stream, state)
  467. var current = stream.current()
  468. // Handle '.' connected identifiers
  469. if (current === '.') {
  470. style = state.tokenize(stream, state)
  471. current = stream.current()
  472. if (style && (style.substr(0, 8) === 'variable' || style === 'builtin' || style === 'keyword')) {
  473. //|| knownWords.indexOf(current.substring(1)) > -1) {
  474. if (style === 'builtin' || style === 'keyword') style = 'variable'
  475. if (knownWords.indexOf(current.substr(1)) > -1) style = 'variable-2'
  476. return style
  477. } else {
  478. return ERRORCLASS
  479. }
  480. }
  481. return style
  482. }
  483. var external = {
  484. electricChars: 'dDpPtTfFeE ',
  485. startState: function () {
  486. return {
  487. tokenize: tokenBase,
  488. lastToken: null,
  489. currentIndent: 0,
  490. nextLineIndent: 0,
  491. doInCurrentLine: false,
  492. ignoreKeyword: false,
  493. }
  494. },
  495. token: function (stream, state) {
  496. if (stream.sol()) {
  497. state.currentIndent += state.nextLineIndent
  498. state.nextLineIndent = 0
  499. state.doInCurrentLine = 0
  500. }
  501. var style = tokenLexer(stream, state)
  502. state.lastToken = { style: style, content: stream.current() }
  503. if (style === 'space') style = null
  504. return style
  505. },
  506. indent: function (state, textAfter) {
  507. var trueText = textAfter.replace(/^\s+|\s+$/g, '')
  508. if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit * (state.currentIndent - 1)
  509. if (state.currentIndent < 0) return 0
  510. return state.currentIndent * conf.indentUnit
  511. },
  512. }
  513. return external
  514. })
  515. CodeMirror.defineMIME('text/vbscript', 'vbscript')
  516. })