vb.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. ;(function (mod) {
  4. if (typeof exports == 'object' && typeof module == 'object')
  5. // CommonJS
  6. mod(require('../../lib/codemirror'))
  7. else if (typeof define == 'function' && define.amd)
  8. // AMD
  9. define(['../../lib/codemirror'], mod)
  10. // Plain browser env
  11. else mod(CodeMirror)
  12. })(function (CodeMirror) {
  13. 'use strict'
  14. CodeMirror.defineMode('vb', function (conf, parserConf) {
  15. var ERRORCLASS = 'error'
  16. function wordRegexp(words) {
  17. return new RegExp('^((' + words.join(')|(') + '))\\b', 'i')
  18. }
  19. var singleOperators = new RegExp('^[\\+\\-\\*/%&\\\\|\\^~<>!]')
  20. var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]')
  21. var doubleOperators = new RegExp('^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))')
  22. var doubleDelimiters = new RegExp('^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))')
  23. var tripleDelimiters = new RegExp('^((//=)|(>>=)|(<<=)|(\\*\\*=))')
  24. var identifiers = new RegExp('^[_A-Za-z][_A-Za-z0-9]*')
  25. var openingKeywords = ['class', 'module', 'sub', 'enum', 'select', 'while', 'if', 'function', 'get', 'set', 'property', 'try', 'structure', 'synclock', 'using', 'with']
  26. var middleKeywords = ['else', 'elseif', 'case', 'catch', 'finally']
  27. var endKeywords = ['next', 'loop']
  28. var operatorKeywords = ['and', 'andalso', 'or', 'orelse', 'xor', 'in', 'not', 'is', 'isnot', 'like']
  29. var wordOperators = wordRegexp(operatorKeywords)
  30. var commonKeywords = [
  31. '#const',
  32. '#else',
  33. '#elseif',
  34. '#end',
  35. '#if',
  36. '#region',
  37. 'addhandler',
  38. 'addressof',
  39. 'alias',
  40. 'as',
  41. 'byref',
  42. 'byval',
  43. 'cbool',
  44. 'cbyte',
  45. 'cchar',
  46. 'cdate',
  47. 'cdbl',
  48. 'cdec',
  49. 'cint',
  50. 'clng',
  51. 'cobj',
  52. 'compare',
  53. 'const',
  54. 'continue',
  55. 'csbyte',
  56. 'cshort',
  57. 'csng',
  58. 'cstr',
  59. 'cuint',
  60. 'culng',
  61. 'cushort',
  62. 'declare',
  63. 'default',
  64. 'delegate',
  65. 'dim',
  66. 'directcast',
  67. 'each',
  68. 'erase',
  69. 'error',
  70. 'event',
  71. 'exit',
  72. 'explicit',
  73. 'false',
  74. 'for',
  75. 'friend',
  76. 'gettype',
  77. 'goto',
  78. 'handles',
  79. 'implements',
  80. 'imports',
  81. 'infer',
  82. 'inherits',
  83. 'interface',
  84. 'isfalse',
  85. 'istrue',
  86. 'lib',
  87. 'me',
  88. 'mod',
  89. 'mustinherit',
  90. 'mustoverride',
  91. 'my',
  92. 'mybase',
  93. 'myclass',
  94. 'namespace',
  95. 'narrowing',
  96. 'new',
  97. 'nothing',
  98. 'notinheritable',
  99. 'notoverridable',
  100. 'of',
  101. 'off',
  102. 'on',
  103. 'operator',
  104. 'option',
  105. 'optional',
  106. 'out',
  107. 'overloads',
  108. 'overridable',
  109. 'overrides',
  110. 'paramarray',
  111. 'partial',
  112. 'private',
  113. 'protected',
  114. 'public',
  115. 'raiseevent',
  116. 'readonly',
  117. 'redim',
  118. 'removehandler',
  119. 'resume',
  120. 'return',
  121. 'shadows',
  122. 'shared',
  123. 'static',
  124. 'step',
  125. 'stop',
  126. 'strict',
  127. 'then',
  128. 'throw',
  129. 'to',
  130. 'true',
  131. 'trycast',
  132. 'typeof',
  133. 'until',
  134. 'until',
  135. 'when',
  136. 'widening',
  137. 'withevents',
  138. 'writeonly',
  139. ]
  140. var commontypes = [
  141. 'object',
  142. 'boolean',
  143. 'char',
  144. 'string',
  145. 'byte',
  146. 'sbyte',
  147. 'short',
  148. 'ushort',
  149. 'int16',
  150. 'uint16',
  151. 'integer',
  152. 'uinteger',
  153. 'int32',
  154. 'uint32',
  155. 'long',
  156. 'ulong',
  157. 'int64',
  158. 'uint64',
  159. 'decimal',
  160. 'single',
  161. 'double',
  162. 'float',
  163. 'date',
  164. 'datetime',
  165. 'intptr',
  166. 'uintptr',
  167. ]
  168. var keywords = wordRegexp(commonKeywords)
  169. var types = wordRegexp(commontypes)
  170. var stringPrefixes = '"'
  171. var opening = wordRegexp(openingKeywords)
  172. var middle = wordRegexp(middleKeywords)
  173. var closing = wordRegexp(endKeywords)
  174. var doubleClosing = wordRegexp(['end'])
  175. var doOpening = wordRegexp(['do'])
  176. var indentInfo = null
  177. CodeMirror.registerHelper('hintWords', 'vb', openingKeywords.concat(middleKeywords).concat(endKeywords).concat(operatorKeywords).concat(commonKeywords).concat(commontypes))
  178. function indent(_stream, state) {
  179. state.currentIndent++
  180. }
  181. function dedent(_stream, state) {
  182. state.currentIndent--
  183. }
  184. // tokenizers
  185. function tokenBase(stream, state) {
  186. if (stream.eatSpace()) {
  187. return null
  188. }
  189. var ch = stream.peek()
  190. // Handle Comments
  191. if (ch === "'") {
  192. stream.skipToEnd()
  193. return 'comment'
  194. }
  195. // Handle Number Literals
  196. if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) {
  197. var floatLiteral = false
  198. // Floats
  199. if (stream.match(/^\d*\.\d+F?/i)) {
  200. floatLiteral = true
  201. } else if (stream.match(/^\d+\.\d*F?/)) {
  202. floatLiteral = true
  203. } else if (stream.match(/^\.\d+F?/)) {
  204. floatLiteral = true
  205. }
  206. if (floatLiteral) {
  207. // Float literals may be "imaginary"
  208. stream.eat(/J/i)
  209. return 'number'
  210. }
  211. // Integers
  212. var intLiteral = false
  213. // Hex
  214. if (stream.match(/^&H[0-9a-f]+/i)) {
  215. intLiteral = true
  216. }
  217. // Octal
  218. else if (stream.match(/^&O[0-7]+/i)) {
  219. intLiteral = true
  220. }
  221. // Decimal
  222. else if (stream.match(/^[1-9]\d*F?/)) {
  223. // Decimal literals may be "imaginary"
  224. stream.eat(/J/i)
  225. // TODO - Can you have imaginary longs?
  226. intLiteral = true
  227. }
  228. // Zero by itself with no other piece of number.
  229. else if (stream.match(/^0(?![\dx])/i)) {
  230. intLiteral = true
  231. }
  232. if (intLiteral) {
  233. // Integer literals may be "long"
  234. stream.eat(/L/i)
  235. return 'number'
  236. }
  237. }
  238. // Handle Strings
  239. if (stream.match(stringPrefixes)) {
  240. state.tokenize = tokenStringFactory(stream.current())
  241. return state.tokenize(stream, state)
  242. }
  243. // Handle operators and Delimiters
  244. if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
  245. return null
  246. }
  247. if (stream.match(doubleOperators) || stream.match(singleOperators) || stream.match(wordOperators)) {
  248. return 'operator'
  249. }
  250. if (stream.match(singleDelimiters)) {
  251. return null
  252. }
  253. if (stream.match(doOpening)) {
  254. indent(stream, state)
  255. state.doInCurrentLine = true
  256. return 'keyword'
  257. }
  258. if (stream.match(opening)) {
  259. if (!state.doInCurrentLine) indent(stream, state)
  260. else state.doInCurrentLine = false
  261. return 'keyword'
  262. }
  263. if (stream.match(middle)) {
  264. return 'keyword'
  265. }
  266. if (stream.match(doubleClosing)) {
  267. dedent(stream, state)
  268. dedent(stream, state)
  269. return 'keyword'
  270. }
  271. if (stream.match(closing)) {
  272. dedent(stream, state)
  273. return 'keyword'
  274. }
  275. if (stream.match(types)) {
  276. return 'keyword'
  277. }
  278. if (stream.match(keywords)) {
  279. return 'keyword'
  280. }
  281. if (stream.match(identifiers)) {
  282. return 'variable'
  283. }
  284. // Handle non-detected items
  285. stream.next()
  286. return ERRORCLASS
  287. }
  288. function tokenStringFactory(delimiter) {
  289. var singleline = delimiter.length == 1
  290. var OUTCLASS = 'string'
  291. return function (stream, state) {
  292. while (!stream.eol()) {
  293. stream.eatWhile(/[^'"]/)
  294. if (stream.match(delimiter)) {
  295. state.tokenize = tokenBase
  296. return OUTCLASS
  297. } else {
  298. stream.eat(/['"]/)
  299. }
  300. }
  301. if (singleline) {
  302. if (parserConf.singleLineStringErrors) {
  303. return ERRORCLASS
  304. } else {
  305. state.tokenize = tokenBase
  306. }
  307. }
  308. return OUTCLASS
  309. }
  310. }
  311. function tokenLexer(stream, state) {
  312. var style = state.tokenize(stream, state)
  313. var current = stream.current()
  314. // Handle '.' connected identifiers
  315. if (current === '.') {
  316. style = state.tokenize(stream, state)
  317. if (style === 'variable') {
  318. return 'variable'
  319. } else {
  320. return ERRORCLASS
  321. }
  322. }
  323. var delimiter_index = '[({'.indexOf(current)
  324. if (delimiter_index !== -1) {
  325. indent(stream, state)
  326. }
  327. if (indentInfo === 'dedent') {
  328. if (dedent(stream, state)) {
  329. return ERRORCLASS
  330. }
  331. }
  332. delimiter_index = '])}'.indexOf(current)
  333. if (delimiter_index !== -1) {
  334. if (dedent(stream, state)) {
  335. return ERRORCLASS
  336. }
  337. }
  338. return style
  339. }
  340. var external = {
  341. electricChars: 'dDpPtTfFeE ',
  342. startState: function () {
  343. return {
  344. tokenize: tokenBase,
  345. lastToken: null,
  346. currentIndent: 0,
  347. nextLineIndent: 0,
  348. doInCurrentLine: false,
  349. }
  350. },
  351. token: function (stream, state) {
  352. if (stream.sol()) {
  353. state.currentIndent += state.nextLineIndent
  354. state.nextLineIndent = 0
  355. state.doInCurrentLine = 0
  356. }
  357. var style = tokenLexer(stream, state)
  358. state.lastToken = { style: style, content: stream.current() }
  359. return style
  360. },
  361. indent: function (state, textAfter) {
  362. var trueText = textAfter.replace(/^\s+|\s+$/g, '')
  363. if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit * (state.currentIndent - 1)
  364. if (state.currentIndent < 0) return 0
  365. return state.currentIndent * conf.indentUnit
  366. },
  367. lineComment: "'",
  368. }
  369. return external
  370. })
  371. CodeMirror.defineMIME('text/x-vb', 'vb')
  372. })