123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- /*
- This MUMPS Language script was constructed using vbscript.js as a template.
- */
- ;(function (mod) {
- if (typeof exports == 'object' && typeof module == 'object')
- // CommonJS
- mod(require('../../lib/codemirror'))
- else if (typeof define == 'function' && define.amd)
- // AMD
- define(['../../lib/codemirror'], mod)
- // Plain browser env
- else mod(CodeMirror)
- })(function (CodeMirror) {
- 'use strict'
- CodeMirror.defineMode('mumps', function () {
- function wordRegexp(words) {
- return new RegExp('^((' + words.join(')|(') + '))\\b', 'i')
- }
- var singleOperators = new RegExp("^[\\+\\-\\*/&#!_?\\\\<>=\\'\\[\\]]")
- var doubleOperators = new RegExp("^(('=)|(<=)|(>=)|('>)|('<)|([[)|(]])|(^$))")
- var singleDelimiters = new RegExp('^[\\.,:]')
- var brackets = new RegExp('[()]')
- var identifiers = new RegExp('^[%A-Za-z][A-Za-z0-9]*')
- var commandKeywords = [
- 'break',
- 'close',
- 'do',
- 'else',
- 'for',
- 'goto',
- 'halt',
- 'hang',
- 'if',
- 'job',
- 'kill',
- 'lock',
- 'merge',
- 'new',
- 'open',
- 'quit',
- 'read',
- 'set',
- 'tcommit',
- 'trollback',
- 'tstart',
- 'use',
- 'view',
- 'write',
- 'xecute',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'q',
- 'r',
- 's',
- 'tc',
- 'tro',
- 'ts',
- 'u',
- 'v',
- 'w',
- 'x',
- ]
- // The following list includes intrinsic functions _and_ special variables
- var intrinsicFuncsWords = [
- '\\$ascii',
- '\\$char',
- '\\$data',
- '\\$ecode',
- '\\$estack',
- '\\$etrap',
- '\\$extract',
- '\\$find',
- '\\$fnumber',
- '\\$get',
- '\\$horolog',
- '\\$io',
- '\\$increment',
- '\\$job',
- '\\$justify',
- '\\$length',
- '\\$name',
- '\\$next',
- '\\$order',
- '\\$piece',
- '\\$qlength',
- '\\$qsubscript',
- '\\$query',
- '\\$quit',
- '\\$random',
- '\\$reverse',
- '\\$select',
- '\\$stack',
- '\\$test',
- '\\$text',
- '\\$translate',
- '\\$view',
- '\\$x',
- '\\$y',
- '\\$a',
- '\\$c',
- '\\$d',
- '\\$e',
- '\\$ec',
- '\\$es',
- '\\$et',
- '\\$f',
- '\\$fn',
- '\\$g',
- '\\$h',
- '\\$i',
- '\\$j',
- '\\$l',
- '\\$n',
- '\\$na',
- '\\$o',
- '\\$p',
- '\\$q',
- '\\$ql',
- '\\$qs',
- '\\$r',
- '\\$re',
- '\\$s',
- '\\$st',
- '\\$t',
- '\\$tr',
- '\\$v',
- '\\$z',
- ]
- var intrinsicFuncs = wordRegexp(intrinsicFuncsWords)
- var command = wordRegexp(commandKeywords)
- function tokenBase(stream, state) {
- if (stream.sol()) {
- state.label = true
- state.commandMode = 0
- }
- // The <space> character has meaning in MUMPS. Ignoring consecutive
- // spaces would interfere with interpreting whether the next non-space
- // character belongs to the command or argument context.
- // Examine each character and update a mode variable whose interpretation is:
- // >0 => command 0 => argument <0 => command post-conditional
- var ch = stream.peek()
- if (ch == ' ' || ch == '\t') {
- // Pre-process <space>
- state.label = false
- if (state.commandMode == 0) state.commandMode = 1
- else if (state.commandMode < 0 || state.commandMode == 2) state.commandMode = 0
- } else if (ch != '.' && state.commandMode > 0) {
- if (ch == ':') state.commandMode = -1
- // SIS - Command post-conditional
- else state.commandMode = 2
- }
- // Do not color parameter list as line tag
- if (ch === '(' || ch === '\u0009') state.label = false
- // MUMPS comment starts with ";"
- if (ch === ';') {
- stream.skipToEnd()
- return 'comment'
- }
- // Number Literals // SIS/RLM - MUMPS permits canonic number followed by concatenate operator
- if (stream.match(/^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/)) return 'number'
- // Handle Strings
- if (ch == '"') {
- if (stream.skipTo('"')) {
- stream.next()
- return 'string'
- } else {
- stream.skipToEnd()
- return 'error'
- }
- }
- // Handle operators and Delimiters
- if (stream.match(doubleOperators) || stream.match(singleOperators)) return 'operator'
- // Prevents leading "." in DO block from falling through to error
- if (stream.match(singleDelimiters)) return null
- if (brackets.test(ch)) {
- stream.next()
- return 'bracket'
- }
- if (state.commandMode > 0 && stream.match(command)) return 'variable-2'
- if (stream.match(intrinsicFuncs)) return 'builtin'
- if (stream.match(identifiers)) return 'variable'
- // Detect dollar-sign when not a documented intrinsic function
- // "^" may introduce a GVN or SSVN - Color same as function
- if (ch === '$' || ch === '^') {
- stream.next()
- return 'builtin'
- }
- // MUMPS Indirection
- if (ch === '@') {
- stream.next()
- return 'string-2'
- }
- if (/[\w%]/.test(ch)) {
- stream.eatWhile(/[\w%]/)
- return 'variable'
- }
- // Handle non-detected items
- stream.next()
- return 'error'
- }
- return {
- startState: function () {
- return {
- label: false,
- commandMode: 0,
- }
- },
- token: function (stream, state) {
- var style = tokenBase(stream, state)
- if (state.label) return 'tag'
- return style
- },
- }
- })
- CodeMirror.defineMIME('text/x-mumps', 'mumps')
- })
|