mscgen.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. // mode(s) for the sequence chart dsl's mscgen, xù and msgenny
  4. // For more information on mscgen, see the site of the original author:
  5. // http://www.mcternan.me.uk/mscgen
  6. //
  7. // This mode for mscgen and the two derivative languages were
  8. // originally made for use in the mscgen_js interpreter
  9. // (https://sverweij.github.io/mscgen_js)
  10. ;(function (mod) {
  11. if (typeof exports == 'object' && typeof module == 'object')
  12. // CommonJS
  13. mod(require('../../lib/codemirror'))
  14. else if (typeof define == 'function' && define.amd)
  15. // AMD
  16. define(['../../lib/codemirror'], mod)
  17. // Plain browser env
  18. else mod(CodeMirror)
  19. })(function (CodeMirror) {
  20. 'use strict'
  21. var languages = {
  22. mscgen: {
  23. keywords: ['msc'],
  24. options: ['hscale', 'width', 'arcgradient', 'wordwraparcs'],
  25. constants: ['true', 'false', 'on', 'off'],
  26. attributes: [
  27. 'label',
  28. 'idurl',
  29. 'id',
  30. 'url',
  31. 'linecolor',
  32. 'linecolour',
  33. 'textcolor',
  34. 'textcolour',
  35. 'textbgcolor',
  36. 'textbgcolour',
  37. 'arclinecolor',
  38. 'arclinecolour',
  39. 'arctextcolor',
  40. 'arctextcolour',
  41. 'arctextbgcolor',
  42. 'arctextbgcolour',
  43. 'arcskip',
  44. ],
  45. brackets: ['\\{', '\\}'], // [ and ] are brackets too, but these get handled in with lists
  46. arcsWords: ['note', 'abox', 'rbox', 'box'],
  47. arcsOthers: ['\\|\\|\\|', '\\.\\.\\.', '---', '--', '<->', '==', '<<=>>', '<=>', '\\.\\.', '<<>>', '::', '<:>', '->', '=>>', '=>', '>>', ':>', '<-', '<<=', '<=', '<<', '<:', 'x-', '-x'],
  48. singlecomment: ['//', '#'],
  49. operators: ['='],
  50. },
  51. xu: {
  52. keywords: ['msc', 'xu'],
  53. options: ['hscale', 'width', 'arcgradient', 'wordwraparcs', 'wordwrapentities', 'watermark'],
  54. constants: ['true', 'false', 'on', 'off', 'auto'],
  55. attributes: [
  56. 'label',
  57. 'idurl',
  58. 'id',
  59. 'url',
  60. 'linecolor',
  61. 'linecolour',
  62. 'textcolor',
  63. 'textcolour',
  64. 'textbgcolor',
  65. 'textbgcolour',
  66. 'arclinecolor',
  67. 'arclinecolour',
  68. 'arctextcolor',
  69. 'arctextcolour',
  70. 'arctextbgcolor',
  71. 'arctextbgcolour',
  72. 'arcskip',
  73. 'title',
  74. 'deactivate',
  75. 'activate',
  76. 'activation',
  77. ],
  78. brackets: ['\\{', '\\}'], // [ and ] are brackets too, but these get handled in with lists
  79. arcsWords: ['note', 'abox', 'rbox', 'box', 'alt', 'else', 'opt', 'break', 'par', 'seq', 'strict', 'neg', 'critical', 'ignore', 'consider', 'assert', 'loop', 'ref', 'exc'],
  80. arcsOthers: ['\\|\\|\\|', '\\.\\.\\.', '---', '--', '<->', '==', '<<=>>', '<=>', '\\.\\.', '<<>>', '::', '<:>', '->', '=>>', '=>', '>>', ':>', '<-', '<<=', '<=', '<<', '<:', 'x-', '-x'],
  81. singlecomment: ['//', '#'],
  82. operators: ['='],
  83. },
  84. msgenny: {
  85. keywords: null,
  86. options: ['hscale', 'width', 'arcgradient', 'wordwraparcs', 'wordwrapentities', 'watermark'],
  87. constants: ['true', 'false', 'on', 'off', 'auto'],
  88. attributes: null,
  89. brackets: ['\\{', '\\}'],
  90. arcsWords: ['note', 'abox', 'rbox', 'box', 'alt', 'else', 'opt', 'break', 'par', 'seq', 'strict', 'neg', 'critical', 'ignore', 'consider', 'assert', 'loop', 'ref', 'exc'],
  91. arcsOthers: ['\\|\\|\\|', '\\.\\.\\.', '---', '--', '<->', '==', '<<=>>', '<=>', '\\.\\.', '<<>>', '::', '<:>', '->', '=>>', '=>', '>>', ':>', '<-', '<<=', '<=', '<<', '<:', 'x-', '-x'],
  92. singlecomment: ['//', '#'],
  93. operators: ['='],
  94. },
  95. }
  96. CodeMirror.defineMode('mscgen', function (_, modeConfig) {
  97. var language = languages[(modeConfig && modeConfig.language) || 'mscgen']
  98. return {
  99. startState: startStateFn,
  100. copyState: copyStateFn,
  101. token: produceTokenFunction(language),
  102. lineComment: '#',
  103. blockCommentStart: '/*',
  104. blockCommentEnd: '*/',
  105. }
  106. })
  107. CodeMirror.defineMIME('text/x-mscgen', 'mscgen')
  108. CodeMirror.defineMIME('text/x-xu', { name: 'mscgen', language: 'xu' })
  109. CodeMirror.defineMIME('text/x-msgenny', { name: 'mscgen', language: 'msgenny' })
  110. function wordRegexpBoundary(pWords) {
  111. return new RegExp('^\\b(?:' + pWords.join('|') + ')\\b', 'i')
  112. }
  113. function wordRegexp(pWords) {
  114. return new RegExp('^(?:' + pWords.join('|') + ')', 'i')
  115. }
  116. function startStateFn() {
  117. return {
  118. inComment: false,
  119. inString: false,
  120. inAttributeList: false,
  121. inScript: false,
  122. }
  123. }
  124. function copyStateFn(pState) {
  125. return {
  126. inComment: pState.inComment,
  127. inString: pState.inString,
  128. inAttributeList: pState.inAttributeList,
  129. inScript: pState.inScript,
  130. }
  131. }
  132. function produceTokenFunction(pConfig) {
  133. return function (pStream, pState) {
  134. if (pStream.match(wordRegexp(pConfig.brackets), true, true)) {
  135. return 'bracket'
  136. }
  137. /* comments */
  138. if (!pState.inComment) {
  139. if (pStream.match(/\/\*[^\*\/]*/, true, true)) {
  140. pState.inComment = true
  141. return 'comment'
  142. }
  143. if (pStream.match(wordRegexp(pConfig.singlecomment), true, true)) {
  144. pStream.skipToEnd()
  145. return 'comment'
  146. }
  147. }
  148. if (pState.inComment) {
  149. if (pStream.match(/[^\*\/]*\*\//, true, true)) pState.inComment = false
  150. else pStream.skipToEnd()
  151. return 'comment'
  152. }
  153. /* strings */
  154. if (!pState.inString && pStream.match(/\"(\\\"|[^\"])*/, true, true)) {
  155. pState.inString = true
  156. return 'string'
  157. }
  158. if (pState.inString) {
  159. if (pStream.match(/[^\"]*\"/, true, true)) pState.inString = false
  160. else pStream.skipToEnd()
  161. return 'string'
  162. }
  163. /* keywords & operators */
  164. if (!!pConfig.keywords && pStream.match(wordRegexpBoundary(pConfig.keywords), true, true)) return 'keyword'
  165. if (pStream.match(wordRegexpBoundary(pConfig.options), true, true)) return 'keyword'
  166. if (pStream.match(wordRegexpBoundary(pConfig.arcsWords), true, true)) return 'keyword'
  167. if (pStream.match(wordRegexp(pConfig.arcsOthers), true, true)) return 'keyword'
  168. if (!!pConfig.operators && pStream.match(wordRegexp(pConfig.operators), true, true)) return 'operator'
  169. if (!!pConfig.constants && pStream.match(wordRegexp(pConfig.constants), true, true)) return 'variable'
  170. /* attribute lists */
  171. if (!pConfig.inAttributeList && !!pConfig.attributes && pStream.match('[', true, true)) {
  172. pConfig.inAttributeList = true
  173. return 'bracket'
  174. }
  175. if (pConfig.inAttributeList) {
  176. if (pConfig.attributes !== null && pStream.match(wordRegexpBoundary(pConfig.attributes), true, true)) {
  177. return 'attribute'
  178. }
  179. if (pStream.match(']', true, true)) {
  180. pConfig.inAttributeList = false
  181. return 'bracket'
  182. }
  183. }
  184. pStream.next()
  185. return 'base'
  186. }
  187. }
  188. })