q.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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('q', function (config) {
  15. var indentUnit = config.indentUnit,
  16. curPunc,
  17. keywords = buildRE([
  18. 'abs',
  19. 'acos',
  20. 'aj',
  21. 'aj0',
  22. 'all',
  23. 'and',
  24. 'any',
  25. 'asc',
  26. 'asin',
  27. 'asof',
  28. 'atan',
  29. 'attr',
  30. 'avg',
  31. 'avgs',
  32. 'bin',
  33. 'by',
  34. 'ceiling',
  35. 'cols',
  36. 'cor',
  37. 'cos',
  38. 'count',
  39. 'cov',
  40. 'cross',
  41. 'csv',
  42. 'cut',
  43. 'delete',
  44. 'deltas',
  45. 'desc',
  46. 'dev',
  47. 'differ',
  48. 'distinct',
  49. 'div',
  50. 'do',
  51. 'each',
  52. 'ej',
  53. 'enlist',
  54. 'eval',
  55. 'except',
  56. 'exec',
  57. 'exit',
  58. 'exp',
  59. 'fby',
  60. 'fills',
  61. 'first',
  62. 'fkeys',
  63. 'flip',
  64. 'floor',
  65. 'from',
  66. 'get',
  67. 'getenv',
  68. 'group',
  69. 'gtime',
  70. 'hclose',
  71. 'hcount',
  72. 'hdel',
  73. 'hopen',
  74. 'hsym',
  75. 'iasc',
  76. 'idesc',
  77. 'if',
  78. 'ij',
  79. 'in',
  80. 'insert',
  81. 'inter',
  82. 'inv',
  83. 'key',
  84. 'keys',
  85. 'last',
  86. 'like',
  87. 'list',
  88. 'lj',
  89. 'load',
  90. 'log',
  91. 'lower',
  92. 'lsq',
  93. 'ltime',
  94. 'ltrim',
  95. 'mavg',
  96. 'max',
  97. 'maxs',
  98. 'mcount',
  99. 'md5',
  100. 'mdev',
  101. 'med',
  102. 'meta',
  103. 'min',
  104. 'mins',
  105. 'mmax',
  106. 'mmin',
  107. 'mmu',
  108. 'mod',
  109. 'msum',
  110. 'neg',
  111. 'next',
  112. 'not',
  113. 'null',
  114. 'or',
  115. 'over',
  116. 'parse',
  117. 'peach',
  118. 'pj',
  119. 'plist',
  120. 'prd',
  121. 'prds',
  122. 'prev',
  123. 'prior',
  124. 'rand',
  125. 'rank',
  126. 'ratios',
  127. 'raze',
  128. 'read0',
  129. 'read1',
  130. 'reciprocal',
  131. 'reverse',
  132. 'rload',
  133. 'rotate',
  134. 'rsave',
  135. 'rtrim',
  136. 'save',
  137. 'scan',
  138. 'select',
  139. 'set',
  140. 'setenv',
  141. 'show',
  142. 'signum',
  143. 'sin',
  144. 'sqrt',
  145. 'ss',
  146. 'ssr',
  147. 'string',
  148. 'sublist',
  149. 'sum',
  150. 'sums',
  151. 'sv',
  152. 'system',
  153. 'tables',
  154. 'tan',
  155. 'til',
  156. 'trim',
  157. 'txf',
  158. 'type',
  159. 'uj',
  160. 'ungroup',
  161. 'union',
  162. 'update',
  163. 'upper',
  164. 'upsert',
  165. 'value',
  166. 'var',
  167. 'view',
  168. 'views',
  169. 'vs',
  170. 'wavg',
  171. 'where',
  172. 'where',
  173. 'while',
  174. 'within',
  175. 'wj',
  176. 'wj1',
  177. 'wsum',
  178. 'xasc',
  179. 'xbar',
  180. 'xcol',
  181. 'xcols',
  182. 'xdesc',
  183. 'xexp',
  184. 'xgroup',
  185. 'xkey',
  186. 'xlog',
  187. 'xprev',
  188. 'xrank',
  189. ]),
  190. E = /[|/&^!+:\\\-*%$=~#;@><,?_\'\"\[\(\]\)\s{}]/
  191. function buildRE(w) {
  192. return new RegExp('^(' + w.join('|') + ')$')
  193. }
  194. function tokenBase(stream, state) {
  195. var sol = stream.sol(),
  196. c = stream.next()
  197. curPunc = null
  198. if (sol)
  199. if (c == '/') return (state.tokenize = tokenLineComment)(stream, state)
  200. else if (c == '\\') {
  201. if (stream.eol() || /\s/.test(stream.peek()))
  202. return stream.skipToEnd(), /^\\\s*$/.test(stream.current()) ? (state.tokenize = tokenCommentToEOF)(stream) : (state.tokenize = tokenBase), 'comment'
  203. else return (state.tokenize = tokenBase), 'builtin'
  204. }
  205. if (/\s/.test(c)) return stream.peek() == '/' ? (stream.skipToEnd(), 'comment') : 'whitespace'
  206. if (c == '"') return (state.tokenize = tokenString)(stream, state)
  207. if (c == '`') return stream.eatWhile(/[A-Za-z\d_:\/.]/), 'symbol'
  208. if (('.' == c && /\d/.test(stream.peek())) || /\d/.test(c)) {
  209. var t = null
  210. stream.backUp(1)
  211. if (
  212. stream.match(/^\d{4}\.\d{2}(m|\.\d{2}([DT](\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)?)?)/) ||
  213. stream.match(/^\d+D(\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)/) ||
  214. stream.match(/^\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?/) ||
  215. stream.match(/^\d+[ptuv]{1}/)
  216. )
  217. t = 'temporal'
  218. else if (
  219. stream.match(/^0[NwW]{1}/) ||
  220. stream.match(/^0x[\da-fA-F]*/) ||
  221. stream.match(/^[01]+[b]{1}/) ||
  222. stream.match(/^\d+[chijn]{1}/) ||
  223. stream.match(/-?\d*(\.\d*)?(e[+\-]?\d+)?(e|f)?/)
  224. )
  225. t = 'number'
  226. return t && (!(c = stream.peek()) || E.test(c)) ? t : (stream.next(), 'error')
  227. }
  228. if (/[A-Za-z]|\./.test(c)) return stream.eatWhile(/[A-Za-z._\d]/), keywords.test(stream.current()) ? 'keyword' : 'variable'
  229. if (/[|/&^!+:\\\-*%$=~#;@><\.,?_\']/.test(c)) return null
  230. if (/[{}\(\[\]\)]/.test(c)) return null
  231. return 'error'
  232. }
  233. function tokenLineComment(stream, state) {
  234. return stream.skipToEnd(), /\/\s*$/.test(stream.current()) ? (state.tokenize = tokenBlockComment)(stream, state) : (state.tokenize = tokenBase), 'comment'
  235. }
  236. function tokenBlockComment(stream, state) {
  237. var f = stream.sol() && stream.peek() == '\\'
  238. stream.skipToEnd()
  239. if (f && /^\\\s*$/.test(stream.current())) state.tokenize = tokenBase
  240. return 'comment'
  241. }
  242. function tokenCommentToEOF(stream) {
  243. return stream.skipToEnd(), 'comment'
  244. }
  245. function tokenString(stream, state) {
  246. var escaped = false,
  247. next,
  248. end = false
  249. while ((next = stream.next())) {
  250. if (next == '"' && !escaped) {
  251. end = true
  252. break
  253. }
  254. escaped = !escaped && next == '\\'
  255. }
  256. if (end) state.tokenize = tokenBase
  257. return 'string'
  258. }
  259. function pushContext(state, type, col) {
  260. state.context = { prev: state.context, indent: state.indent, col: col, type: type }
  261. }
  262. function popContext(state) {
  263. state.indent = state.context.indent
  264. state.context = state.context.prev
  265. }
  266. return {
  267. startState: function () {
  268. return { tokenize: tokenBase, context: null, indent: 0, col: 0 }
  269. },
  270. token: function (stream, state) {
  271. if (stream.sol()) {
  272. if (state.context && state.context.align == null) state.context.align = false
  273. state.indent = stream.indentation()
  274. }
  275. //if (stream.eatSpace()) return null;
  276. var style = state.tokenize(stream, state)
  277. if (style != 'comment' && state.context && state.context.align == null && state.context.type != 'pattern') {
  278. state.context.align = true
  279. }
  280. if (curPunc == '(') pushContext(state, ')', stream.column())
  281. else if (curPunc == '[') pushContext(state, ']', stream.column())
  282. else if (curPunc == '{') pushContext(state, '}', stream.column())
  283. else if (/[\]\}\)]/.test(curPunc)) {
  284. while (state.context && state.context.type == 'pattern') popContext(state)
  285. if (state.context && curPunc == state.context.type) popContext(state)
  286. } else if (curPunc == '.' && state.context && state.context.type == 'pattern') popContext(state)
  287. else if (/atom|string|variable/.test(style) && state.context) {
  288. if (/[\}\]]/.test(state.context.type)) pushContext(state, 'pattern', stream.column())
  289. else if (state.context.type == 'pattern' && !state.context.align) {
  290. state.context.align = true
  291. state.context.col = stream.column()
  292. }
  293. }
  294. return style
  295. },
  296. indent: function (state, textAfter) {
  297. var firstChar = textAfter && textAfter.charAt(0)
  298. var context = state.context
  299. if (/[\]\}]/.test(firstChar)) while (context && context.type == 'pattern') context = context.prev
  300. var closing = context && firstChar == context.type
  301. if (!context) return 0
  302. else if (context.type == 'pattern') return context.col
  303. else if (context.align) return context.col + (closing ? 0 : 1)
  304. else return context.indent + (closing ? 0 : indentUnit)
  305. },
  306. }
  307. })
  308. CodeMirror.defineMIME('text/x-q', 'q')
  309. })