octave.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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('octave', function () {
  15. function wordRegexp(words) {
  16. return new RegExp('^((' + words.join(')|(') + '))\\b')
  17. }
  18. var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]")
  19. var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;\\.]')
  20. var doubleOperators = new RegExp('^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))')
  21. var doubleDelimiters = new RegExp('^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))')
  22. var tripleDelimiters = new RegExp('^((>>=)|(<<=))')
  23. var expressionEnd = new RegExp('^[\\]\\)]')
  24. var identifiers = new RegExp('^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*')
  25. var builtins = wordRegexp([
  26. 'error',
  27. 'eval',
  28. 'function',
  29. 'abs',
  30. 'acos',
  31. 'atan',
  32. 'asin',
  33. 'cos',
  34. 'cosh',
  35. 'exp',
  36. 'log',
  37. 'prod',
  38. 'sum',
  39. 'log10',
  40. 'max',
  41. 'min',
  42. 'sign',
  43. 'sin',
  44. 'sinh',
  45. 'sqrt',
  46. 'tan',
  47. 'reshape',
  48. 'break',
  49. 'zeros',
  50. 'default',
  51. 'margin',
  52. 'round',
  53. 'ones',
  54. 'rand',
  55. 'syn',
  56. 'ceil',
  57. 'floor',
  58. 'size',
  59. 'clear',
  60. 'zeros',
  61. 'eye',
  62. 'mean',
  63. 'std',
  64. 'cov',
  65. 'det',
  66. 'eig',
  67. 'inv',
  68. 'norm',
  69. 'rank',
  70. 'trace',
  71. 'expm',
  72. 'logm',
  73. 'sqrtm',
  74. 'linspace',
  75. 'plot',
  76. 'title',
  77. 'xlabel',
  78. 'ylabel',
  79. 'legend',
  80. 'text',
  81. 'grid',
  82. 'meshgrid',
  83. 'mesh',
  84. 'num2str',
  85. 'fft',
  86. 'ifft',
  87. 'arrayfun',
  88. 'cellfun',
  89. 'input',
  90. 'fliplr',
  91. 'flipud',
  92. 'ismember',
  93. ])
  94. var keywords = wordRegexp([
  95. 'return',
  96. 'case',
  97. 'switch',
  98. 'else',
  99. 'elseif',
  100. 'end',
  101. 'endif',
  102. 'endfunction',
  103. 'if',
  104. 'otherwise',
  105. 'do',
  106. 'for',
  107. 'while',
  108. 'try',
  109. 'catch',
  110. 'classdef',
  111. 'properties',
  112. 'events',
  113. 'methods',
  114. 'global',
  115. 'persistent',
  116. 'endfor',
  117. 'endwhile',
  118. 'printf',
  119. 'sprintf',
  120. 'disp',
  121. 'until',
  122. 'continue',
  123. 'pkg',
  124. ])
  125. // tokenizers
  126. function tokenTranspose(stream, state) {
  127. if (!stream.sol() && stream.peek() === "'") {
  128. stream.next()
  129. state.tokenize = tokenBase
  130. return 'operator'
  131. }
  132. state.tokenize = tokenBase
  133. return tokenBase(stream, state)
  134. }
  135. function tokenComment(stream, state) {
  136. if (stream.match(/^.*%}/)) {
  137. state.tokenize = tokenBase
  138. return 'comment'
  139. }
  140. stream.skipToEnd()
  141. return 'comment'
  142. }
  143. function tokenBase(stream, state) {
  144. // whitespaces
  145. if (stream.eatSpace()) return null
  146. // Handle one line Comments
  147. if (stream.match('%{')) {
  148. state.tokenize = tokenComment
  149. stream.skipToEnd()
  150. return 'comment'
  151. }
  152. if (stream.match(/^[%#]/)) {
  153. stream.skipToEnd()
  154. return 'comment'
  155. }
  156. // Handle Number Literals
  157. if (stream.match(/^[0-9\.+-]/, false)) {
  158. if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) {
  159. stream.tokenize = tokenBase
  160. return 'number'
  161. }
  162. if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) {
  163. return 'number'
  164. }
  165. if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) {
  166. return 'number'
  167. }
  168. }
  169. if (stream.match(wordRegexp(['nan', 'NaN', 'inf', 'Inf']))) {
  170. return 'number'
  171. }
  172. // Handle Strings
  173. var m = stream.match(/^"(?:[^"]|"")*("|$)/) || stream.match(/^'(?:[^']|'')*('|$)/)
  174. if (m) {
  175. return m[1] ? 'string' : 'string error'
  176. }
  177. // Handle words
  178. if (stream.match(keywords)) {
  179. return 'keyword'
  180. }
  181. if (stream.match(builtins)) {
  182. return 'builtin'
  183. }
  184. if (stream.match(identifiers)) {
  185. return 'variable'
  186. }
  187. if (stream.match(singleOperators) || stream.match(doubleOperators)) {
  188. return 'operator'
  189. }
  190. if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) {
  191. return null
  192. }
  193. if (stream.match(expressionEnd)) {
  194. state.tokenize = tokenTranspose
  195. return null
  196. }
  197. // Handle non-detected items
  198. stream.next()
  199. return 'error'
  200. }
  201. return {
  202. startState: function () {
  203. return {
  204. tokenize: tokenBase,
  205. }
  206. },
  207. token: function (stream, state) {
  208. var style = state.tokenize(stream, state)
  209. if (style === 'number' || style === 'variable') {
  210. state.tokenize = tokenTranspose
  211. }
  212. return style
  213. },
  214. lineComment: '%',
  215. fold: 'indent',
  216. }
  217. })
  218. CodeMirror.defineMIME('text/x-octave', 'octave')
  219. })